Platform layers
Nuxt Customer Portal follows Nuxt's npm-layer model. Each layer package exposes nuxt.config.ts, declares a stable $meta.name, and is composed through extends. The preset provides a useful starting point without owning the host's brand or public website.
Layer catalog
| Package | Owns |
|---|---|
core | Sessions, Better Auth infrastructure, tenancy, authorization, database access, feature registry, shared contracts, and generic OpenAPI merging |
ui | Neutral shell primitives, contribution rendering, and fallback layouts |
authentication | Login, signup, email verification, and password recovery UI |
organizations | Profile, organization selection, invitations, settings, and email-provider credentials |
administration | Installation-wide organization and user administration |
preset | Composition of core, UI, authentication, organizations, and administration |
kit | Portal configuration, diagnostics, provider resolution, migrations, and legacy adoption |
service-requests and timesheets are optional business packages. A host selects either, both, or neither in portal.config.ts.
Core and UI
core is visually headless. It must not render a branded application shell or import an optional business package. Feature code consumes @nuxt-customer-portal/core/feature, @nuxt-customer-portal/core/server, and @nuxt-customer-portal/core/schema.
ui turns serializable feature registrations into neutral navigation, dashboards, surfaces, modals, and fallback layouts. A production host can override those layouts and compose the same primitives differently. The Apex and Brutal demos prove this by sharing package selection but not demo-only shell components.
Open the core and UI contracts
Authentication and organizations
authentication owns account entry and recovery screens while core retains Better Auth configuration and identity records. organizations owns the signed-in user's profile, organization selection, invitations, and tenant settings. Neither grants installation-wide administration privileges.
Server operations always derive the active organization from the authenticated session. Organization identifiers supplied by the browser are not trusted when session context determines the tenant.
Administration and surfaces
administration owns system-administrator routes and APIs. Optional features must not be imported by administration to add feature-specific panels. Instead they register a PortalSurfaceContribution for a named surface such as administration.organization.detail; the UI resolves the component only when that package is installed.
Preset and kit
Use @nuxt-customer-portal/preset for the common platform. Add business packages independently. The kit converts portal.config.ts to Nuxt extends, resolves official and local manifests, checks dependency order, and manages one immutable migration stream per provider.
Public pages, branding, app.vue, layouts, headers, footers, error pages, assets, and global styling are host-owned. They intentionally have no public-site package.
Decide where a change belongs
- Shared sessions, tenancy, authorization, database, registry, or contracts belong in core.
- Reusable presentation and fallback shells belong in UI.
- Account entry belongs in authentication.
- Profile and tenant management belong in organizations.
- Installation-wide management belongs in administration.
- Optional domain workflows belong in their own package.
- Brand and marketing experiences belong in a host app.
If a change crosses boundaries, add the smallest serializable contract or surface registration instead of a private physical import. Continue with Create a feature layer or inspect the product source map.