Choosing Astro
For this redesign of my blog, I wanted to explore new and best technologies. I was initially deciding if I would use Next.js as I was wanting to tinker with it, coming from the Angular world. But I quickly set that thought aside seeing it would be overkill for a small blog that wouldn't be updated very often, (frankly.) So static site generation (SSG), was still the way to go. Having used Jekyll for my previous blog stack, I decided to switch to Astro. In few words, it is simply a more modern and less rudimentary approach, allowing SSG while still making it possible to make data requests to external APIs, and allowing me to use technologies and architectural approaches I am familiar with or want to become more familiar with such as React components and shadcn/radix UI primitives.
Choosing Strapi
I had the usual goals for the content creation side of the stack, and in the end I decided on a self-hosted Strapi with postgres database setup for the backend. Strapi is a popular headless CMS, and its ease of configurability, ease of API token and webhook creation, and allowing as simple or as complex a schema as one wishes via a well designed and intuitive UI were the deciding factors. For a simple technical blog it fit the bill perfectly. I was up and running in an afternoon.
Automating Builds
The webhook is posted to on relevant changes in Strapi (i.e. blog article creation), and a very simple Express app serves as the webhook receiver, kicking off a build of Astro to regenerate the site's static files upon a successful POST to it.
1const express = require('express');
2const bodyParser = require('body-parser');
3
4var exec = require('child_process').exec;
5
6const app = express();
7
8app.use(bodyParser.json());
9
10app.post('/webhook/', (req, res) => {
11
12 console.log('Received Webhook:', req.body);
13 exec('npm run build', { cwd: '/home/protected/[Source Folder]' }, function(error, stdout, stderr) {
14 if (!error) {
15 res.status(200).send('OK');
16 } else {
17 res.status(200).send('NOT OK: ' + stdout + ' ' + stderr);
18 }
19 });
20});
21
22const PORT = process.env.PORT || 3000;
23
24app.listen(PORT, () => {
25 console.log(`Webhook receiver listening on port ${PORT}`);
26});Further Credits
Lastly, a big credit to astro-erudite, from which I borrowed extensively:
astro-erudite is an opinionated, unstyled static blogging template built with Astro, Tailwind, and shadcn/ui. Extraordinarily loosely based on the Astro Micro theme.