My stack
The tools I build with, and the reasoning behind each choice.
My /about page lists what I use. This page explains why. I value simplicity, small surface areas, and tools that let me ship without fighting the framework. I’d rather use boring technology that works than chase the new thing every quarter.
Language: TypeScript
TypeScript everywhere. Front-end, back-end, scripts, tooling. One language, shared types from database to UI, fewer bugs reaching production.
And TypeScript 7 is being rewritten in Go, so it should only get better.
Framework: Next.js, TanStack Start, Hono
Next.js has been my default for years. The App Router, server components, and the Vercel ecosystem make it hard to beat for content-heavy sites and SaaS products. This site runs on it.
For new projects that aren’t static, I’m leaning towards TanStack Start. Full-stack TypeScript without the opinions Next.js imposes. It’s newer, still rough around the edges, but the primitives are solid and the direction feels right.
Hono for APIs and lightweight services. Fast, runs everywhere (Cloudflare Workers, Bun, Node), and the middleware system is clean.
You’ll notice TanStack shows up a lot on this page (Start, Query, Form). There are very few people in the ecosystem I respect as much as Tanner Linsley, Dominik Dorfmeister, and Jack Herrington. The quality and consistency of what they put out, combined with how well they teach what they know, is rare.
Styling: Tailwind + shadcn/ui
I was a Styled-components person for a long time, and even co-created a library compatible with styled-system. But Tailwind won me over. The JIT compiler, the universality across frameworks, and for advanced component workflows, CVA (Class Variance Authority) make it hard to go back. The iteration speed is something else, and the constraint system keeps CSS from rotting over time.
shadcn/ui on top gives me accessible, well-built components that I own and can modify. No dependency to update, no breaking changes to track. Copy, paste, adapt.
Design: Figma
I’ve always had a tendency to design directly in CSS, and LLMs have only made that worse. Or better? But for anything that requires real craft (spacing, visual rhythm, fine-tuning details), it’s still easier to work in a proper design tool. Figma is that tool.
Hosting: Vercel, Netlify, Railway
Most of what I ship is hosted on Vercel. The DX is the best I’ve used for Next.js projects, and I’d be lying if I said otherwise. I’m not entirely comfortable, though, with some of the political positions taken and displayed by its leadership, whether through tweets or selfies. It’s not about vendor lock-in or Next.js bashing, it’s just a gut feeling that won’t go away.
Netlify holds a special place for me. Mathias Biilmann and his team championed the Jamstack, which was my workhorse for years. I haven’t deployed anything there in a while, but I’d like to find a reason to go back.
Railway for anything that needs a persistent server: Discord bots, background workers, or orchestrating multiple interdependent services.
For databases: Neon when I need Postgres, Turso when I don’t. Turso is built on libSQL, an open-source fork of SQLite with native replication across edge locations.
I’m cautious about recommending heavier infrastructure. I won’t suggest Kubernetes or Terraform until they’re actually needed. Most projects I’ve worked on would have shipped faster and cost less without them. The same goes for monorepos: the DX overhead used to be a dealbreaker, but LLMs are getting good at compensating for the complexity we can’t be bothered to master. The calculus is shifting.
ORM: Prisma, Drizzle
Prisma was my default for years. Solid migrations, good schema-first workflow. But heavy. The generated client is large and cold starts on serverless grind my gears.
Drizzle is where I’m heading. Closer to SQL, lighter, and if you’re starting something new today, just use Drizzle.
Auth: Better Auth
Auth is one of those things you should almost never build from scratch.
Better Auth is the best thing that happened to Auth.js: better documentation, better features, and you own your users’ data. That last part is why I can’t bring myself to use managed solutions like Clerk or WorkOS for SAML/SSO. I understand why people do, and the DX is good. But not owning my user table is a tradeoff I’m not willing to make.
Validation: Zod, TanStack Form
Zod everywhere. API inputs, environment variables, form validation. It plugs into everything I use (tRPC, TanStack Form, Payload) and the TypeScript inference just works. Not much else to say.
TanStack Form for forms. Used React Hook Form for years, moving on. TanStack Form is controlled by design: predictable state, works outside the DOM (React Native, Three.js), easier to test. RHF’s uncontrolled approach was clever, but controlled wins when you need to actually reason about what’s going on.
Data flow: tRPC, server actions
TanStack Query for client-side data fetching. Caching, refetching, stale-while-revalidate. Once you’ve used it, you can’t go back.
tRPC for type safety between client and server. No code generation, no schema files, just TypeScript. Calling an API feels like calling a function.
Server actions for simpler mutations where tRPC would be overkill. I’m less confident about them than I used to be. The ecosystem doesn’t seem to be fully rallying behind them, and the React2Shell vulnerability (CVE-2025-55182, CVSS 10.0 RCE) didn’t help. The follow-up disclosures made it worse. They still reduce boilerplate, but I have yet to release a project in production that uses them.
Email: Resend
Resend. Build email templates in JSX with React Email instead of wrestling with table-based HTML from 2003. They also treat agents as first-class citizens with an MCP server and inbound email handling. Does one thing, does it well.
CMS: Payload
Payload. Code-first, runs on Next.js, admin panel generated from your config. Drizzle under the hood, Zod for validation. It just slots into everything else on this page.
Task management
I hate Jira with every fiber of my being. I love Linear, but working solo, it’s sometimes a bit much. These days I keep my backlog on GitHub Issues or just in markdown files. All three work well with the Ralph Wiggum loop.
AI SDK
Haven’t had many occasions to use AI SDK yet. The few times I did, it felt obvious. I’d like to try TanStack AI next (you guessed it).
LLM tools: Claude Code
Claude Code is my primary tool, even more so since Anthropic stood its ground against the Pentagon’s demands to allow unrestricted military use of Claude, at the cost of being blacklisted as a supply chain risk. That took guts.
I know there’s a turf war between Opus 4.6 and Codex 5.3. But it’s like switching lanes in traffic: I’d rather stay where I am and pay attention to where the companies are heading. Anthropic is far from perfect; I resent that my Claude Max subscription no longer works with OpenCode, seeing PRs named "Anthropic legal requests" on the OpenCode repo, or watching the ClawdBot OpenClaw opportunity slip through their fingers out of pride. Non-exhaustive list. But it’s the only major LLM provider I trust enough to give my time, money, and data to.
I still use Cursor sporadically. I have a lot of respect for the team and the product, and I like trying new features and non-Anthropic models from time to time. But I always end up gravitating back to a TUI.
More on my AI usage on the /ai page, and my tool setup on /uses.
This is a /stack page. See all slash pages.