I get asked about my stack a lot, and I used to answer with whatever sounded current. That made my answers unreliable. A few months ago I started keeping a single inventory of what I actually build with, not what I think about building with. This post is that inventory.

It is not a prediction. It is what I use on this site and on the projects I ship in 2026.

Why a written inventory helps

When I do not write this down, three things happen:

  • I recommend tools I have not used in months.
  • I switch stacks mid-project because something new looks interesting.
  • I cannot explain why I chose one tool over another.

A written inventory fixes that. It is just a reference I can point to and update when my real choices change.

Languages and runtime

ToolRoleWhy I keep it
TypeScriptPrimary languageCatches shape errors before runtime; same language across frontend and Node scripts
JavaScriptBrowser and quick scriptsStill the runtime target; useful for small glue code and Gatsby configuration
Node.jsRuntimeHosting compatibility and the package ecosystem I already know
BashAutomationDeployment scripts, CI one-liners, and local shortcuts

I do not try to learn a new language for every project. TypeScript covers most of what I build. I reach for something else only when the project genuinely requires it.

Frontend framework and site generator

ToolRoleWhy I keep it
GatsbyStatic site generatorGraphQL data layer, fast builds, and image pipeline I already understand
ReactUI libraryComponent model I have used for years; huge ecosystem
Next.jsApp-like projectsBetter fit when I need dynamic routing, server components, or heavy client state

Gatsby runs this site. Next.js is what I reach for when the project feels more like an app than a content site. The decision usually comes down to whether the content or the interaction is the star.

Styling and design tokens

ToolRoleWhy I keep it
Tailwind CSSUtility stylingFast layout work without leaving the markup
Custom CSS variablesTheme tokensLight/dark mode and accent colors in one controlled layer
Theme UIBase primitivesConsistent spacing and typography defaults I can override when needed

I use Tailwind for speed and custom variables for control. I do not want a component library to own my tokens, so I keep the design system in CSS and apply it with Tailwind utilities.

Animation and interaction

ToolRoleWhy I keep it
GSAP + ScrollTriggerScroll-driven animationFine-grained control over reveal and parallax effects
CSS scroll-timelineProgressive enhancementNative performance where supported, no JS overhead

GSAP is my default for anything complex. CSS scroll-timeline is the fallback and enhancement I add when browser support is good enough.

Deployment, hosting, and services

ToolRoleWhy I keep it
NetlifyHostingBranch previews, redirects, identity widget, serverless functions
sharpImage processingReliable and pinned to avoid the upgrade churn I have hit before
Netlify IdentityAuthFits the hosting stack; simple widget for protected routes
Git + GitHubVersion controlStandard, familiar, good CI integration

Netlify is the simplest path from a Git push to a live site for my content projects. I use GitHub Actions when I need custom build or deploy steps.

Content and data

ToolRoleWhy I keep it
MDXBlog and page contentLets me write posts with JSX components and keeps content in version control
SupabaseQuick database prototypeFastest path to persisted state in a demo
JSON filesTiny data needsNo setup when the dataset is small and read-only

MDX is what you are reading right now. I only add a real database when the project needs authentication, real-time updates, or relational data.

Execution process checkpoint illustration for this section.

Where I intentionally deviate

SituationI switch toWhy
Tiny static landing pagePlain HTML + Tailwind CDN or ViteFaster boot than Gatsby for one-pagers
Heavy client-side interactivityNext.js App Router or Vite + ReactBetter fit for dynamic routing and app-like behavior
Long-running background taskDocker on a VPS or AWS LambdaNetlify functions are great for short tasks, not long workers
Quick database prototypeSupabase or a JSON fileFastest path to persisted state in a demo
Native mobile experimentReact NativeI am not great at it yet, but it is the fastest way to get a real app on a phone

The pattern is simple: I start with the default stack, then switch only when the project genuinely needs something else. Not when I am bored.

Tools I tried but did not keep

