Project structure

Where things live, and the one boundary rule worth knowing before you move a file.

Two applications, one repository

The Nuxt app is at the root; the Sanity Studio is in studio/. They have separate package.json files and separate `.env` files, and they are deployed separately — the Studio to Sanity's hosting, the frontend wherever you like.

They meet in exactly two places: the schemas in studio/ define the shape of the content, and the typed GROQ queries in app/services/groq-queries.ts fetch it. Everything else is on one side or the other.

The directories you'll spend time in
PathWhat lives there
app/components/ui/The standard block library — blocks, elements, utilities
app/components/custom/Your project-specific blocks
app/components/ui/shadcn/shadcn-vue / Reka UI primitives, hand-adapted
app/composables/Composition functions, auto-imported
app/services/groq-queries.tsEvery GROQ query and projection
app/services/helpers/Pure TypeScript helpers, unit-tested in isolation
app/stores/Pinia state, including the theme store
studio/schemas/web/Content schemas — documents, blocks, custom, elements
studio/schemas/web/custom/Your customisation entry point
scripts/Setup, scaffolding and build-time generators

Pages and routing

There are almost no file-based marketing routes. A catch-all route resolves any slug to a page document, so pricing, features, and contact are content, not files. You add file routes only for genuinely new _types_ of thing — a products section, say — and the docs cover the four-line normalisation that hands theme and fonts to it.