Neutrino Platform
Documentation for Neutrino Platform
Date: 2026-03-30 Status: Agreed — Ready for Detailed Expansion Scope: Full platform architecture from meta-platform layer down to feature packages
1. Vision
Neutrino is a platform orchestration layer that allows clients to compose infrastructure-backed applications from a curated catalogue of feature packages — either predefined by Neutrino or authored by the client and submitted for review.
The key mental model:
Neutrino = Infrastructure provisioner + Feature package runtime + Multi-tenant shell + CLI toolchainA client subscribes to Neutrino. Neutrino provisions their Cloudflare infrastructure and a managed code repository. The client's users interact with a console shell that statically bundles whatever feature packages the tenant has activated — auth, billing, analytics, or any NNO-built features.
Features can be activated individually (standalone) or grouped into Stacks — named, versioned collections of features that share a common set of Cloudflare resources (D1, R2, KV). Stacks are the preferred activation path for multi-feature applications. See stacks.md.
2. System Layers
┌────────────────────────────────────────────────────────────────────────────┐
│ Layer 0: Neutrino Core (NNO) │
│ The meta-platform. Neutrino itself, deployed on its own Cloudflare infra. │
│ Manages all downstream platforms. Shares the same CF account (Phase 1). │
└───────────────────────────────────┬────────────────────────────────────────┘
│ provisions & manages
┌───────────────────────────────────▼────────────────────────────────────────┐
│ Layer 1: Platform │
│ A client's top-level environment. One platform = one client/product. │
│ Resources co-hosted on NNO's Cloudflare account, isolated by naming. │
└───────────────────────────────────┬────────────────────────────────────────┘
│ partitions into
┌───────────────────────────────────▼────────────────────────────────────────┐
│ Layer 2: Tenant / Sub-Tenant │
│ Logical isolation within a platform. Can be a business unit, region, │
│ customer, or team. Sub-tenants nest under tenants. │
│ Each gets its own provisioned resource set. │
└───────────────────────────────────┬────────────────────────────────────────┘
│ runs
┌───────────────────────────────────▼────────────────────────────────────────┐
│ Layer 3: Console Shell │
│ Thin React shell. Statically bundles activated feature packages at build. │
│ Deployed to Cloudflare Pages. Rebuilt by CF Pages on every repo change. │
└───────────────────────────────────┬────────────────────────────────────────┘
│ composed of
┌───────────────────────────────────▼────────────────────────────────────────┐
│ Layer 4: Feature Packages & Stacks │
│ Feature packages authored by NNO. │
│ Each package = UI + optional backend Worker + optional storage. │
│ Stacks group features into cohesive applications sharing CF resources. │
│ See stacks.md for full Stack architecture. │
└────────────────────────────────────────────────────────────────────────────┘3. Layer 0 — Neutrino Core (NNO)
Neutrino itself is deployed on Cloudflare using the same naming convention it enforces for clients:
nno-{nno-platform-id}-{service}[-stg]Suffix convention: no suffix for production,
-stgfor staging. Example:nno-k3m9p2xw7q-registry(prod),nno-k3m9p2xw7q-registry-stg(staging).
\{nno-platform-id\}=k3m9p2xw7q— this is the fixed NanoID assigned to the Neutrino meta-platform itself. All NNO Core resource names resolve to the prefixnno-k3m9p2xw7q-. Example:nno-k3m9p2xw7q-registry-stg.
Cloudflare Account Model
Phase 1 (current): NNO Core and all client platform resources share the same Cloudflare account. Isolation is enforced entirely through the naming convention (\{platform-id\}-\{stack-id\}-...). This keeps operational complexity low while the platform is being established.
Phase 2 (future): Migrate to per-client Cloudflare accounts (BYOC — see Section 4) once account-level isolation is required for enterprise compliance.
NNO Core Services
┌────────────────────────────────────────────────────────────────────┐
│ NNO CORE │
│ │
│ ┌──────────────┐ ┌──────────────────────────────────────────┐ │
│ │ Gateway │ │ Zero (backoffice + tenant mgmt) │ │
│ │ (Hono Worker)│ │ (@neutrino-io/feature-zero — separate │ │
│ └──────┬───────┘ │ repo: nno-app-zero, CF Pages app) │ │
│ │ └──────────────────────────────────────────┘ │
│ ┌──────▼─────────────────────────────────────────────────────┐ │
│ │ NNO Internal Services │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ Registry │ │ IAM │ │Provision │ │ Billing │ │ │
│ │ │ Service │ │ Service │ │ Service │ │ Service │ │ │
│ │ └────┬─────┘ └──────────┘ └──────────┘ └──────────────┘ │ │
│ │ │ │
│ │ ┌───────────────────────┐ ┌──────────────────────────┐ │ │
│ │ │ Stack Registry Service│ │ CLI Service (repo+builds) │ │ │
│ │ └───────────────────────┘ └──────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────▼──────────────────────────────────────────────────────┐ │
│ │ NNO Registry D1 (source of truth) │ │
│ │ platforms · tenants · resources · features · billing │ │
│ └─────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────┘| NNO Service | Responsibility |
|---|---|
| Gateway | Single API entry point. Routes to internal services. Auth via NNO IAM. Full middleware pipeline (9 registrations: rate limiting, security, tracing, and more) with service-to-service JWT auth via ServiceTokenCache. See gateway.md. |
| Registry | Source of truth: all platforms, tenants, sub-tenants, resources, active features |
| IAM | Identity and access for NNO itself. Issues API keys per platform. |
| Auth Service (Template) | Per-platform auth worker template (services/auth/). Not an NNO-operated service — deployed by CLI Service during platform onboarding. See services/auth.md |
| Provisioning | Calls Cloudflare API to create Workers, Pages, D1, R2, KV resources (Phase 1). Queue provisioning planned for Phase 2. |
| Stack Registry | Versioned catalogue of NNO-authored Stack templates. NNO operators publish stack definitions; platform admins activate them. No submission or review pipeline — NNO-only authorship. See stack-registry.md |
| Billing | Unified service: per-platform Stripe billing (subscriptions, payments) + NNO-level usage metering, quota enforcement, and invoicing |
| CLI Service | Manages per-platform GitHub repos. Applies feature config changes, triggers CF Pages builds |
3.1 Gateway Detail
Routes all API traffic to internal NNO services. Routing table, auth middleware, CORS, health endpoint, resilience, and service bindings are documented in gateway.md.
4. Layer 1–2 — Platform & Tenant
Provisioning Model
Phase 1 — Full Control (current)
NNO owns and operates the Cloudflare account. When a client onboards:
- NNO creates all Cloudflare resources (Workers, Pages, D1, R2, KV) via the CF API
- NNO holds the
CF_API_TOKENandCF_ACCOUNT_ID - Client interacts only with NNO Portal and their console URL
- Resources are named using the NNO convention and tracked in the Registry
Phase 2 — BYOC (future)
Client provides their own Cloudflare account credentials:
- Client generates a scoped
CF_API_TOKENfrom their own account - NNO Provisioning deploys into the client's account using their token
- NNO Registry still tracks all resources (reference only, not ownership)
- Client retains full Cloudflare account sovereignty
- Required for enterprise compliance, data residency, or cost ownership requirements
Per-Stack Resource Set
[Updated for DNS architecture] Resources are now organised by Stack rather than by individual tenant entity. The entity hierarchy is Platform → Tenant → Stack → apps + services.
Every stack provisioned for a platform gets a corresponding set of Cloudflare resources:
{platform-id}-default-auth ← Auth Worker (default stack, always provisioned)
{platform-id}-default-auth-db ← Auth D1 Database (default stack, always provisioned)
{platform-id}-{stack-id}-db ← Shared D1 (per stack, if sharedD1: true)
{platform-id}-{stack-id}-storage ← Shared R2 (per stack, if sharedR2: true)
{platform-id}-{stack-id}-kv ← Shared KV (per stack, if sharedKV: true)
{platform-id}-{stack-id}-{name} ← App/service Worker (per app or service in stack)Staging variants append -stg (e.g. \{platform-id\}-default-auth-stg). Production resources carry no environment suffix.
Each resource is tracked in the NNO Registry with its CF resource ID, status, and config.
Stack Resource Independence
Platform: k3m9p2xw7q (AcmeCorp)
Default stack (auth, auto-created):
├─ k3m9p2xw7q-default-auth ← Auth Worker (prod)
└─ k3m9p2xw7q-default-auth-db ← Auth D1 (prod)
Stack x7y8z9w0q1 (Marketing):
├─ k3m9p2xw7q-x7y8z9w0q1-dashboard ← Pages app (prod)
├─ k3m9p2xw7q-x7y8z9w0q1-db ← Shared D1 (prod)
└─ k3m9p2xw7q-x7y8z9w0q1-kv ← Shared KV (prod)
Stack r4s5t6u7v8 (Analytics Pro):
├─ k3m9p2xw7q-r4s5t6u7v8-analytics ← Worker (prod)
├─ k3m9p2xw7q-r4s5t6u7v8-db ← Shared D1 (prod)
└─ k3m9p2xw7q-r4s5t6u7v8-storage ← Shared R2 (prod)The Platform → Tenant → Stack entity hierarchy is tracked in the NNO Registry. Resource names encode only platform-id and stack-id — the full hierarchy lives in the registry, not in the resource name.
5. Layer 3 — Console Shell
The current apps/console is the Neutrino shell application. It already contains a feature registry pattern; this architecture formalises and extends it.
Shell Responsibilities
┌────────────────────────────────────────────────────────────────────┐
│ CONSOLE SHELL │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Chrome Layer │ │
│ │ Sidebar · Header · Theme · Search · Notifications │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Feature Runtime │ │
│ │ Feature Registry → Route Generator → Sidebar Generator │ │
│ │ Permission Gate → Feature Loader → Context Injector │ │
│ │ (Registry resolves FeatureDefinition.navigation[] for │ │
│ │ collapsible sub-menus; resolves icon strings to lucide) │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Foundation │ │
│ │ Auth Gate · TanStack Router · TanStack Query · Providers │ │
│ └──────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
Feature Pkg A Feature Pkg B Feature Pkg C
(static import) (static import) (static import)What the Shell Does NOT Do
- It does not contain business logic
- It does not know what features exist until they register
- It does not decide which features load — the tenant's feature manifest (baked in at build time from NNO Registry) decides
Shell Configuration Source (Current — Auto-Discovery + Static Build)
At build time:
1. Vite neutrino-feature-discovery plugin scans installed @neutrino-io/feature-* packages
2. Generates virtual:feature-registry module with static imports + manifests
3. features.config.ts merges: auto-discovered manifests + local features + overrides
(NNO CLI Service may also update features.config.ts and package.json — Phase 2)
4. Vite bundles all discovered feature packages statically
At runtime:
1. Shell boots with the statically bundled feature set
2. Authenticates the user via auth service
3. Reads embedded feature manifest → activates registered features
4. Generates routes and sidebar dynamically from registered features
5. Renders the app6. Layer 4 — Feature Packages
The Feature Package Contract
Every feature package — Type 1, 2, or 3 — must export a FeatureDefinition:
// features/[name]/src/feature.ts
export interface FeatureDefinition {
// Identity
id: string; // unique slug, e.g. 'analytics'
version: string; // semver
displayName: string;
description: string; // short description shown in marketplace / help
icon?: string; // lucide icon name (optional)
// Shell Integration
routes: FeatureRoute[]; // TanStack Router route definitions
navigation: FeatureNavItem[]; // sidebar entries this feature contributes
permissions: FeaturePermission[]; // required permissions, e.g. ['analytics:read']
// Backend
serviceEnvKey?: string; // env var name for service URL, e.g. 'VITE_ANALYTICS_API_URL'
requiresService?: boolean; // false = UI-only feature
// Lifecycle (optional)
onRegister?: (shell: ShellContext) => void;
onActivate?: (shell: ShellContext) => void;
onDeactivate?: (shell: ShellContext) => void;
providers?: FeatureProvider[]; // context providers to inject at shell level
}Contract source:
@neutrino-io/sdk/feature— the single source of truth forFeatureDefinition,FeatureRoute,FeatureNavItem,FeaturePermission,FeatureProvider, andShellContext.
Package Types
┌─────────────────────────────────────────────────────────────────────┐
│ TYPE 1: Core Packages (NNO-maintained, always present) │
│ @neutrino-io/feature-settings · @neutrino-io/ui-auth* · ... │
│ Stable API. Versioned. Bundled into every platform shell. │
│ * @neutrino-io/ui-auth is a UI library that exports authFeatureDefinition; │
│ it is not a pluggable feature package like the features/ packages │
├─────────────────────────────────────────────────────────────────────┤
│ TYPE 2: Domain Packages (NNO-maintained, selectable) │
│ @neutrino-io/feature-billing · @neutrino-io/feature-stacks · ... │
│ Activatable per tenant via NNO Portal. Maps to a backend Worker. │
│ Maintained and versioned by NNO. │
├─────────────────────────────────────────────────────────────────────┤
├─────────────────────────────────────────────────────────────────────┤
│ TYPE 3: Client Packages (client-authored, curated) │
│ @acme/feature-dashboard · @acme/feature-inventory · ... │
│ Developed using NNO CLI + @neutrino-io/sdk. Submitted for NNO review │
│ before listing. Private to the submitting platform by default. │
└─────────────────────────────────────────────────────────────────────┘No open marketplace. All feature packages — including client-authored ones — go through NNO review before they can be activated on any platform. This ensures quality, security, and compatibility with the shell contract.
Feature Package Location
All activatable feature packages live in the features/ workspace (features/*), separate from shared libraries in packages/. Each feature package:
- Exports a
FeatureDefinition(typically fromsrc/feature.ts) — runtime contract - Exports a
featureManifest(fromsrc/index.ts) — build-time discovery metadata - Declares
"neutrino": \{"type": "feature"\}in itspackage.jsonto opt in to auto-discovery - Uses
dts: falsein tsup (not statically imported by TypeScript consumers) - Is automatically registered via the Vite
neutrino-feature-discoveryplugin — no manual entry infeatures.config.tsneeded
| Package | Type | Location | Status |
|---|---|---|---|
@neutrino-io/feature-settings | Type 1 | features/settings/ | ✅ Built, wired in shell |
@neutrino-io/feature-billing | Type 2 | features/billing/ | ✅ Built, registered with enabled: false |
@neutrino-io/feature-stacks | Type 2 | features/stacks/ | 🔧 Planned |
Feature Auto-Discovery
Feature packages are auto-discovered at build time by the Vite neutrino-feature-discovery plugin. Packages following the @neutrino-io/feature-* convention with a "neutrino": \{"type": "feature"\} marker in their package.json are automatically imported and registered — no manual configuration needed. The shell can override any auto-discovered defaults via features.overrides.ts.
The discovery pipeline runs during Vite's configResolved phase:
pnpm add @neutrino-io/feature-billing
│
▼
Vite plugin scans apps/console/package.json
→ finds @neutrino-io/feature-billing
→ reads its package.json: neutrino.type === "feature" ✓
│
▼
Generates virtual:feature-registry
→ static import * as _f0 from '@neutrino-io/feature-billing'
→ exports discoveredManifests array
│
▼
features.config.ts merges:
1. Auto-discovered manifests (from virtual module)
2. Console-local features (home, help, error pages)
3. Shell overrides (features.overrides.ts)
│
▼
FeatureRegistry boots with complete feature setSee Shell Feature Config — Auto-Discovery for the full specification, including the
FeatureManifesttype and override authority model.
Feature ↔ Service Mapping
Each feature package that requires a backend maps 1:1 to a Cloudflare Worker:
| Feature Package | Worker Service (prod) | D1 Database (prod) | Notes |
|---|---|---|---|
@neutrino-io/ui-auth | \{pid\}-default-auth | \{pid\}-default-auth-db | Always required, default stack |
@neutrino-io/feature-settings | (none) | — | UI-only, reads from auth |
@neutrino-io/feature-billing | \{pid\}-\{stackId\}-billing | shared stack D1 or dedicated | Optional |
| Client custom app/service | \{pid\}-\{stackId\}-\{name\} | \{pid\}-\{stackId\}-db (shared) | Provisioned on activation |
7. Development & Deployment Model
Each client platform is deployed via a dedicated NNO-managed GitHub repository created from the nno-stack-starter template. Feature activation triggers the NNO CLI Service to commit features.config.ts to the platform repo. A GitHub Actions workflow in the repo (inherited from nno-stack-starter) runs wrangler pages deploy to CF Pages on every push — the same pattern used by the NNO operator console. Phase 2 will evolve this to Remote Module Federation for hot-swappable features without shell rebuilds.
Phase 1 deployment detail and roadmap: System Architecture Phase 1 Plan.
NNO CLI Toolchain
The NNO CLI (nno) is the universal command-line interface for the Neutrino platform. It uses a namespaced architecture — nno <namespace> <command> — so capabilities can be added incrementally without breaking existing commands.
nno project ← local dev, build, deploy for a platform project (P1)
nno feature ← scaffold, develop, validate, submit feature packages (P1)
nno marketplace ← browse catalogue, manage submissions (P1)
nno platform ← platform provisioning and management (P2)
nno ops ← NNO operator tooling (P2)Project workflow (platform developers):
# Start local dev — validates config, applies migrations, starts all services
nno project dev
# Build console shell for staging
nno project build --env stg
# Validate config + secrets before deploying
nno project check --env stg
# Full deploy: check → build → wrangler deploy → migrations → pages deploy
nno project deploy --env stg
nno project deploy --env prodFeature package workflow (feature developers):
# Scaffold a new feature package
nno feature init my-feature
# Start local dev with mock NNO shell
nno feature dev
# Validate FeatureDefinition contract
nno feature validate
# Submit to NNO Marketplace for review
nno feature submit --message "Initial submission"
# (NNO admin) Approve and list
nno marketplace approve sub_9x2m4k7p1qProvisional design — subject to revision.
nno feature submitand the full marketplace submission/review pipeline are Phase 2 capabilities, contingent on lifting the NNO-only authorship restriction (see Q4 in the Architecture Decisions Log, Section 13). Phase 1 supports only NNO-authored feature packages.
Feature development flow:
nno feature init my-feature
│ scaffolds package using feature-sdk template
▼
nno feature dev
→ mock shell + feature Vite dev + local Wrangler service
│
▼
nno feature validate
→ checks FeatureDefinition contract (V01–V20)
→ checks service binding config
→ checks permission declarations
│
▼
(Phase 2) nno feature submit
→ packages and uploads to NNO Stack Registry review queue
→ NNO team reviews (security, contract compliance, quality)
│
▼
(Phase 2) nno marketplace approve (NNO admin action)
→ lists package in Stack Registry
→ available for activation on eligible platforms8. End-to-End Data Flow
Client Onboarding Flow
Phase 2 adds self-serve onboarding: user registers → email verification → onboarding wizard (stack selection, tier, billing setup) → automated ONBOARD_PLATFORM job → real-time progress tracking → platform active.
Client signs up on NNO Portal
│
▼
NNO IAM creates platform record
→ generates platform NanoID (10 chars)
→ generates default tenant NanoID
→ Platform created in 'pending' status (awaiting email verification and billing setup)
│
▼
User completes onboarding wizard (email verification, stack selection, billing setup)
NNO Provisioning runs ONBOARD_PLATFORM job:
→ creates platform + entity records in Registry
→ creates Stripe customer + subscription in Billing
→ enqueues BOOTSTRAP_PLATFORM job for CF resource creation
→ Platform transitions to 'provisioning' status while CF resources are created
│
▼
NNO Provisioning (BOOTSTRAP_PLATFORM) creates Cloudflare resources
→ deploys auth Worker (k3m9p2xw7q-default-auth)
→ creates auth D1 (k3m9p2xw7q-default-auth-db)
→ connects CF Pages project for console app
→ runs auth migrations, sets secrets
→ registers DNS hostname (auth.svc.default.k3m9p2xw7q.nno.app) via CF4SaaS
→ Platform transitions to 'active' status. The client can now access their platform console.
│
▼
NNO CLI Service creates platform repo
→ creates nno-platform-k3m9p2xw7q in NNO GitHub org
→ configures with Core packages (auth, settings)
→ triggers initial CF Pages build
│
▼
NNO Registry records all provisioned resources + active features
│
▼
Client accesses their console at:
https://<name>.app.default.<platformId>.nno.app (NNO-assigned DNS hostname via CF4SaaS)
https://app.acmecorp.com (optional custom domain via CF4SaaS)Feature Activation Flow
Admin activates a feature (e.g. 'analytics') via NNO Portal
│
▼
NNO Registry validates feature exists in the NNO feature catalogue and is compatible with the platform's plan
│
▼
NNO Provisioning creates:
→ analytics Worker (k3m9p2xw7q-x7y8z9w0q1-analytics)
→ analytics D1 (k3m9p2xw7q-x7y8z9w0q1-analytics-db)
→ runs analytics migrations, sets secrets
│
▼
NNO CLI Service updates platform repo:
→ adds @neutrino-io/feature-{feature} to package.json
→ updates features.config.ts
→ commits and pushes
│
▼
GitHub Actions deploy workflow triggers → wrangler pages deploy → updated shell live
→ analytics routes and navigation are now bundled in the shellRuntime Request Flow
User opens a feature page in console
│
▼
Console Shell (CF Pages)
→ TanStack Router matches route registered by the feature package
→ Renders feature page component
│
▼
Page makes API call to the feature Worker
→ Authorization header: Better Auth JWT
→ URL resolved from VITE_{FEATURE}_API_URL (set in CF Pages env vars)
│
▼
Feature Worker (CF Workers)
→ Validates JWT via auth service
→ Queries its own D1 database
→ Returns response9. Billing Model
Neutrino uses a hybrid model: a flat base tier covers infrastructure and platform access, with usage-based charges for overages.
Tiers
| Tier | Monthly Base | Included Resources | Typical Use Case |
|---|---|---|---|
| Starter | Fixed flat fee | 1 platform, 2 tenants, 3 features, limited invocations + storage | Early-stage / evaluation |
| Growth | Mid flat fee | 3 platforms, 10 tenants, unlimited features, moderate usage | Growing product |
| Scale | Higher flat fee | Unlimited platforms + tenants, priority support, audit logs | Enterprise |
Usage Overages (above tier limits)
| Metric | Unit | Measured Via |
|---|---|---|
| Worker invocations | Per million | Cloudflare Analytics Engine |
| D1 read operations | Per million rows | Cloudflare D1 usage metrics |
| D1 write operations | Per million rows | Cloudflare D1 usage metrics |
| R2 storage | Per GB/month | Cloudflare R2 metrics |
| R2 operations | Per million | Cloudflare R2 metrics |
| KV reads | Per million | Cloudflare KV metrics |
Metering Architecture
CF Analytics Engine / Cloudflare API
│ usage data (polling or push)
▼
NNO Billing Service
→ aggregates usage per platform-id + stack-id
→ stores daily snapshots in billing D1
→ runs monthly invoice generation
→ marks tier upgrades when thresholds are crossed
│
▼
NNO Portal → Billing dashboard (usage charts, invoices, upgrade prompts)Phase 1: Manual invoice generation + Stripe. Phase 2: Automated metering with real-time usage dashboard and auto-upgrade suggestions.
10. Existing Codebase Mapping
Implementation status and gap tracking: System Architecture Phase 1 Plan.
11. Repository Structure (Target)
nno-app-builder/ ← NNO core monorepo
├── apps/
│ └── console/ ← Reference shell (used as template for platform repos)
│ NNO operator console = console shell + role-gated routes
│
├── packages/
│ ├── sdk/ ← @neutrino-io/sdk — FeatureDefinition contract + shared utils/hooks/types
│ │ (merged from ui-shared + feature-sdk)
│ │ subpaths: ./feature · ./utils · ./hooks · ./hooks/auth · ./types · ./constants
│ ├── ui-core/ ← @neutrino-io/ui-core — Layer 1: base components (Radix, Shadcn, Recharts)
│ ├── ui-auth/ ← @neutrino-io/ui-auth — auth providers, guards, hooks, Better Auth integration
│ ├── core/ ← @neutrino-io/core — naming, types, constants
│ │ subpaths: ./naming · ./types · ./constants
│ └── cli/ ← @neutrino-io/cli — single binary + NnoPlugin registry
│ subpaths: . (bin) · ./plugin (external plugin authoring)
│
├── features/ ← Activatable feature packages (dynamically loaded by the shell)
│ ├── settings/ ← @neutrino-io/feature-settings — Type 1: always-present settings UI
│ ├── billing/ ← @neutrino-io/feature-billing — Type 2: per-tenant billing UI
│
├── services/
│ ├── iam/ ← NNO IAM Worker: auth-core + /api/nno/session (global)
│ ├── auth/ ← Auth Worker (thin per-platform wrapper; imports @neutrino-io/service-iam/core)
│ ├── billing/ ← Billing Worker: per-platform Stripe + NNO-level metering/invoicing
│ ├── registry/ ← NNO Registry Worker: source of truth (platforms, tenants, resources, features)
│ ├── gateway/ ← NNO API Gateway Worker: stateless proxy + auth enforcement
│ ├── provisioning/ ← NNO Provisioning Worker: CF resource job state machine
│ ├── stack-registry/ ← NNO Stack Registry Worker: NNO-authored stack template catalogue (no submissions/review)
│ └── cli/ ← NNO CLI Service (directory: cli/, worker name: nno-{platformId}-cli-service-{env})
│
├── tooling/
│ ├── github/
│ └── tsconfig/
│
└── docs/
└── architecture/
├── overview.md ← this document
├── README.md
├── concepts/
│ ├── feature-sdk.md ← Feature Package SDK spec
│ ├── stacks.md ← Stack architecture
│ ├── cli.md ← NNO CLI spec
│ ├── shell-config.md ← Shell feature config & auto-discovery
│ └── module-federation.md ← Module Federation (Phase 2 stub)
├── services/
│ ├── auth.md ← Multi-tenant auth model
│ ├── billing.md ← Billing & metering spec
│ ├── cli-service.md ← CLI Service spec
│ ├── gateway.md ← Gateway routing, auth, resilience
│ ├── provisioning.md ← NNO Provisioning state machine
│ ├── registry.md ← NNO Registry schema & API
│ └── stack-registry.md ← Stack Registry (was marketplace.md)
├── cross-cutting/
│ ├── cloudflare-naming.md ← naming convention
│ └── observability.md ← Observability spec (future design)
├── operator/
│ └── zero.md ← NNO operator backoffice (Zero) — see nno-app-zero repo
└── decisions/Per-stack repos (managed by NNO, separate GitHub repos):
nno-stack-{stack-id}/ ← generated from nno-stack-starter template
├── src/
│ └── config/
│ └── features.config.ts ← managed by NNO CLI Service
├── package.json ← managed by NNO CLI Service
└── wrangler.toml ← CF Pages project config12. Technology Decisions
| Concern | Technology | Rationale |
|---|---|---|
| Shell Framework | React 19 + Vite | Current, performant, strong ecosystem |
| Routing | TanStack Router | Type-safe, file-based + programmatic; feature registry already uses it |
| Server State | TanStack Query | Already established; features bring their own queries |
| Service Framework | Hono.js on CF Workers | Lightweight, CF-native, already in use |
| Database | Cloudflare D1 (raw D1 API for most services; Drizzle ORM in services/iam and services/registry) | Edge-native, zero cold starts; already in use |
| Auth | Better Auth | Multi-provider, CF Workers compatible; already in use |
| ID Generation | NanoID (10 chars, [a-z0-9]) | CF-safe alphabet, collision-resistant (see naming doc) |
| Type Safety | TypeScript + Zod | End-to-end; existing standard |
| Feature Loading (Phase 1) | Static bundling via Vite | Simple, fast, no runtime complexity |
| Feature Loading (Phase 2) | Vite Plugin Federation | Module Federation for hot-swappable remote packages |
| Platform Repo Hosting | GitHub (NNO org) | neutrino-io org; repos created from nno-stack-starter template |
| Shell CI/CD | GitHub Actions → wrangler pages deploy → CF Pages | Same pattern as apps/console; org-level CF_API_TOKEN secret inherited by all platform repos; no CF dashboard OAuth per project |
13. Architecture Decisions Log
| # | Question | Decision | Phase |
|---|---|---|---|
| Q1 | Feature loading model | Static bundling now. NNO CLI manages platform repos; CF Pages builds on push. Remote Module Federation in a future phase. | P1 now, P2 future |
| Q2 | NNO hosting | Same Cloudflare account as client platforms. Isolation via naming convention only. Separate accounts considered for Phase 2. | P1 |
| Q3 | Provisioning scope | Full control — NNO manages the CF account and holds credentials. BYOC (client-owned CF account) is a future phase for enterprise. | P1 now, P2 future |
| Q4 | Feature authorship model | NNO-only. All feature packages are NNO-authored. No client-submitted feature packages. Platform clients activate NNO features via standalone activation or Stack templates. | P1 |
| Q5 | Billing model | Hybrid. Flat monthly base tier per platform + usage-based overages for Workers, D1, R2, KV. Metered via Cloudflare Analytics Engine. | P1 |
| Q6 | Feature registration mechanism | Auto-discovery via Vite plugin (Phase 1.5). Feature packages opt in by declaring "neutrino": \{"type": "feature"\} in package.json and exporting featureManifest. The shell retains full override authority via features.overrides.ts. Manual registration in features.config.ts is no longer required for @neutrino-io/feature-* packages. | P1.5 |
14. NNO API Conventions
Error Response Envelope
All NNO services return errors in a single canonical JSON shape. This format applies to every Hono Worker in the NNO stack (Gateway, Registry, IAM, Provisioning, Billing, CLI Service, Stack Registry).
{
"error": {
"code": "NOT_FOUND",
"message": "Platform not found",
"details": { "platformId": "k3m9p2xw7q" },
"requestId": "req_abc123xyz"
}
}| Field | Type | Required | Description |
|---|---|---|---|
code | string | ✅ | Machine-readable error identifier. Use SCREAMING_SNAKE_CASE. |
message | string | ✅ | Human-readable description. Safe to surface to API consumers. |
details | Record<string, unknown> | optional | Structured context (field names, IDs, limits) — aids debugging. |
requestId | string | optional | Echoes the x-request-id / requestId assigned by the request logger. |
Enforcement: A Zod schema NnoErrorEnvelopeSchema and an ErrorCode enum are exported from @neutrino-io/core/errors. Import these when building response helpers or writing integration tests.
import {
NnoErrorEnvelopeSchema,
ErrorCode,
makeErrorEnvelope,
} from "@neutrino-io/core/errors";
// Build a compliant error response in a Hono handler
return c.json(
makeErrorEnvelope(ErrorCode.NOT_FOUND, "Platform not found", {
details: { platformId },
requestId: c.get("requestId"),
}),
404,
);Common codes (full enum in @neutrino-io/core/errors):
| Code | HTTP | When |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid auth credentials |
FORBIDDEN | 403 | Authenticated but lacks permission |
NOT_FOUND | 404 | Resource does not exist |
VALIDATION_ERROR | 422 | Zod / input validation failed |
CONFLICT | 409 | Duplicate key, state conflict |
RATE_LIMITED | 429 | Rate limit exceeded |
INTERNAL_ERROR | 500 | Unhandled server error |
Service-specific codes (e.g. JOB_NOT_FOUND, STRIPE_ERROR, QUOTA_EXCEEDED) are defined in each service's own constants but must still be returned inside the same \{ error: \{ code, message, ... \} \} envelope.
15. Areas for Detailed Expansion
Roadmap and expansion areas: System Architecture Phase 1 Plan.
Status: Agreed — architecture decisions locked, detailed expansion in progress For implementation phase tracking, see Implementation Plans. Document Owner: Neutrino Platform Team