Tour the project
The repository is organized so a feature has a predictable path from contract to implementation to UI.
Repository map
| Path | Responsibility |
|---|---|
MyApp.ServiceModel | Authoritative SaaS entities and ServiceStack request/response DTOs |
MyApp.ServiceInterface | Services, policy, billing gateway, storage, telemetry, and job commands |
MyApp | ASP.NET Core host, plugins, Identity pages, migrations, configuration, and static assets |
MyApp.Client | Next.js application, React components, styles, and generated DTO client |
MyApp.Tests | Architecture, security, policy, Stripe, audit, and database tests |
scripts | Development reset, diagnostics, verification, and production preflight |
config | Deployment configuration |
features.json | Machine-readable module ownership and table classification |
docs | Developer onboarding and reference documentation |

Trace a typical API
RecordUsage demonstrates the normal flow:
MyApp.ServiceModel/Saas.csdefines the typed request and response.MyApp.ServiceInterface/SaasServices.csimplements authorization and behavior.MyApp.Client/lib/dtos.tscontains the generated TypeScript request class.- A React page imports that class and calls it through
MyApp.Client/lib/gateway.ts. - Tests exercise quota, idempotency, and isolation behavior.
After changing a C# request or response contract, regenerate the browser client while the backend is running:
cd MyApp.Client
npm run dtosNever make durable changes directly in MyApp.Client/lib/dtos.ts; regeneration replaces them.

Backend landmarks
SaasServices.cscontains customer-facing organization, plan, usage, member, and billing APIs.SaasPlatformServices.cscontains operator analytics, Customer 360, support access, audit, lifecycle, and retention administration.FileStorageServices.csdemonstrates safe quota reservation, streaming storage, export, and deletion jobs.SaasMaintenanceJobs.cscontains recurring operational commands.SaasAudit.cscentralizes registered audit actions and sensitive-value redaction.AppConfig.csdefines typed deployment-wide settings.Configure.Saas.csregisters SaaS dependencies and production configuration validation.
Host landmarks
Configuration follows the Configure.*.cs convention:
Configure.Db.csselects SQLite or PostgreSQL.Configure.Db.Migrations.csregisters migration app tasks and empty-state bootstrap.Configure.BackgroundJobs.csregisters workers and recurring commands.Configure.ApiKeys.csbinds ServiceStack API keys to organizations.Configure.HealthChecks.csdefines/upand/ready.Configure.Observability.csadds request correlation.Configure.RequestLogs.csconfigures ServiceStack request logs.
MyApp/Migrations/Migration1001.cs creates the SaaS schema and seeds plans.json. Because this template is still under heavy development, a clean database is the expected way to apply structural changes here. A derived live product should use new numbered migrations.
Frontend landmarks

app/page.tsxandapp/(content)provide the public site and Markdown-backed content routes.app/dashboard,documents,usage,billing,team, andsettingsare customer pages.app/admincontains the role-gated, static Operations Center routes.components/app-shell.tsxswitches between organization navigation and capability-aware Operations Center navigation.components/admin-center-page.tsxcomposes the shared heading and focused content for each operator route.components/saas-operations.tsxowns the route-scoped Customer 360, analytics, queue, retention, support, and audit workflows.lib/use-saas.tsxloads and shares organization state without recursive requests.lib/auth.tsxsupplies authentication and role guards.styles/index.csscontains Tailwind and template-wide styling.
The production Next.js build is a static export. Pages fetch dynamic customer data from ServiceStack APIs in the browser; they do not require a Node.js server in production.
Data ownership
features.json classifies every OrmLite table as one of:
- global — shared catalog definitions;
- tenant-owned — constrained to an organization;
- platform-operational — queues, logs, snapshots, and other operator state.
An architecture test fails when a new table is not classified. Update the relevant module, routes, configuration, jobs, and tests whenever a feature crosses those boundaries.
Where a change belongs
| Change | Canonical location |
|---|---|
| Product name, contact details, retention default | appsettings.json or environment configuration |
| Initial clean-database plans | MyApp/plans.json |
| Runtime plan price, quota, trial, or feature | /admin/plans Plans tab, persisted in the RDBMS |
| Coupon or promotion code | /admin/plans Coupons tab, owned by Stripe and locally audited |
| Customer contract exception | /admin/customers, persisted with actor and reason |
| API contract | MyApp.ServiceModel |
| Business and authorization policy | MyApp.ServiceInterface |
| Customer or operator experience | MyApp.Client |
| Identity account page | MyApp/Areas/Identity/Pages |
Run the template locally
This page takes a clean checkout to a working development application and explains how to return to a clean state.
Customize the product
Make the template visibly yours before adding domain behavior. Product identity is deployment-wide configuration; plans and customer exceptions remain database state.