What I actually build with, why each piece is there, and the ones I have changed my mind about
https://idominikos.com/articles/my-stack
Stack posts age badly. This one is honest about a moment rather than prescriptive, and where I have swapped something out I have said so.
The surface #
Next.js and React 19, usually closer to canary than is sensible. TypeScript everywhere, with the compiler set strict enough that it argues with me. Tailwind CSS 4 for styling.
The strictness is deliberate and it is not about elegance. Coming to engineering
late means I do not always know what I do not know, and a type checker that
refuses possibly undefined on an array index is a colleague who read the manual.
Underneath #
Go for tools that should be a single binary you can hand someone. FastAPI with Pandera for the machine learning pipelines, because schema validation at the ingestion boundary is the difference between a bad prediction and a bad prediction you cannot debug.
Drizzle ORM against Neon PostgreSQL, with TimescaleDB where the data is genuinely time-series and Redis for the things that should not touch a disk.
The ones I changed my mind about #
Clerk replaced Supabase Auth across several products. Auth is the thing you least want to be clever about, and the migration cost was paid back the first time I did not have to think about session handling.
TimescaleDB replaced ClickHouse in Entrolytics. ClickHouse is a better analytics database and that was not the constraint — running one fewer kind of database was.
Biome replaced oxlint, and then oxc replaced Biome. I have been round this loop more than once, which is its own lesson about how much of tooling choice is taste dressed as engineering.
Desktop and tooling #
Tauri 2 when something needs to be a real desktop application rather than a page in a costume. pnpm with mise managing versions. A shell configuration I have been maintaining and refusing to abandon for years.
AI #
The Anthropic SDK, the AI SDK, and Claude Code in the loop daily. This is not a small part of how I work and pretending otherwise would be dishonest.
What I have learned is that the leverage is in the harness, not the model. Most of my useful work here has gone into context — what the model can see, how it is structured, how a long session keeps its thread. That is what VDK exists to solve, and it came out of needing it rather than deciding to build it.
The rule underneath all of it #
Prefer the boring option unless the interesting one solves a problem you actually have. I break this regularly, usually with build tooling, and I have never once been glad afterwards.
topics covered
related reading
- Thinking about going on Dragon's Den? My advice, don'tarticlesWhat the on-screen deal is actually worth, where the advertised money really went, and the one case where going still makes sense1 shared tag(s): lessons learned
- Your vibe-coded database is a mess (mine was too)articlesSchema drift is the tax of AI-assisted coding — why it happens to every vibe-coded project, and the tool I built to squash it1 shared tag(s): lessons learned
- Making your site agent-readablearticlesBuyers increasingly never visit your site — they ask an AI, and the AI recommends whatever it can parse. The full pattern: markdown mirrors, llms.txt, agents.md, and content negotiation1 shared tag(s): lessons learned