On Building this Site
Jun 18, 2023
I rebuilt this website in December 2022. My son was just born and my wife and I were adjusting to life with a newborn and life without sleep. During my turn on “night shift”, I spent my time hacking this site together. It’s written in Svelte with the Sveltekit framework (think React with the Next.js framework).
I’ve had Svelte on my radar since it was Stackoverflow’s most loved framework in 2021. As someone whose day job has been React since 2015, I needed something new. Plus, my site needed a refresh since I haven’t updated it in almost 7 years at this point.
Quick interlude before continuing: I like Svelte. A lot. I can write so much more frontend with a lot less boilerplate. For example, here's a stripped down version of a way to do file uploads in React:
import { useRef } from 'react';
export const FileComponent = () => {
const ref = useRef<HTMLInputElement>(null);
const handleFiles = async () => {
if (ref.current) {
const files = Array.from(ref.current.files);
// some api call
}
}
return (
<input type="file" multiple onChange={handleFiles} ref={ref} />
);
}
And here's how to do it the Svelte way:
<script lang="ts">
let files: FileList
$: if (files) sendFiles(files);
const sendFiles = async () => { /* some api call */ }
</script>
<input type="file" multiple bind:files={files} />
(Self imposed) Design Constraints
In the early 2010s, my site was powered by WordPress (whose wasn’t?) Sometime between then and 2015, I dabbled in using static site generators (Jekyll in Ruby and Wintersmith in Node). I liked the idea of a fast, static site.
But one thing I didn’t want was a flat file system, pathwalking through nested .md files with front matter. (I’m picky. We’ll see this come up a lot). This leads us to the first constraint:
Constraint 1: Static site but not with a flat file system.
I like to read a lot. I wanted a way to share what I’ve read without using a site like GoodReads. It’s not that I’m anti Amazon - it’s just that I didn’t like how they handled this property. Plus, I wanted to control this information (There’s me being picky again). Since the end of the year was coming up, I wanted to show off this book database on a page somewhere (see it here) so this feature had a bit of a deadline.
It’s obvious that I needed a database to store these book records. The thing is, I’m cheap. At this point in time, managed databases were averaging $15-20/month. DigitalOcean charged $15/month, Supabase charged $25/month* and Linode charged $15/month.
*I am aware that Supabase is free for 2 projects, but again, I’m picky, I don’t know if I mentioned that yet. I wanted to “save” those two free projects for something else and not a dumb website.
Constraint 2: cheap database.
Iteration 1
With these two constraints in mind, the first iteration of this Sveltekit powered website was a static site generated using the static adapter.
To satisfy the first constraint (static site, but not a flat file system) I wrote a very simple admin panel and CMS, CRUDing different content types:
- Posts
- Fields
- Books
Posts are pretty obvious: blog posts. Long form content. Fields are small snippets of content that I could query from the Frontend to fill in different sections of the site (like an about me, my CV etc). It’s like contentful but self-hosted and really shitty.
The Books content type was filled in using the Google Books API. I wrote a quick search page to query Google Books API where I could save which book I read.
And the database? Sqlite. This is a dumb, personal website with probably 10s of visitors a year. I don’t actually need a managed database. Sqlite is just fine. And cheap.
Building and Deploying
Vercel seemed like the obvious choice for hosting since they have first class support for Sveltekit. Unfortunately, due to vercel’s serverless architecture, any writes to sqlite would never persist.
“Storage is ephemeral” – https://vercel.com/guides/is-sqlite-supported-in-vercel
I ended up with Github pages: whenever I needed to update my website, I fired it up on a laptop, updated content, made a commit and pushed. This satisfied both constraints.
What I liked about this approach was that I had a global CDN and hosting for free. I didn’t expect to be updating content as often so firing up my site locally, committing and pushing seemed fine.
Iteration 2
It was not fine.
While I don’t write as often as I want, I read a lot and I wanted to update my book list as quickly as I could. Local development quickly became annoying.
It became clear that I needed to host the entire site.
The changes were trivial which basically amounted to swapping out the static adapter to the node server adapter. For hosting, I decided to go with a cheap $5/month linode server.
After configuring nginx, I deployed my site and all was well.
Tradeoffs
Unfortunately, I had to give up on the static site generation (though some of the site is prerendered) and I no longer get the benefit of having a global CDN (I apologize to my one German visitor for waiting 200ms to load my website).
However, Vercel just announced storage options (included in their free tier) so Vercel might just become the next home.
But, I’m picky and I’m paranoid. I like the idea of controlling my entire stack (kind of). And we’ve been burned before with free Platforms as Service tiers only to be shut down a few years later (see Removal of Heroku Free Product). So, I may just keep my current setup.