HoschDB
activePersonal blog and portfolio built with Astro 6 and the HoschDB design system.
This site. Built in six phases over a few days in May 2026, starting from a working React design prototype and ending at a deployed, mobile-optimized Astro 6 static site.
The design system
The HoschDB design system came first — prototyped in Claude’s design canvas as a React component library with tokens.css, hoschdb.css, DM Mono + DM Sans typography, and an ink/chalk/moss palette. The prototype included a full editorial portfolio layout (v1-editorial.jsx) with interactive mockups at desktop, tablet, and phone viewports.
The goal was to port that design to Astro without losing fidelity and without the prototype’s shortcuts — no Google Fonts CDN, no hardcoded hex values, no SSR.
Technical decisions
Astro 6 with static output. output: 'static' throughout — no serverless functions, no SSR. Content Collections use the Astro 6 Content Layer API, which means entry.id for routing (not entry.slug, which was removed), z.coerce.date() for date fields, and loader: glob() in every defineCollection().
MDX in git, no CMS. Writing workflow is markdown files committed to the repo. Astro’s getCollection() handles querying, filtering drafts, and sorting. A custom remark plugin calculates reading time at build time via reading-time + mdast-util-to-string.
CSS container queries for mobile. The responsive layout uses @container v1 (max-width: ...) blocks targeting named CSS classes, all living in tokens.css. Three breakpoints: 820px (tablet), 560px (phone), 380px (tiny). No Tailwind, no utility classes — just the design system tokens and container queries.
Vercel static deploy. Zero-config — no @astrojs/vercel adapter needed for static output. DNS is handled at the registrar level (A + CNAME records) rather than switching nameservers, which preserves MX records for benjamin@hosch.us.
One bug worth documenting
The mobile writing list had a rendering failure on iOS Safari: post titles were invisible, only badges and read time showed. The cause was hiding grid > :nth-child(1) (the date column) with display: none while simultaneously changing grid-template-columns. iOS Safari doesn’t correctly reflow the shifted content in this case.
Fixed by reordering the HTML so the date column is last, then hiding :nth-child(3) instead — the same trailing-column pattern the projects list uses. Desktop appearance unchanged.
What’s live
- Editorial home page with stats, featured projects, and latest post
- Blog with MDX posts, reading time, tag pages, and RSS feed
- Projects list with kind filter (tool / case study / writing)
- About page with work history, stack, and contact
- Full SEO: OG tags, JSON-LD structured data, sitemap, Search Console verified
- Mobile-responsive at all viewport sizes with hamburger nav