Building JuniperCity.com
Monday, November 4, 2019
So I started a new thing: Juniper City.
While I also want to shamelessly plug it. I also want to talk about the tech in it and decisions that were made.
The What
Juniper City is a place to post and manage your events. The idea is to get away from having to use Facebook and making it really easy for people not on the platform to use.
There’s some core concepts I wanted to keep with.
- No account creation.
- Invite people where they are.
- Usable over email.
No account creation
Technically you do create an account but I wanted it to be easy. We don’t have passwords. You put in your email and we send you a one time password to login.
The goal is very little friction for people you invite to use the site. So when you do invite people they get a link with a key in the query params. That key logs them in. They didn’t have to think about anything, and no redirect to do what they wanted to do.
Invite people where they are.
I wanted this to be something you could use for your entire family or group. Not everyone has Facebook or any number of social accounts. But almost everyone has an email or can get texts.
You invite people not by a username we have, but their email or phone. In the background if we don’t have them on file we will make a user for them. Like mentioned before we have links that auto log them in, but since we made a user and have no passwords, they can log in at anytime without it.
Usable over email
I didn’t quite launch with everything I wanted for this part. We currently send out invites over email but I wanted to do more.
So coming soon the future, you will be able to email Juniper City to create your event without ever visiting our site.
The people in the to field of the email get invited. You never have to even copy and paste over emails this way. Your email client is now our fronted client.
The big goal is trying to make useful open tools.
The How
So how was it built?
So the stack for the site is:
- Docker
- Nodejs
- Hapi
- Postgres
- Redis
- Stimulusjs
The entire stack is one monolith. No micro-services and we use server side rendering. It makes it simple to program for and deploy.
Frontend
This is a really simple frontend and we use a really simple framework. I’ve talked about Stimulusjs in a lot in my other posts so I won’t belabor the point.
We use ejs for server side templates. (Though I am thinking of switching to Nunjucks it just seems nicer).
The total JavaScript bundle in production is around 350 kb and 65 kb minified. That’s tiny. We don’t do a lot in the frontend so why bloat it?
All our frontend is doing is just a few AJAX requests as well as hiding and showing things. Stimulus really does help keep this organized.
Keeping the site server side rendered with minimal JavaScript give a big advantage. Once we respond from the server, we’re serving up blazing fast pages. Taking advantage of Turbolinks as well to make it feel single page. Can you get similar results with React or Vue? Yes, but it’s not as EASY.
From the styling end we use Tailwindcss it’s just awesome. Worth checking out. Makes putting together designs an absolute breeze.
Tools
For bundling we use Parcel. I don’t have a very strong opinion on this but parcel is very near it’s promise of zero config.
In production to keep the CSS small (tailwind has a lot of unused css) we use PurgeCSS. This pushes our css to 7.5 kb and 2 kb gziped.
Server side.
The stack here is pretty standard and easy.
- Nodejs as the application logic.
- Postgres as our database.
- Redis for job queuing.
We integrate with Postmark for email delivery. For SMS delivery we use Textbelt. Also note that it will only send texts in the US.
I found Textbelt after a large amount of searching.
Some other options I didn’t like.
- Twilio
- Wow is this complex. Do I have to buy a number? How can I JUST send a text
- AWS SNS
- Simple and cheap but I was searching to get away from using AWS.
Queues
We make use of queues and task workers. Take a look at this thing I wrote for an in depth about it.
Anytime we want to send an email or a text, we put it into a queue. Incoming web hooks? Queues. In essence anything you don’t want to do right now. Queue it baby! The great thing is our current system has great support for running things at a later date as well. Things like cron jobs fit this use case.
Deploying
We package the server and frontend code in a docker container (Docker is so great).
Right now we server all our assets from the server. For the future we’ll likely move static assets (CSS, JS, images) to a CDN. It’s good enough right now.
Hosting is on Digital Ocean. Amazon is kinda evil so I wanted to try something else. What Digital Ocean lacks in configuration and power it makes up for in simplicity.
If you couldn’t tell simplicity is a core tenant of this entire project.
- We Build the project using docker.
- Upload the image to a registry.
Deploy with docker compose.
- I learned about this option in compose
-H "ssh://user@server"
. As long as you have SSH access to your remote machine it’s the same as running the commands on your own machine. In the past I would copy the env files and compose files over to the remote machine as part of the build step. Using this new method you don’t have to do ANY of that. docker-compose -H "ssh://user@server" pull image
docker-compose -H "ssh://user@server" up -d
- I learned about this option in compose
Again really simple.
Conclusion
I hope you liked that overview of what Juniper City is. Maybe you can find a use for it!