I just finished a complete redesign of this website—not a refresh, not a reskin, but a ground-up rebuild of everything from the component architecture to the visual language.
The previous version was functional, but it had accumulated enough friction that I decided to start fresh. This post covers what I built, why I made certain decisions, and what I learned along the way.
Why a Full Redesign?
The old site worked, but it had problems:
- No design system. Components were styled inline or with one-off utility classes. There was no consistent vocabulary for spacing, typography, or color.
- Component sprawl. Over time, I’d accumulated duplicate components with slight variations. Making a global change meant hunting through files.
I could have refactored incrementally, but the cognitive overhead of working around existing patterns wasn’t worth it. A clean slate was faster.
The Design System
The biggest investment was building a proper design system, a system of composable primitives designed specifically for this site.
Each component category has a specific purpose:
- Primitives are the atomic building blocks: buttons, badges, icon containers. They don’t know anything about the page they’re on.
- Typography components handle text styling with consistent scales and spacing.
- Layout components manage structure: sections with configurable backgrounds, responsive grids, max-width containers.
- Sections are pre-composed page blocks such as hero sections and call-to-actions. They combine primitives and layout into reusable patterns.
The key discipline: every component has a single responsibility, and composition happens at the page level.
Storybook for Component Development
I added Storybook to the workflow, which changed how I build components.
Instead of building components in-place on a page, I now develop them in isolation first:
- Each component gets a
.stories.sveltefile alongside it - Stories document the component’s variants, states, and edge cases
- I can see all components in one place and catch visual regressions early
This added some upfront overhead, but it pays off quickly. When I need a button, I don’t have to remember what variants exist—I just open Storybook.
Technical Decisions
A few other choices that shaped the build:
Svelte 5 runes throughout. The entire codebase uses $state(), $derived(), $effect(), and $props(). No legacy reactive syntax.
Snippets instead of slots. Svelte 5’s snippet syntax ({#snippet} and {@render}) replaced slots for content composition. It’s more explicit and easier to reason about.
TailwindCSS v4 with utility-first styling. No custom CSS except where Tailwind doesn’t reach. The design system components encapsulate the utility classes, so pages stay clean.
Scroll animations with IntersectionObserver. Sections fade in as they enter the viewport using a simple AnimatedSection wrapper. No animation library—just native browser APIs.
What I Learned
Starting fresh is sometimes faster than refactoring. The old site had too many assumptions baked into its structure. Building new components without those constraints was faster than working around them.
A design system is worth the investment, even for a personal site. The upfront cost of building primitives pays off the first time you need to make a global change. It also forces you to think about consistency before you have a problem.
What’s Next
The foundation is in place. Now I can iterate on content without fighting the structure.
A few things on the list:
- More interactive demos for technical projects
- Better blog typography and reading experience
But for now, the redesign is done—and I’m happy with where it landed.