Default stack choices
Settled preferences — applied without asking, departed from only with a stated reason.
These are settled. Apply them without asking; depart only with a stated reason.
Frontend
| Situation | Choice |
|---|---|
| Styling, always | Tailwind + shadcn/ui. shadcn is copied source we own and edit, not a component library dependency. No CSS-in-JS, no CSS Modules, no SCSS. |
| Website — content-led: marketing, docs, editorial, brochure, blog | Astro. Ship HTML; hydrate an island only where a component genuinely needs state. |
| Application, no SSR | Vite + TanStack Router |
| Application, SSR | TanStack Start |
| Never | Next.js — with one exception |
The one place Next.js is allowed
A documentation site built on a generator that happens to run on Next.js — Fumadocs is the one in use. The exception is narrow and it is about who owns the framework choice: you are adopting a docs generator, not choosing an application framework, and the generator's own runtime is not yours to pick.
Two conditions, both required:
- The framework is an implementation detail of a tool you did not write. Choosing Next.js and then building on it is the thing the rule forbids.
- Nothing product-shaped lives there. A docs site renders content. The moment auth, forms or long-lived client state appear, it is an application and the standing rule applies again.
Inheriting a Next.js codebase is not this exception either — that is a migration question, answered by reversal cost like any other.
Say the exception out loud when you use it. A rule with an unwritten exception teaches the next reader that the rules are negotiable, which costs more than the rule was worth.
The line between website and application
If the product is pages — content is the point, most of it static — it is a website → Astro. If it is sessions — auth, dashboards, forms, long-lived client state — it is an application → Vite or Start.
A website that grows a real app section keeps Astro and mounts the app, rather than converting the site.
Backend
| Situation | Choice |
|---|---|
| JVM service | Java + Spring Boot with Modulith |
| Go service | Go + the service shape |
Both sit inside the standing architecture default: hexagonal, feature-first, dependency rule enforced by a test.
Platforms
| Platform | Page |
|---|---|
| Railway | Railway |
Reading a stack page
Every page opens with a Verified line naming the date and the versions it
was checked against. That line, and the rules for what to do when a page and the
code disagree, are on
how to read this.