Skip to main content

Tech Stack Choices for This Site

svelteweb developmentdesign

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 /blog page? Create routes/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, chip classes)
  • 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:

  1. Write fast: Markdown for content, Svelte for interactions
  2. Deploy fast: Static generation with Vercel
  3. Iterate fast: Hot module replacement and instant updates
  4. 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.

Software developer passionate about elegant systems, reproducible infrastructure, AI/ML, and open source development. Experience with YOLO models, dataset curation, and building declarative, data-driven systems.

Navigation

© 2024 Lucca. Built with SvelteKit and SkeletonUI.