Source code for Cito's personal blog — the blog of Christoph Zwerschke, a software developer and programming enthusiast writing about Python, web development, GraphQL, and technology.
This blog is built with Astro using the Spaceship theme and deployed to GitHub Pages via GitHub Actions.
- Astro — the web framework for content-driven websites. Thanks to the Astro team for building such a great tool.
- Spaceship — a modern, fast blog theme for Astro. Many thanks to Alexey Poimtsev for creating and maintaining this beautiful theme.
Deployment is fully automatic. A GitHub Actions workflow
(.github/workflows/deploy.yml) runs whenever you push to the main branch.
It installs dependencies, builds the site, and deploys the result to GitHub
Pages. You can also trigger a deployment manually from the Actions tab on GitHub
("workflow_dispatch").
As the blog author, all you need to do is push (or merge) to main. The
rest happens automatically. The live site at https://cito.github.io/ updates
within a couple of minutes.
pnpm dev |
pnpm build + pnpm preview |
|
|---|---|---|
| Purpose | Live preview while writing | Test the production build locally |
| Drafts | Shown (posts with draft: true) |
Hidden |
| Future posts | Shown (posts with pubDate in the future) |
Hidden |
| Speed | Hot-reloads on file save | Requires rebuild after changes |
Use pnpm dev when writing or editing posts. Use pnpm build followed by
pnpm preview if you want to verify exactly what will be deployed.
Before using either command for the first time (or after pulling changes), install dependencies:
pnpm install-
Create a new Markdown file in
site/content/posts/, e.g.site/content/posts/my-new-post.md. -
Add YAML frontmatter at the top:
--- title: "My New Post" description: "A short summary for SEO and post listings." pubDate: 2026-04-04 tags: ["Python", "Programming"] ---
-
Write the post body in Markdown below the frontmatter.
-
Illustrative images go in
site/assets/img/(). Screenshots and full-width images go insite/assets/scr/(). -
Run
pnpm devto preview, then commit and push tomainto publish.
Frontmatter fields:
| Field | Required | Description |
|---|---|---|
title |
yes | Post title |
description |
yes | Short summary (used in listings and SEO) |
pubDate |
yes | Publication date (YYYY-MM-DD) |
tags |
no | Array of tag strings (defaults to ["others"]) |
draft |
no | Set to true to hide in production |
updatedDate |
no | Date of last significant edit |
featured |
no | Set to true to feature on the homepage |
slug |
no | Custom URL slug (default: YYYY-MM-DD-filename) |
- Edit the Markdown file in
site/content/posts/. - Optionally add or update the
updatedDatefield in the frontmatter. - Commit and push to
main.
Astro is the static site generator that turns Markdown into HTML. Update it when you want bug fixes, performance improvements, or new Markdown/MDX features. This is a low-risk update that you can do periodically (e.g. every few months) or when you hit a specific bug.
pnpm update astro
pnpm build # verify the build still worksFor a major version upgrade (e.g. Astro 6 to 7), check the Astro upgrade guide first, as breaking changes may require config or code adjustments.
The Spaceship theme provides the visual design, layout components, and
page templates. It lives in the src/ directory. Your content in site/ is
separate from the theme engine, so theme updates should not touch your posts.
Update the theme when you want new design features, bug fixes, or compatibility with newer Astro versions. Check the Spaceship changelog to decide whether an update is worth it.
To update:
- Download or clone the latest version of Spaceship.
- Replace these directories/files with the new versions:
src/astro.config.mjs(merge carefully — our file has customredirectsandsitesettings)package.json(merge carefully — keep thename, removepreparescript, keepsharpdependency)tsconfig.jsonsvelte.config.js
- Re-apply the local customisations listed below (they live in
src/and will be overwritten). - Run
pnpm installandpnpm buildto verify.
Keep your site/ directory untouched — it contains all your content and
configuration.
src/content.config.ts— changeimport { z } from 'zod'toimport { z } from 'astro:schema'(Astro 6 compatibility fix; may already be fixed in a newer theme release). Also removeprojectsandappearancesfrom thecollectionsexport (keep their definitions but prefix them with_so they are not loaded — the content directories don't exist and would cause warnings).src/components/Header.svelteandHeader.astro— remove{ name: 'Projects', href: '/projects' }and{ name: 'Appearances', href: '/appearances' }from thenavLinksarray, keeping onlyPostsandAbout.src/pages/index.astro— remove theprojectsandappearancescollection fetches near the top, and remove the entire "Projects" and "Talks & Appearances"<section>blocks from the page body.src/pages/about.astro— addlinkedin,bluesky,mastodon, andemailentries to thesocialIconsmap (with proper SVG path data), and remove unused entries (x,telegram,facebook,youtube).src/styles/global.css— append the "Site customisations" section from the bottom of the file (post image sizing: constrained for/img/, full-width for/scr/).src/components/SocialShare.svelte— replace theplatformsarray with LinkedIn, BlueSky, and Mastodon entries (each with aname,iconSVG path string, andgetShareUrlfunction), removing X, Telegram, and Facebook. In the template, render the icon via{@html platform.icon}inside an<svg>element (same pattern as the original, just new platforms).
site/ # Content (posts, about page, config, assets)
config.ts # Site title, author, social links, feature flags
hero.md # Homepage hero text
content/
posts/*.md # Blog posts
about/index.md # About page
assets/ # Static files (images, favicons, legacy redirects)
img/ # Illustrative images (displayed at constrained size)
scr/ # Screenshots (displayed at full content width)
src/ # Theme engine (Spaceship) — don't edit for content
.github/workflows/ # GitHub Actions deployment
All blog content (posts, images, and text) is copyright (c) 2016-2026 Christoph Zwerschke. All rights reserved.