As I mentioned in the last issue, I was hoping to get things into a production environment this weekend. I spent a lot of time yesterday and today doing just that, but now it’s all connected and working together.
So let’s take a look at what’s what.
First up, the landing page. This was already deployed as a static React site on render.com. Nothing fancy, just a simple site I can tweak as needed. But I did make a change to actually make it live at whoshouldIunfollow.com. This was a simple DNS change to point the domain to the one that Render creates for me. They had nice instructions and that was pretty simple. Still a little bit of work to do on that landing page as there’s still a bunch of template stuff I need to remove/change/replace, but it’s there.
Next up, the API layer. As I mentioned before, this is going to be pretty important to everything I’m doing with Feather, so I decided to have it live as a subdomain under that. Again, I deployed through 2wqsx, but this one was a bit more complex. It has a bunch of pieces that needed deployed. The main part was a Django app that connected to a Postgres database. Those two pieces were fairly simple. I had previously tested a deployment on Render with this architecture and there’s a pretty decent guide to deploying Django apps on Render.
I did have one issue that took me an embarrassing amount of time to solve though. I was really struggling with getting the static files to work the way they were supposed to. At one point, I decided to just rip out the static files part, but then quickly realized that made the nice admin panel that comes with Django pretty much unusable.
So I went over it and over it, trying to figure out what I was doing wrong. The answer: I had DEBUG always set to true. So the production settings, the ones that made sure the deployment worked on Render, were never firing and the static files setup was broken. But I did eventually get that figured out.
And then the rest of it was getting Celery added in. This was pretty simple, but did require a few pieces:
A Redis instance - pretty straightforward to deploy on Render. Very similar to setting up a Postgres instance.
The worker - this is the server that actually runs the celery tasks
The scheduler - this is the part used to schedule tasks (not currently using, but will be soon enough)
Flower - this is another server that gives you a nice dashboard for monitoring what’s going on within Celery.
So three more servers and another database. Once all this was finally working, I started working on the next bit: the “frontend”.
I have that in quotes because, as a BlitzJS project, it’s actually more than a frontend. It’s an entire stack that has a database and a backend layer that all just work together. But for all intents and purposes, it’s the frontend. This database isn’t going to hold much, other than user information.
As with Feather, I decided to deploy this via Flightcontrol, the deployment service that’s being built by the guy who developed Blitz. It’s come quite a long way since I first started as one of their first users, and that was really cool to see!
I did have a couple of issues getting it to work, but luckily, the team was there to help. Turns out, you can only have 5 VPCs per region by default on AWS and I was at my limit. This broke the deployment process for me and they had a bug where that error wasn’t visible. But they quickly answered when I posted in the Discord and got the bug fixed shortly afterward. It took me longer to figure out how to remove a bunch of old things I had started configuring in AWS than it did for them to fix that bug.
It was a bit funny too: I posted a little bit on Twitter about what I was doing and tagged Brandon, the founder of Blitz and Flightcontrol. He liked my tweets and a few minutes later, sent me a DM. He was curious why I was deploying part of my stack on Render and part on Flightcontrol. So I told him the simplest answer: that was the easiest way for me to do it. Sure, I could set up Docker images for each piece of my backend and figure out exactly how to connect it up, and deploy it via Flightcontrol, or I could follow the documentation by Render, use a really simple render.yaml file, and deploy my whole stack quickly.
Since I’m fairly new to that whole stack and haven’t deployed anything like that, I didn’t want to spend more time fighting that than I needed to. I wanted to get up and running as quickly as possible and this was the route that gave me that. He thanked me for the feedback and agreed that that is how he would do it as well. But he also mentioned that eventually, they are going to have an easy setup for Redis and workers as well, so I’ll likely move everything over to Flightcontrol at some point. He and his team have been incredible to work with and I love what they are doing. I want to support them in their mission to make everything a lot easier. It certainly has made my life easier. Just check out this issue if you missed out on why I ended up coming back to Blitz for my frontend work:
That went live last night and this morning, I set up the DNS to point it to app.whoshouldIunfollow.com. If you visit that, you’ll see a mostly generic Blitz starter page, but there is a link at the bottom that you can use to login with Twitter. There’s also a route that you can use that makes a backend call to the Django API, but the database isn’t populated with any data yet so it never returns anything.
I had a bunch of fun trying to connect the Blitz app with my API. I was getting all sorts of errors and I couldn’t figure out what was happening. Basically, any time I tried to make an API call, the entire Blitz app would completely crash and I’d have to bounce it.
Turns out, I was doing a few things wrong with my error handling. But the thing that tripped me up was I was trying to deconstruct the error parameter in my catch block of the promise.
So here's my code block that makes the API call:
await axios
.post(
URL,
{
token: user.twitterApiToken,
twitter_id: twitterId,
logged_in_user_id: user.twitterId,
},
{
headers: {
Authorization: `Api-Key ${process.env.BACKEND_API_KEY}`,
"Content-Type": "application/json",
},
}
)
.then(({ data }) => {
console.log(data)
})
.catch((err) => {
console.log(err)
error = err
})
That’s the working version. Here’s the one with the problem:
await axios
.post(
URL,
{
token: user.twitterApiToken,
twitter_id: twitterId,
logged_in_user_id: user.twitterId,
},
{
headers: {
Authorization: `Api-Key ${process.env.BACKEND_API_KEY}`,
"Content-Type": "application/json",
},
}
)
.then(({ data }) => {
console.log(data)
})
.catch(({ err }) => {
console.log(err)
error = err
})
I wasn’t getting anything logged and I couldn’t figure out why. Turns out, those curly braces around ‘err’ were the issue. That was trying to pull out the ‘err’ property of the error and since that didn’t exist, it just kept logging null.
That was one of those hidden errors that are always fun to diagnose. I don’t remember adding them in specifically, I think I just copied it from the then call which pulls the data parameter out. Once I figured that out, I was able to realize that I was getting a 400 from the backend. A little bit of investigating later and I realized I didn’t have the ‘api.feathercrm.io’ added to the ALLOWED_HOSTS list on Django. So it wasn’t allowing me to call anything from that URL. Fixed that and suddenly everything started working!
So now, I’m setting up a list of things that still need to be completed. Then I’ll build a quick Kanban board in Notion and start picking things off throughout the week. Still going to shoot for a week from tomorrow to be live and testing with some beta users and then hopefully a Product Hunt launch the week after. That’s a pretty aggressive time frame, but will hopefully help me prioritize the work that moves the needle the most.
Lesson from this weekend: the little things matter and are really easy to miss. They end up taking more time than you plan for. It’s really easy to overlook things, especially as you gain more experience, because you don’t expect to make those kinds of errors.
And yet, you do. That’s part of software development. Just have to roll with the punches and figure out one problem at a time. Eventually, you’ll get it figured out and working.
Hope you had a great weekend! On a non-programming note, I did plan my weekend around the Columbus Crew game. Which had weather delay after weather delay and eventually started at the same time that I had agreed to take my son to go see Dr. Strange 2. So I completely missed the game, which was apparently a good thing as they ended up losing again. But the movie was excellent and my son loved it! Ok, I loved it too. Dr Strange is one of my favorite Marvel characters.