I have used a lot of frameworks over the last few years. Here is where some of them landed:

  • Prisma: Great DX, but I usually do not need an ORM on small projects. Raw SQL or a thin query layer is enough.
  • shadcn/ui: Good components. I use it as inspiration more than a dependency because I want to own my CSS tokens.
  • Bun: Fast. I use it for scripts, but I still deploy Node because hosting compatibility matters more than local speed.
  • Redux/Zustand: Rarely needed now. Server state or URL state usually covers what I used to put in global stores.

This list is not criticism. These tools are good. They are just not my defaults.

How this stack has evolved

This is not the stack I started with. Three years ago, this site was plain HTML and CSS with no framework. Two years ago, it was Gatsby with JavaScript and styled-components. The current version is Gatsby with TypeScript, Theme UI, and Tailwind.

The evolution was driven by real problems, not novelty. I moved from JavaScript to TypeScript after spending two days debugging a shape error that TypeScript would have caught at compile time. I added Tailwind after realizing I was writing the same utility classes over and over in custom CSS. I kept Theme UI because ripping it out would mean rewriting every page's styling, and the benefit did not justify the risk.

The one change I regret is not adopting TypeScript sooner. I resisted it because it felt like overhead on small projects. In practice, it saves me more time on small projects than on large ones, because small projects have less test coverage and fewer eyes on the code.

Trade-offs of the current stack

Every stack has costs. Here are the real ones I live with.

Build speed. Gatsby builds this site in about 90 seconds locally. For a site with 50+ pages and a heavy image pipeline, that is acceptable but not fast. Next.js with the App Router builds comparable sites in 30-40 seconds. I accept the slower build because the GraphQL data layer and image pipeline save me more time during development than I lose during builds.

Bundle size. The inlined CSS is about 194KB. That is larger than I would like, but it is a known Gatsby behavior and the site scores well on Core Web Vitals regardless. If bundle size became a real problem, I would externalize the CSS, but I am not willing to re-test every theme to save 100KB that does not affect the metrics that matter.

Developer experience. TypeScript adds friction for quick edits. Tailwind's class lists get long and hard to read. Theme UI's sx prop causes a persistent type error in the layout component that I have chosen not to fix because it is a theme-ui typing issue, not a real bug. These are tolerable annoyances, not dealbreakers.

Hosting lock-in. Netlify's functions, identity widget, and redirect system are convenient, but they create mild lock-in. Moving to Vercel or a VPS would require reworking serverless functions and auth. I accept this because the convenience outweighs the migration cost for the projects I actually ship.

What I would choose if starting fresh today

If I were building this site from scratch tomorrow, the stack would be different in a few specific ways.

  • Astro instead of Gatsby. Astro builds faster, has a smaller output, and supports MDX natively. Gatsby's GraphQL layer is powerful but unnecessary for a content site. Astro's content collections give me the type safety I need without the build overhead.
  • TypeScript from day one. No question. The type safety is worth the setup cost.
  • Tailwind, same as now. Nothing has replaced it for my workflow.
  • No Theme UI. I would use CSS variables and Tailwind exclusively. Theme UI works, but the typing issues and the overlap with Tailwind create more friction than value on a new project.
  • Netlify or Vercel. Both are fine. I would pick based on which had the better free tier at the time.

The core principles would not change: TypeScript, utility-first CSS, static generation, and git-based deployment. The specific tools would shift, but the philosophy is the same. Start simple, add complexity only when a real problem demands it.

The most common mistake I make

The biggest mistake I make is switching tools before I understand the one I am using. I have abandoned perfectly good stacks because a new release got attention, then regretted it two weeks later.

The rule I try to follow now: use the default for at least two projects before switching. That gives me enough real feedback to know whether a tool is actually better for my workflow, or just newer.

Delivery workflow checkpoint illustration for this section.

Closing

A stack inventory is not exciting. It is useful. If you do not have one, write yours down. Keep it honest. Update it when your real choices change, not when your social feed changes.

If you want to see this stack in action, you are already looking at it.

Proof