Tech Stack Choices for This Site
Tech Stack Choices for This Site
Building a personal website is an opportunity to work with technologies you genuinely enjoy. Here’s what I chose and why.
SvelteKit
SvelteKit provides excellent performance and developer experience. What I love about it:
- Compiler-based: Unlike React or Vue which ship framework libraries to the browser, Svelte compiles to vanilla JavaScript at build time. This means smaller bundles, faster load times, and no framework overhead running in your browser.
- Elegant reactivity: Svelte 5’s runes (
$state,$derived) are one of the most elegant and least verbose reactivity systems available. The developer community loves how natural and straightforward they feel. - File-based routing: Your folder structure is your routing. Want a
/blogpage? Createroutes/blog/+page.svelte. Need/blog/[slug]? Add a[slug]folder. No separate route configuration files, no manual setup. The file system defines your routes, making it instantly clear where pages live and trivial to add new ones. - SSR + SSG: Best of both worlds for performance and SEO
mdsvex
mdsvex allows me to write posts in Markdown with embedded Svelte components. This means I can:
- Write content in familiar Markdown syntax
- Add interactive demos without switching contexts
- Keep content and code colocated
- Maintain type safety with Zod validation
Here’s a live example with a button that has Svelte reactivity embedded right in this markdown:
Pretty cool, right? The component state works seamlessly within the markdown content.
SkeletonUI (Minimal Usage)
SkeletonUI provides utility classes for buttons, badges, and chips - but I’ve stripped out their theming system entirely:
- Using only component utilities (
btn,badge,chipclasses) - Built a completely custom dual-theme system with CSS custom properties
- Custom light/dark mode toggle with localStorage persistence
- All colors, backgrounds, and styling are custom-designed
Rather than using their themes, I’ve created a bespoke design system that fits the site’s aesthetic.
Custom Design Features
Beyond the framework stack, I’ve built several custom features:
- Dual-theme system: Custom light/dark mode with CSS custom properties for centralized color management
- Cursor spotlight effect: An animated radial gradient that follows your cursor with a gentle pulsing animation (try moving your mouse around!)
- Purple-tinted light mode: Warm, purple-tinted backgrounds instead of harsh whites for better readability
- Consistent design language: All tags, cards, and UI elements use standardized styling across the entire site
The Build System
Beyond the core framework, I’m using:
- Vite: Lightning-fast dev server and optimized builds
- Tailwind CSS 4: Utility-first styling with latest features
- Zod: Runtime validation and type safety for frontmatter metadata
- Biome: Fast, consistent code formatting and linting
- Claude Code + Sonnet 4.5: The entire website was built with heavy assistance from Claude Sonnet 4.5 through Claude Code, helping with architecture decisions, component design, and implementation details
Why These Choices Matter
This stack lets me:
- Write fast: Markdown for content, Svelte for interactions
- Deploy fast: Static generation with Vercel
- Iterate fast: Hot module replacement and instant updates
- Build confidently: TypeScript + Zod catch errors early
The goal was to minimize friction between having an idea and publishing it. This stack achieves that.
Code Example
Here’s how simple the blog post loader is with this setup:
import { z } from 'zod';
const postSchema = z.object({
title: z.string(),
date: z.coerce.date(),
excerpt: z.string(),
tags: z.array(z.string()),
published: z.boolean(),
});
const modules = import.meta.glob('../posts/*.md', { eager: true });
export const posts = Object.entries(modules)
.map(([path, mod]) => ({
slug: path.match(/([^/]+).md$/)?.[1],
...postSchema.parse(mod.metadata),
Content: mod.default,
}))
.filter(p => p.published)
.sort((a, b) => b.date - a.date); Just drop a markdown file in src/posts/ and it automatically appears on the site. No configuration or manual imports needed. It just works.
The bottom line: Choose tools that get out of your way and let you focus on creating. That’s what this stack does for me.