No description
Find a file
HangerThem 98212889bf chore: README, dependency cleanup and shared components
- Replace the create-next-app README with real project docs (features,
  env vars, frontmatter schema, Markdown extensions, deployment)
- Drop ESLint (unused by any script; oxlint is the linter) and the
  unrelated 'hast' package; move oxlint, oxfmt and puppeteer to
  devDependencies (locked versions unchanged)
- Extract PostList, used by the tag and category pages
- Use shared Intl formatters for post dates, pinned to Europe/Prague so
  the build server's timezone can't shift dates
- Use <h1> for the tag/category page headings (same styling)
- Remove math/mermaid flags from posts that don't use them; fix a typo
  in the Tessera cover alt text

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:25:58 +02:00
app chore: README, dependency cleanup and shared components 2026-10-19 14:25:58 +02:00
components chore: README, dependency cleanup and shared components 2026-10-19 14:25:58 +02:00
content chore: README, dependency cleanup and shared components 2026-10-19 14:25:58 +02:00
lib feat(seo): sitemap, robots, canonical URLs, OG images and JSON-LD 2026-10-19 14:22:40 +02:00
public perf: image loading, smaller assets, server-rendered code blocks 2026-10-19 14:17:18 +02:00
types feat(seo): sitemap, robots, canonical URLs, OG images and JSON-LD 2026-10-19 14:22:40 +02:00
utils chore: README, dependency cleanup and shared components 2026-10-19 14:25:58 +02:00
.gitignore Initial commit from Create Next App 2026-07-26 11:39:13 +02:00
.oxfmtrc.json Fixed few formatting things; started on support for mobile/PWA 2026-08-03 15:11:10 +02:00
.oxlintrc.json Fixed formatting 2026-08-04 07:46:51 +02:00
bun.lock chore: README, dependency cleanup and shared components 2026-10-19 14:25:58 +02:00
next.config.ts perf: image loading, smaller assets, server-rendered code blocks 2026-10-19 14:17:18 +02:00
nixpacks.toml Fixed formatting 2026-08-04 07:46:51 +02:00
package.json chore: README, dependency cleanup and shared components 2026-10-19 14:25:58 +02:00
postcss.config.mjs Fixed few formatting things; started on support for mobile/PWA 2026-08-03 15:11:10 +02:00
README.md chore: README, dependency cleanup and shared components 2026-10-19 14:25:58 +02:00
tsconfig.json Initial commit from Create Next App 2026-07-26 11:39:13 +02:00

Ephemeris

Source of blog.hangerthem.com — my personal blog and portfolio. Posts are plain Markdown files rendered to static HTML at build time by a custom unified pipeline.

Features

  • Fully static — every post, tag and category page is pre-rendered with Next.js (App Router, React Server Components)
  • Custom Markdown extensions via small rehype plugins in lib/:
    • Callouts: > [!TIP], > [!WARNING], > [!INFO], > [!QUOTE]
    • Highlights: ==marked text==
    • Definition lists (a term line followed by : definition lines)
    • Code blocks with language label, line numbers and a copy button
  • Math with KaTeX and diagrams with Mermaid, rendered to SVG at build time — no client-side JS for either
  • Table of contents generated from h2/h3 headings with scroll-spy
  • SEO — canonical URLs, Open Graph/Twitter cards, generated OG images, JSON-LD, sitemap, robots.txt and an Atom feed
  • Works without JavaScript; JS-only UI (like copy buttons) is hidden when it's unavailable

Stack

Next.js 16 · React 19 · TypeScript · Tailwind CSS 4 · unified (remark/rehype) · highlight.js · KaTeX · Mermaid (via Puppeteer) · Bun · oxlint/oxfmt

Getting started

bun install
SITE_URL=http://localhost:3000 bun dev
Script Purpose
bun dev Development server
bun run build Production build (static generation)
bun start Serve the production build
bun run lint oxlint + formatting check
bun run lint:fix Auto-fix lint issues and format

Environment variables

Variable Required Description
SITE_URL yes Public origin, e.g. https://blog.hangerthem.com
SOURCE_COMMIT no Commit hash shown in the sidebar (falls back to git rev-parse)
GIT_ORIGIN_URL no Repository URL; enables the "Source Code" link and commit link

Writing posts

Posts live in content/posts/; the file name is the URL slug. Standalone pages (About, Projects, Setup) live in content/pages/.

---
title: 'Tessera: A Privacy-First Card Wallet'
description: 120–160 characters work best for search results.
date: 2026-09-18 12:00:00 +0200
updated: 2026-09-18 12:30:00 +0200 # optional
category: Projects
tags: [projects, pwa, privacy]
coverImage: tessera-cover.png # optional, from public/posts/, 1200×630 recommended
coverImageAlt: Tessera logo next to two loyalty cards
math: true # optional, enables KaTeX
mermaid: true # optional, enables Mermaid diagrams
draft: true # optional, only rendered in development
---

Frontmatter is validated at build time, so a missing or malformed field fails the build with the file name instead of producing a broken page.

Images go in public/posts/ and are referenced by file name: ![Alt text](image.png "Optional caption").

Project structure

app/            Routes, metadata, feed, sitemap and OG image generation
components/     UI split into content/, layout/, post/ and ui/
content/        Markdown posts and pages
lib/            Markdown pipeline, rehype plugins, tag/category helpers
public/posts/   Post images

Deployment

Deployed with Nixpacks (see nixpacks.toml). Mermaid diagrams are rendered with headless Chromium during the build, so the build environment needs Chromium's system libraries and network access to fetch the Mermaid script.