Tech
This is the setup I usually work with.
I don't switch tools often. Most of these choices are the result of building the same kinds of systems over and over again, running into the same problems, and converging on what holds up over time.
I care more about clarity and control than novelty.
Language
I almost always work in TypeScript.
It forces decisions early and makes systems easier to reason about once they grow. I'd rather spend time thinking about structure than debugging avoidable runtime issues later.
Frontend
For UI work, I usually start with shadcn/ui.
I like components that live close to the code instead of being hidden behind abstractions. It gives me a solid baseline without locking me into a rigid design system. As the product grows, the components grow with it.
Project structure
When a project stays small, I keep it simple.
Once there are multiple apps or shared concerns, I move to a monorepo. It keeps types, shared logic, and UI consistent, and avoids fragmentation early on. I don't default to it, but I introduce it as soon as duplication becomes real.
Backend & infrastructure
For infrastructure, I often use Supabase.
I treat it as boring infrastructure. PostgreSQL, authentication, storage, policies. No magic. I rely heavily on database-level rules and clear data ownership instead of pushing security concerns into the client.
I prefer setups that stay out of the way and don't require constant operational work.
Architecture
I aim for clear separation between:
- domain logic
- application flow
- infrastructure
Not because it's academically "clean", but because it makes change safer later. Most complexity shows up after the first version, not before it.
What I optimize for
I don't chase tools. I optimize for:
- systems that survive iteration
- decisions that are easy to explain months later
- setups another engineer can step into without guesswork
If something keeps working quietly, I usually leave it alone.
What I deliberately avoid
I try to stay away from:
- heavy frameworks that hide too much
- stacks that require constant tuning
- complexity that only exists to feel clever
Simple systems tend to last longer.