Skip to content

timomeh/timomeh.de

Repository files navigation

Source code from timomeh.de. Stack:

  • Next.js
  • Content stored in a separate (private) GitHub Repo
  • Keystatic as CMS
  • Drizzle with SQLite for caching and querying the content from GitHub
  • hosted on Railway 🚞

Is this a bit overkill for a blog? Probably. Is it fun? Absolutely.

Implementation details

Where do I store content?

All posts and pages, including images, are stored in a private GitHub repository as MDX. I use Keystatic as a CMS to manage this content. I enjoy the editing experience in a WYSIWYG editor in my browser, with support for drag-and-drop file uploads. Keeping the content repository private allows me to work on drafts in private.

Why cache in SQLite?

Keystatic only supports fetching content by a slug or fetching everything. No filtering, no joins, no sort—you have to do that in JavaScript. This can result in a bunch of requests to the GitHub API.

A fetch cache could fix that, but in theory I could still hit the GitHub API Rate Limits—especially when dependabot opens or rebases a bunch of PRs, and E2E tests constantly fetch new data from GitHub.

That's why I cache it. Caching it in a SQL database additionally gives me filters, joins, sort. Whenever content in the private repository changes, GitHub triggers a webhook that updates the corresponding caches.

Serving images

Images are also stored in the private GitHub repository. To make them publicly accessible, I have a reverse proxy on an private Railway service, with a public imgproxy in front of it for image optimization.

Videos are simply uploaded to YouTube, and YouTube links in posts are automatically converted to embeds.

Getting Started

  1. Fill in env variables
  2. pnpm db:push to prepare database
  3. pnpm dev
  4. Visit https://localhost:3000/webhooks/nuke to populate database

Publish

Pushing to the main brach automatically triggers a new release:

  • it builds a new docker image as release candidate
  • runs e2e tests against it
  • publishes the release it to ghcr.io
  • redeploys the Railway service
  • executes a database migration container

Tech & Libraries used

This is total overkill and I do it because it's fun. You might not need what I used:

About

📝 my blog where I swear I write regular content

Resources

Stars

Watchers

Forks

Contributors 2

  •  
  •  

Languages