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

nuxt.config.ts
content.config.ts
components.json

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:

LayoutPurpose
default.vueMarketing and general pages
auth.vueLogin, registration, verification, and password reset
docs.vueDocumentation sidebar, content, and table of contents
user.vueAuthenticated 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.ts attaches auth context and exports auth helpers.
  • server/database/drizzle contains the PostgreSQL client, schema, and services.
  • server/email, server/payment, and server/ai isolate provider logic.
  • server/utils contains 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

AliasResolves toUse for
~ / @app/Components, composables, frontend config
~~ / @@Project rootServer and root-level modules
#sharedshared/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.

On this page