Modules

Platform layers

Edit page
Understand the reusable foundation packages, their ownership boundaries, and host-owned presentation.

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

PackageOwns
coreSessions, Better Auth infrastructure, tenancy, authorization, database access, feature registry, shared contracts, and generic OpenAPI merging
uiNeutral shell primitives, contribution rendering, and fallback layouts
authenticationLogin, signup, email verification, and password recovery UI
organizationsPROVIDER profile, organization selection, settings, and email-provider credentials
clientsCLIENT profiles, memberships, invitations, archival, and module activation
administrationSystem user, organization, invitation, and centralized email administration
saas-configurationPortal onboarding, branding, homepage content, legal pages, themes, and module selection
presetComposition of core, UI, authentication, organizations, and clients
kitPortal configuration, diagnostics, PROVIDER seeding, migrations, starter generation, and host-owned page copying

timesheets and invoices are independent optional business packages. Add invoice-timesheets to connect approved time to invoicing. The optional service-requests package is an example extension for developers. A host selects its packages 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 PROVIDER settings; clients owns CLIENT organizations and their contacts. administration provides system-level management surfaces, and saas-configuration provides the configurable portal experience and onboarding. There is no installation-wide administrator bypass.

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.

Clients and feature integrations

An installation has exactly one PROVIDER; every other organization is a CLIENT. Client-aware features advertise a stable module ID and may contribute module-specific configuration to client details. Disabling a module blocks new client activity without deleting history.

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

  1. Shared sessions, tenancy, authorization, database, registry, or contracts belong in core.
  2. Reusable presentation and fallback shells belong in UI.
  3. Account entry belongs in authentication.
  4. PROVIDER settings belong in organizations.
  5. CLIENT profiles, contacts, and activation belong in clients.
  6. Optional domain workflows belong in their own package.
  7. 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.