Project Structure
How the Nuxt template organizes app/, server/, shared/ and content/.
The template follows Nuxt 4's full-stack layout: Vue code lives in app/,
Nitro code in server/, cross-boundary types and constants in shared/, and
Nuxt Content Markdown in content/.
Top-level map
Frontend: app/
app/pages uses file-based routing. Parenthesized route groups organize files
without changing their URLs: (marketing)/about.vue becomes /about, while
(dashboard)/dashboard.vue becomes /dashboard. Auth, blog, and docs routes
are kept in their own folders.
The four layouts have distinct jobs:
| Layout | Purpose |
|---|---|
default.vue | Marketing and general pages |
auth.vue | Login, registration, verification, and password reset |
docs.vue | Documentation sidebar, content, and table of contents |
user.vue | Authenticated dashboard and account surfaces |
app/middleware/auth.ts and admin.ts are client route guards. Pages opt in
with definePageMeta({ middleware: "auth" }) or
middleware: ["auth", "admin"]. Server APIs must still enforce access with
requireAuth; client middleware is a navigation aid, not an authorization
boundary.
Components are grouped by feature. ui/ contains shadcn-vue primitives;
layout/, docs/, and motion/ are template infrastructure; ai/,
ai-elements/, dashboard/, email/, home/, and auth/ compose product
features. Composables, site configuration, locale messages, global CSS, plugins,
and shared frontend types sit beside them under app/.
Auto-imported components
Nuxt auto-imports pages, composables, and configured components. The
components block in nuxt.config.ts adds three component trees:
components: [
{ path: "~/components/layout", pathPrefix: false },
{ path: "~/components/docs", global: true, pathPrefix: false },
{ path: "~/components/motion", pathPrefix: false },
]pathPrefix: false keeps names concise (for example, AppHeader rather than a
path-derived name), while the docs components are registered globally for
Markdown content. The shadcn block separately targets
app/components/ui and app/components/ai-elements, both without a prefix.
Backend: server/
Nitro turns files under server/api into endpoints. They are grouped by
purpose: the Better Auth catch-all, user/, admin/, ai/, chat, payment and
provider notifications, storage, and contact. Shared backend modules live next
to the handlers:
server/middleware/auth.tsattaches auth context and exports auth helpers.server/database/drizzlecontains the PostgreSQL client, schema, and services.server/email,server/payment, andserver/aiisolate provider logic.server/utilscontains server-only configuration such as Better Auth.
Handlers are not completely uniform. For new protected JSON endpoints, prefer
an explicit pattern: authenticate with requireAuth/getAuthContext, validate
input with Zod, and return a stable response such as { success, data }.
Shared code and content
shared/ is available to both the Vue app and Nitro server. Use it for types
and configuration that cannot depend on browser-only or server-only APIs.
content/ holds the per-locale Nuxt Content collections; public/ holds files
served unchanged from the site root.
Import aliases
| Alias | Resolves to | Use for |
|---|---|---|
~ / @ | app/ | Components, composables, frontend config |
~~ / @@ | Project root | Server and root-level modules |
#shared | shared/ | Cross-boundary types and config |
Prefer the narrowest alias that expresses ownership. For example,
@/components/ui/button is app code, while ~~/server/email is server code.
