There are two different approaches to running a personal website: static or dynamic. They each have their pros and cons, but there are some ways to bridge the gap between them.
Static websites
Static websites are generated by running a program that generates HTML files, as well as CSS and Javascript. The generated files can then be uploaded to the web, usually for free. People use GitHub pages to host their websites for free, and some people use Amazon S3 for a very cheap solution. I think the most popular static site generator (SSG) these days is 11ty. A few years ago I used to run my own SSG, called nefelibata.
The biggest advantage of SSGs is that it's easy to host the website. They are just HTML, so it's easy to cache or put in a content delivery network (CDN) to ensure the website is never down. It's a very resilient solution, trivial to backup and move from one provider to another. It's just files that never change.
And that's the biggest disadvantage with static websites: it's just files that never change. To add support for comments, webmentions, and other interactions, you need rely on an external service. For people who care about self-hosting, like I do, that becomes a challenge.
Dynamic websites
Dynamic websites are websites that depend on software running on a server, and usually rely on a database. If that sounds daunting, you've found the main disadvantage that they have. They require maintenance, and are hard to scale: if someone shares a link to one of your posts on a popular website, it's very likely that your website will go down.
They're also more expensive to run, in general. People usually rent a virtual private server (VPS) on a cloud provider, which costs around $4-20/month. They can be hacked, so now you have to be a 24/7 sysadmin making sure the system is secure and stable.
The biggest advantage of dynamic websites is that they're alive. If someone leaves a comment it can show up immediately to other visitors. You can configure your website to receive webmentions, or to send webmentions when you create a new post. It can send you notifications when someone likes one of your posts. The level of interactivity that you can achieve is much higher, compared to SSGs.
My current website is dynamic: it runs Python on a $5/month VPS. When I weight myself on my smart scale the data is automatically sent to my blog, creating a private post. It's the same thing when I play a video game on Steam. All of these interactions would be impossible with an SSG.
Funky caching
Are there any in-betweens? I remember discovering funky caching back in 2002. It worked by generating a static version of a page the first time it was requested. Subsequent requests would read from the generated static HTML, reducing the load on the server. If something changed on the website β for example, you added a new post β you would have to delete the old, stale, pages.
It was not popular, and to be honest I don't remember what problem it was trying to solve. Wouldn't it be easier to just generate the whole website when a change happened, instead of deleting the files and waiting for them to be built during requests? Maybe the time to generate all the static files was too big back then; these days modern SSGs can regenerate a whole site in milliseconds, when written correctly.
Back then I used a blog engine called PyBlosxom, and I added support for funky caching. I also wrote a Wiki engine called "kikiki" that leveraged the concept: whenever you visited a non-existing page it would show a form to create it, instead of returning a 404.
My new blog
In the new blog engine I'm writing, each page is a program. When you run the program, it generates HTML. But because the program is written in Forth, the programs look a lot like HTML with templates. I have a Makefile that runs all the Forth programs it can find, in order to build a static version of my website: the index.fs program generates index.html, pages/likes.fs generates pages/likes.html, and so on.
So it's an SSG?
It is static. But it also has one endpoint that is dynamic. The website runs a single Forth program as a CGI file, exposing an endpoint for visitors to like posts and leave comments. Those interactions are saved into a CCSV file, that is read by the individual pages in order to render them along my posts.
The problem is, once a visitor leaves a comment, how do we make the new comment show up on the page, if it's static? One way to solve this, which is how I initially solved it, is to have Javascript code accessing the endpoint to read the comments for a given post. This works well: a visitor opens a page, the page renders with some comments, and any new comments are loaded from the dynamic endpoint and displayed in under a second.
But it doesn't work for everyone. Some people don't have Javascript. I'm from a time when we celebrated progressive enhancement, when pages worked without Javascript and, instead, relied on Javascript only as a way of improving the user experience. And while the big corporate web is way past progressive enhancement, we're talking about the indie web here, the punk web, grassroots websites & al. I want to make a website that works on lynx.
How does it work without Javascript? Without Javascript, the CGI bin stores the like/comment in the CCSV file and then calls the original page to re-render the HTML. It doesn't even need to spawn a process: it's just a Forth program (the CGI bin script) calling another Forth program the page, which can be done with an include directive. And because it's Forth, it's fast: rendering a page takes ~7ms in my 11 year old laptop running NetBSD.
After rendering the page, the CGI bin script then redirects the user back to the fresh page. So the website is static, but it has a single endpoint for POST requests that recompiles the static pages as needed. Deployment is still relatively simple: it requires a gforth and a web server with support for CGI (I'm using bozohttpd), but no database.