Skip to Content
TechnicalApplicationsApplications

Applications

The Sustentus monorepo contains eight applications. The platform itself is apps/web; the others are the agentic app, the tenant management console, the marketing site, role-based dashboards, two Nextra doc sites, and Storybook.

Overview

ApplicationPurposeStackPort
WebMain platform — all six persona portals + API/AINext.js 163000
AgentThe agentic layer, beside the platformNext.js 163007
ConsoleTenant management for Sustentus staff + partnersNext.js 163006
DashboardsRole-based analytics dashboardsNext.js 163005
MarketingPublic marketing siteNext.js 153001
DocumentationThis documentation siteNextra
HelpHelp & support centreNextra
StorybookComponent docs for @sustentus/uiStorybook 103002

Application details

Web (apps/web)

The main platform — Next.js 16 with the App Router and Turbopack. Hosts the portals for all six personas (admin, CSM, SDM, expert, vendor, customer), the server surface (route handlers + Server Actions), and the runtime AI (the BRD agent via @sustentus/services/ai). Imports UI from @sustentus/ui and data/logic from @sustentus/services/server. See [apps/web/AGENTS.md] in the repo for app-specific rules.

Agent (apps/agent)

Next.js 16 agentic app (port 3007) — the home of the agentic layer, deployed as the agentic-interface Vercel project. It sits beside the platform rather than inside it: proxy.ts (this repo’s Next 16 middleware file) gates every route, so the gate is deny-by-default at the edge rather than per-layout. It runs against the same Clerk instance as the platform, so on a shared root domain a signed-in platform user is already signed in here.

It serves two populations. A tenant user holds a Clerk org and a platform role, both read from the session claims — no database call at the edge. Sustentus staff and invited partners hold neither: they are org-less Clerk users carrying the publicMetadata console-access marker, which the gate reads live from Clerk so a revocation denies the next request. Everyone else gets an honest “no workspace” state, and /api/** answers 403.

Tenant scoping is the same one-tenant binding the platform uses: every AI tool is built by createTenantContext(tenantId) and a tool’s execute never receives a tenant id, so the model cannot point one at another tenant. Staff and partners choose which tenant they are working in — staff any tenant, a partner only those assigned to them, bounded by the same ConsoleTenantScope the console uses — and bind to that one. Their extra privilege is reach, not power: nothing extra inside the tenant they pick. The selection cookie is re-authorised against that scope on every request and never trusted on its own.

Imports UI from @sustentus/ui; @sustentus/services through /ai and /shared anywhere and /server in server-only files (never a client component). The root route is a streamed conversation with the Sustentus assistant, built from the shared @sustentus/ui AI primitives, reaching the model through the Vercel AI Gateway and reading its tenant’s catalogue through a tenant-bound tool. Conversations are saved, per user and per tenant: a conversation rail lists the caller’s recent threads (a drawer below the mobile breakpoint), /c/<threadId> reopens one with its full history, and each can be renamed or deleted. Reading is the author’s alone — there is no staff or cross-tenant view. The route is the writer: the client posts one new message and a thread id, the transcript is read back from the store, and only a bounded window of it is replayed to the model so a long-lived thread does not make every turn cost more than the last. Persistence degrades on its own: if a write fails the turn still streams, unsaved. Every assistant turn also writes an agent-run record — agent, model, tool calls with the tenant each was bound to, token usage and outcome — which is the join key the accounting and tracing work reads. The header links back to the platform when PLATFORM_APP_URL resolves (the same parsing rules as the console’s CONSOLE_APP_URL; unset, the link is simply absent).

It also serves GET /api/ai/availability, a signed-in-only route that reports whether the gateway can serve — ok, degraded or unknown, and nothing else. The conversation asks once on mount and warns above the composer when the answer is degraded, so a credit outage is visible before a user spends a turn discovering it. See AI Gateway.

Console (apps/console)

Next.js 16 tenant management console (port 3006) — the Sustentus-side operational surface, deployed as the tenant-management Vercel project. Its users are org-less Clerk users carrying a publicMetadata console-access marker, not platform roles: Sustentus staff see every tenant, partners see only the tenants assigned to them. Imports UI from @sustentus/ui and data from @sustentus/services/server. Learn more →

Dashboards (apps/dashboards)

Next.js 16 role-based dashboards (port 3005). Self-contained — it does not import @sustentus/ui; UI primitives live locally in components/ui/, and all text uses the local Typography component. Charts use Recharts.

Marketing (apps/marketing)

Next.js 15 public site (port 3001) — landing, pricing, and waitlist signup with Clerk auth. Imports UI from @sustentus/ui. Learn more →

Documentation (apps/docs)

This Nextra site — MDX content under app/business/ (direction, strategy, roles, journey) and app/technical/ (architecture, applications, packages, development). Built-in Pagefind search. Learn more →

Help (apps/help)

Nextra help & support centre for end users.

Storybook (apps/storybook)

Storybook 10 (port 3002) documenting every component exported from @sustentus/ui — one Default story per component, props exposed via Controls. Learn more →

Running applications

pnpm dev # all apps pnpm web:dev # main platform (3000) pnpm agent:dev # agentic app (3007) pnpm --filter @sustentus/console dev # console (3006) pnpm dashboards:dev # dashboards (3005) pnpm marketing:dev # marketing (3001) pnpm storybook:dev # storybook (3002)

Building

pnpm build # all apps and packages

Turborepo builds the shared packages (@sustentus/ui, @sustentus/services) before the apps that depend on them.

Last updated on