A personal API part 2, restructuring

Lets start with a look at the infrastructure before this change:

                                             │Vercel        │      
                                             │              │      
┌─────────────────────┐          ┌───────────┤│[Svelte] CMS││      
│Odroid               │          │           │└────────────┘│      
│                     │          │           └──────────────┘      
│┌───────────────────┐│          │                                 
││[GO]   Pocketbase  │◀──────────┤           ┌────────────────────┐
│└───────────────────┘│          │           │Netlify             │
│          ▲          │          │           │                    │
│          ▼          │          │           │┌──────────────────┐│
│┌───────────────────┐│          └───────────▶│[Ruby] Bridgetown ││
││[Rust] Pocketknive │├──────────┐           │└──────────────────┘│
│└───────────────────┘│          │           └────────────────────┘
└─────────────────────┘          │           ┌────────────────────┐
                                 │           │Bunny.net           │
                                 │           │                    │
                                 │           │┌──────────────────┐│
                                 └───────────▶│Storage zone + CDN││

I ran Pocketbase on the Odroid H3+ in my utilities closet. Pocketbase is a great little CMS with tons of options, but my site is heavily focused on Images (especially the trips section), and lazy-loading all the images wasn't good for performance.

This was resolved by introducing the Pocketknive helper process. This would query pocketbase for new uploads and resize/convert them before uploading to the Bunny.net storage zone.

The CMS is a wrapper in Svelte(kit) around the TipTap editor, deployed on Vercel. I use the JSON export of this editor and store it in pocketbase as a JSON field.

When I added content, I would request a build from Bridgetown, running on Netlify to generate a new static site from the content.

The reason for using both Vercel and Netlify, was that Netlify wouldn't run SvelteKit properly at the time, and so Vercel was added, which did support Sveltekit.

New structure

The new structure is less complicated, and looks like this:

┌──────────────────────┐    ┌────────────────────┐
│Odroid                │    │Bunny.net           │
│                      │    │                    │
│┌────────────────────┐│    │┌──────────────────┐│
││[Rust] Matsimitsu-rs│├────▶│Storage zone + CDN││
│└────────────────────┘│    │└──────────────────┘│
└──────────────────────┘    └────────────────────┘

I have a small Rust/Axum server running on the Odroid, which is fronted by a Bunny.net "Pullzone" that caches the pages. I can control the cache with the headers from Axum, so older articles get cached indefinitely, while index pages and new posts have shorter cache time. I can also purge the cache when I update the CSS.

I'll post more about the Axum webserver in the future. It runs as a single binary and even the (S)CSS is handled completely in Rust, and embedded when compiling.


(I'm still using the CMS, but not hosted on Vercel. I just run it locally, as I only accessed it from my desktop anyway).

To add short-form content on the go, I have added a Telegram bot, which listens for commands and creates content from the messages and publishes them.

e.g. : /note Photo Sunny day creates a new note, and all messages after that are added as content, including photo/video uploads. Closing with /publish will publish the content added.

What's next

The base components are now in place. And ideally I'd be able to create posts from the Xxum webapp, instead of running SvelteKit locally. This would mean coming up with a way to run the TipTap editor, or replace it with another block-like system.

Other features I'd like to include is posting content to Mastodon and adding replies as comments. Now that I have a webserver that can listen to requests, this should be very doable.