Architecture

Architecture overview

Edit page
How the thin host, portal core, and feature layers combine into one Customer Portal application.

Customer Portal is a Nuxt application assembled from layers. Start with the working client-access, timesheet, and invoicing modules, then add capabilities for your own business. The shared platform handles authentication, organizations, and client management so each module can concentrate on its workflow.

Three responsibilities

The host

The host is intentionally small. It owns the Nuxt entry point, branding, public site, layouts, error handling, and global assets. Migration order comes from installed provider manifests rather than a host-owned combined journal.

Portal core

packages/core is visually headless. It owns:

  • session and active-organization state;
  • authorization helpers and database access;
  • the feature and surface registry;
  • shared types for navigation, modules, widgets, audiences, and policies.

packages/ui owns neutral fallback layouts, dashboard rendering, menus, modals, notifications, and shell primitives. Hosts can override its presentation without replacing core infrastructure.

Feature layers

A feature layer owns a vertical slice of the product. It may contribute pages, components, composables, server routes, translations, shared types, tests, and tables in its own PostgreSQL schema.

Host application
├── core
│   ├── session, tenancy, and authorization
│   ├── database adapters
│   └── feature and surface registry
├── ui
│   └── neutral fallback shell
└── feature layers
    ├── organizations and clients
    ├── timesheets (optional)
    ├── invoices (optional)
    ├── invoice-timesheets (optional bridge between both)
    └── your own modules

Runtime composition

Each feature registers a PortalFeatureDefinition through a Nuxt plugin. Core and UI collect those definitions and derive:

  • global navigation;
  • module-aware sidebars based on the current route;
  • dashboard widgets grouped by area and order;
  • role policies used by server authorization.

This means a feature can be installed or removed without adding imports to the shell.

Data ownership

Portal core and authentication tables live in PostgreSQL’s public schema. Each business feature owns a schema derived from its layer name, such as timesheets or invoices.

Each database-backed package owns an immutable migration stream. The kit orders provider streams while keeping a separate journal table for each provider.

For a compact example extension, study Service Requests. To write your own module, follow create a feature layer.

Continue with feature layers, core contracts, or tenancy and security.