Colophon
The tech stack, design decisions, and integrations that make this site tick.
Framework & Hosting
Astro 5
Static-first framework with islands architecture. Astro components handle server-side rendering, React components hydrate client-side only where interactivity is needed.
React 19
Used for interactive islands — animated icons, GitHub calendar, social links — hydrated via client:idle and client:visible directives.
Netlify
Static output with serverless API routes for Spotify, Discogs, Hardcover, view counting, and password-protected posts.
TypeScript
End-to-end type safety across components, API routes, content schemas, and utility functions.
Content
Astro Content Collections
Four collections — Thoughts, TIL, Projects, Photography — with Zod schemas, Markdown/MDX support, and frontmatter validation.
Shiki
Syntax highlighting with dual themes (Catppuccin Latte for light, Tokyo Night for dark), plus transformers for filename labels, line highlighting, and diff notation.
Custom Rehype Plugins
Sidenotes rendered as margin notes on wide screens, external link indicators, and GFM support via remark-gfm.
Pages CMS
Git-based content management for data files like bookmarks, brain dumps, and networks.
Styling & Design
Tailwind CSS 3
Utility-first CSS with class-based dark mode. Extended via a custom design system token layer built on CSS custom properties.
Design Tokens
CSS variables for colours, shadows, radii, z-index scale, and transition speeds. Every component references tokens, never raw values.
Typography
Literata (serif) for body and headings, system sans-serif for UI elements. Font size accessibility controls for reader preference.
View Transitions
Astro's ClientRouter for smooth page transitions. Dark mode toggle uses a clip-path circle reveal animation from the click point.
Integrations
Spotify
Now-playing widget with marquee text, spinning vinyl disc animation, and idle state. OAuth token refresh handled server-side.
Hardcover
GraphQL-powered reading list with book spines, genres, ratings, and reading progress.
Discogs
Vinyl collection displayed in a scattered, draggable layout with cover art and metadata.
Upstash Redis
View counting for Thoughts and TIL posts with per-session deduplication, stale-while-revalidate caching, and graceful fallback.
GitHub
Contribution calendar on the projects page via react-github-calendar.
Microlink
Auto-generated bookmark preview thumbnails for the curated links collection.
Cloudflare Web Analytics
Privacy-friendly, cookie-free analytics with no pageview limits. No individual visitor tracking.
Interactions & Polish
30+ Animated Icons
SVG React components with hover animations, derived from itshover.com and wrapped in a shared animation controller.
Sound Effects
Web Audio API sounds on interactions — button taps, modal opens, navigation. Off by default with a mute toggle.
Haptic Feedback
Vibration API patterns on mobile for button presses, toggles, and form submissions.
Command Palette
Cmd+K interface for keyboard navigation across all pages and posts, plus g+key shortcuts.
PWA
Installable with offline support via service worker. Save individual posts for offline reading.
OG Images
Dynamic Open Graph image generation via Vercel OG for every blog post.
Performance
Static Output
Pre-rendered HTML with selective hydration. Only interactive islands ship JavaScript to the client.
Asset Compression
Images optimised to AVIF via Astro's image pipeline. CSS and JS compressed at build time.
Prefetching
All routes prefetched on page load for near-instant navigation.
Caching
Build-time API response caching with 5-minute TTL. Redis view counts use stale-while-revalidate headers.
LQIP Blur Placeholders
Photography gallery loads tiny 32px thumbnails with CSS blur as instant placeholders, fading out once the full image loads.