Moved HelloWebBooks.com from a static site generator to full Django site

This website got a big update!

This is where I would usually show a screenshot of the new website except, in this case, the changes are 99% invisible.

I created this website way back in the day using a static site generator named Cactus, which worked okay for what I wanted to do. Back then, my concerns were more about time to get things launched and making things as easy as possible to deploy, since I was more concerned about getting the books released.

But a staticly-generated site has some major limitations and I started to feel like my hands were tied behind my back. Blogging became more of a chore. People often asked me for Wes Bos-style discounts (price parity, selling my courses for cheaper based on country), and that’s harder to build without a backend. I’m also paying a lot for various services, including a video host, but that service doesn’t have a way to insert a “buy” button on my own website, so I’m using another service for that, meaning that people who buy my books tend to create two accounts, which is plainly annoying.

HelloWebBooks.com moved from a static site generator to full Django

If I wanted to address any of the above, I needed to migrate this website to a full Django system. The hardest part was figuring out what to do with the static files I had for the blog. For WeddingLovely, my startup, I used Wordpress for the blog and it runs on a completely different system, and I here I hoped for better integration between my site and my blog.

Blog moved from static files to Wagtail

I ended up using Wagtail. There actually wasn’t a ton of thought put into this — I’ve heard a lot about Wagtail from my friends in Django, and I missed Wordpress-like features for blogging, like scheduling posts. This whole new website started out as an experiment at home that I didn’t anticipate finishing, just a test to see if it was doable to run Wagtail for just the blog portion of my website and easily migrate my files over. I managed to get everything looking exactly the same as it did before, locally, using Wagtail for everything under /news/, so I decided to plow forward with launching the site.

For the website/book portion of the website, I haven’t used the backend at all (files are still just static files with no database involvement), but at some point I’m going to start building some fun stuff.

I learned a lot about server administration

Doing all this was also a fun excuse to finally get more comfortable with setting up servers. In the past, for complicated deploys, I usually whined for my husband (hi Andrey) to help me out since he’s really awesome like that. But it was time for me to fly on my own.

The following is not a tutorial, just the process I went through:

DigitalOcean

I was doing all of this without a deadline, so I felt comfortable trying a few different server solutions. I started with DigitalOcean. I mainly used this tutorial, but ran into issues at the point where tutorial walks you though creating Django site from scratch within the server, not pushing an existing local Django site (which I find kind of silly, since who does that.)

I found some other tutorials which walked me through using git on the server to pull my site from a public repo. Here’s where I spent a few hours using GitLab, and then just falling back to GitHub because I’m lazy and I already have accounts there, then trying not to be lazy and moving all my private into to environment variables, then forgetting about git history when I pushed to the public GitHub repo, then scrubbing everything and updating all my passwords and secret keys and starting over. Phew. That was fun.

Finally, my site was was pushed into DO, I went back to the original tutorial to set up nginx and gunicorn, and went through a few hours of finding an error, fixing an error, finding a new error, fixing the new error, etc, etc.

I finally reached a point where I thought, “Well, this is why Heroku exists, maybe I should use that instead.” Not to mention I need to fix something within the Hello Web App book anyways that in (coming this week), so I thought it would be good for me to reacquaint myself with Heroku.

Heroku

I popped over to Heroku and tried going through the process of deploying the site there. It ended up being more frustrating because I was getting some of the same errors I got with DO, but it was harder for me to figure out how to fix because everything is abstracted away. Heroku’s documentation also drove me up the wall (especially after using some of DO’s documentation) so after a day of frustration, I decided that I was going to stick with DO. Oh, and deployment is sloooow.

I recommend Heroku for my Hello Web App readers precisely because I don’t want to burden new devs with all that server mumbo jumbo, and will continue to do so. But for me, I like having more control since I’m a bit farther along in my dev-itude.

DigitalOcean again

Back I went to DO today, fresh and ready to fix the last few errors I ran into. One of my big issues was that I filled out my local database with my blog posts, thinking, “Oh, Django’s dumpdata and loaddata looks easy, I’ll just do that.” I should have known better — postgres and Wagtail were not playing nicely and it took me a few hours to debug the issues and get my data loaded into my production database (still with errors, but nothing that stops me from working.) I learned a lot here about how Wagtail works and learned about all the things I don’t like about it, but hey, going to keep using it for now.

Fabric for deployment

One last technology that I’ve never used. Since I ditched Heroku, I needed an easier way to deploy my site after making local changes, and was recommended creating a Fabric file (fabfile) to run the commands I was doing manually (ssh into the server, change to the correct directory, running git pull, then restarting gunicorn.)

Things got tricky since Fabric has moved to a new version with different commands and most tutorials references the first version, but after a few hours I figured out how to create a very basic fabfile for deployment.

Setting up scheduled posts with systemd timers

I’m familiar with cron (and have a whole chapter on Django management commands and cron in my Hello Web App: Intermediate Concepts book) so I started setting it up before I realized I would have issues running the publish_scheduled_posts Wagtail command since my settings files need to have environment variables set and I didn't (obviously) want to hard code those.

Andrey pointed me in the direction of using systemd timers (Here’s the best tutorial I found on the subject.), which would have been just great had I not named my timer cron.timer and guess what! That’s already used by the system and nothing would happen and I tore my hair out for hours before I renamed my files and then they worked. Don’t be clever with names, folks.

Updates to the current site

I didn’t change much on the front-end. The main visible difference now is that the blog posts in the blog have multiple categories, rather than being limited to just one.

Other than that, the site is probably slower, since it’s not static. Funny that I spent days making these changes only to make the site slower. 😅

Upcoming

  1. Hopefully I’ll blog more. I love being able to schedule posts in Wordpress, so I can set up good content at my own pace and schedule things to go live at an appropriate time, and Wagtail appears to be able to do this. I say “appears” because I actually haven’t tested this until this blog post.
  2. A better shopping cart system. I’ve been using Gumroad for the last three or so years, but have been itching to roll my own system using Stripe. I love having video courses, and use Podia for hosting those, but it’s expensive and doesn’t let me allow people to buy memberships from my own website or allow for physical products (and capturing shipping addresses), so I use Gumroad for all my sales and then punt to Podia using coupon codes, and both of those services make you create an account, which is… not ideal. It bugs me, it probably bugs my customers.
  3. Related to the above — hosting my own videos. I’m using Wes Bos as inspiration and love how he runs his website and courses. Of course, hosting videos will be a whooole mess of potential additional issues but would be pretty baller.
  4. Price parity. Another Wes Bos inspiration. I get emailed a lot from folks in Africa or India asking for a coupon code since $15 USD is a whoooole bunch of money there. And while I make probably 10x less than Wes Bos and kind of need to save all the pennies I can, I also don’t want to be a dick. So I’ll look into rolling something like this hopefully soon.
  5. More authors! More books! Maybe! This big website update will make it easier to move from self-publisher to publisher territory.

In conclusion: Development is fun!

Well, the last three days of work didn’t directly make me money (and I’m rather poor right now) but they were fun, I learned a lot, and hopefully this new infrastructure will improve my future revenue flow. At the very least, hopefully it’ll good for my career in general.