# Project structure

URL: /code/project-structure · Id: `page:code/project-structure`

> Every top-level file and folder in a Startup project, what it holds, and the tab of the business it builds.

A [Startup](/business/nouns/startup) project holds a file only where the Startup differs from its [Startup Template](/business/nouns/startup-template). Its top-level folders follow the tabs of these docs, from `nouns/` to `code/`.

## The tree
```text
leaseline/
├── startup.ts                        the Startup: name, domain, Startup Template, own values
├── startups.lock                     Startup Template pins, by fingerprint
├── settings.mdx                      Settings not set in startup.ts
├── policies.mdx                      how the numbers are computed
├── env.ts                            Secret and Integration names, no values
│
├── nouns/                            BUSINESS
│   ├── Lease.mdx                     a Noun: properties, Verbs, states
│   ├── Lease.renew.ts                the Function behind Lease.renew
│   └── Lease.renew.test.ts           its cases
├── verbs/renew.mdx                   a Verb several Nouns share
├── evaluators/notice-tone.ts         a rubric and its grader
├── mappings/rent-roll.ts             a Source mapped into Nouns
│
├── products/pro.mdx                  PRODUCTS: App, API, Agent, Dataset or Service
├── offers/pro.mdx                    a Product at a Price, on terms
├── sites/www/                        a Site: Pages, layouts, navigation
├── apps/portal/                      an App over the Nouns
├── domains/leaseline.com.mdx         a Domain: what it hosts, redirects, email
├── content/blog/                     posts and changelog entries
│
├── agents/customer/                  AGENTS: a Team
│   ├── index.mdx                     the Team: lead Role, mission
│   ├── success-manager.mdx           a Role and the agent or person filling it
│   ├── success-manager.test.ts       its eval cases
│   └── skills/renewal-call/          a skill the Role loads
│
├── workflows/renewals/               WORKFLOWS: a Process
│   ├── index.mdx                     owner Role, Metric, target
│   ├── notice-at-60-days.mdx         a Workflow: prose, code and tests
│   └── weekly-unanswered.ts          a Workflow: code only
├── plays/manager-referrals.mdx       a Play: Process, Metric, budget
│
├── systems/billing.mdx               SYSTEMS: an override on one System
├── dashboards/renewals.mdx           a Dashboard for one scope
│
├── brand/                            CODE: Brand, Theme, Templates
├── components/RenewalCountdown.*     a Component: props, web rendering, CSS
├── tests/first-renewal.test.ts       scenario tests in test
├── code/partner-webhook/             a custom program
├── generated/                        rendered by the platform; pushes refused
├── _research/                        unmanaged
├── AGENTS.md, .mcp.json, package.json   coding agent setup
└── .sb/                              manifest, resolved Startup, types
```

## Top-level files
| [File](/business/nouns/file) | Holds | Convention |
| --- | --- | --- |
| `startup.ts` | The Startup and its own values. Also `startup.mdx` or `startup.json` | [startup.ts](/code/startup-ts) |
| `startups.lock` | Startup Template pins | [startups.lock](/code/file-conventions/startups-lock) |
| `settings.mdx` | [Settings](/business/nouns/setting) | [Settings](/code/file-conventions/settings) |
| `policies.mdx` | [Policies](/business/nouns/policy) | [Policies](/code/file-conventions/policies) |
| `env.ts` | [Secret](/business/nouns/secret) and [Integration](/business/nouns/integration) names | [env.ts](/code/file-conventions/env) |
| `AGENTS.md`, `.mcp.json`, `package.json` | Coding agent setup | [agent files](/code/file-conventions/agent-files) |

## Top-level folders
| Path | Holds | Convention |
| --- | --- | --- |
| `nouns/` | [Nouns](/business/nouns/noun), their [Verb](/business/nouns/verb) functions and tests | [Nouns](/code/file-conventions/nouns) |
| `verbs/` | Shared [Verbs](/business/nouns/verb) | [Shared Verbs](/code/file-conventions/verbs) |
| `evaluators/` | [Evaluators](/business/nouns/evaluator) | [Evaluators](/code/file-conventions/evaluators) |
| `mappings/` | [Mappings](/business/nouns/mapping) | [Mappings](/code/file-conventions/mappings) |
| `products/` | [Products](/business/nouns/product) | [Products](/code/file-conventions/products) |
| `offers/` | [Offers](/business/nouns/offer) | [Offers](/code/file-conventions/offers) |
| `sites/` | [Sites](/business/nouns/site) | [Sites](/code/file-conventions/sites) |
| `apps/` | [Apps](/business/nouns/app) | [Apps](/code/file-conventions/apps) |
| `domains/` | [Domains](/business/nouns/domain) | [Domains](/code/file-conventions/domains) |
| `content/` | [Content](/business/nouns/content) | [Content](/code/file-conventions/content) |
| `agents/` | [Teams](/business/nouns/team) and [Roles](/business/nouns/role) | [Teams](/code/file-conventions/agents), [Roles](/code/file-conventions/roles) |
| `workflows/` | [Processes](/business/nouns/process) and their [Workflows](/business/nouns/workflow) | [Processes](/code/file-conventions/processes), [Workflows](/code/file-conventions/workflows) |
| `plays/` | [Plays](/business/nouns/play) | [Plays](/code/file-conventions/plays) |
| `systems/` | Overrides on [Systems](/business/nouns/system) | [Systems](/code/file-conventions/systems) |
| `dashboards/` | [Dashboards](/business/nouns/dashboard) | [Dashboards](/code/file-conventions/dashboards) |
| `brand/` | [Brand](/business/nouns/brand), [Theme](/business/nouns/theme), [Templates](/business/nouns/template) | [Brand](/code/file-conventions/brand) |
| `components/` | [Components](/business/nouns/component) | [Components](/code/file-conventions/components) |
| `tests/` | Scenario tests | [Scenario tests](/code/file-conventions/tests) |
| `code/` | Custom [Implementations](/business/nouns/implementation) | [Custom code](/code/file-conventions/code) |
| `generated/` | Files the platform renders | [Generated files](/code/file-conventions/generated) |
| `_name/` | Anything unmanaged | [Private folders](/code/file-conventions/private-folders) |
| `.sb/` | Manifest, resolved Startup, types | [The .sb folder](/code/file-conventions/sb-folder) |

## Rules every file follows
1. **The path is the identity.** `nouns/Lease.mdx` is `Lease`, and `offers/pro.mdx` is `offers/pro`. No file states its own id.
2. **A file exists only where the Startup differs.** Everything else is inherited and shows in `.sb/resolved/`.
3. **Definitions are MDX, behavior is TypeScript.** Frontmatter is the record and the body is its docs. JSON is for machine-written files only.
4. **Root TypeScript is data.** `startup.ts` and `env.ts` are parsed, never run. A loop or a computed value belongs in `code/`.
5. **Behavior binds by name.** `Lease.renew.ts` runs `Lease.renew`, and a Workflow's [Trigger](/business/nouns/trigger) is read from its code.
6. **The fingerprint covers meaning.** Reformatting a file or editing a comment mints no [Version](/business/nouns/version).
7. **One leader per project.** A project is git-first, with each commit imported as a [Change](/business/nouns/change), or db-first, with files regenerated from the record.
8. **No secrets and no records in files.** [Customers](/business/nouns/customer), [Orders](/business/nouns/order), [Invoices](/business/nouns/invoice), [Messages](/business/nouns/message) and [Events](/business/nouns/event) live in [db.sb](/code/platform/db-sb), never in the repository.
9. **A rename rewrites every reference.** No alias is kept for an old path.

## Several Startups in one repository
One repository can hold several Startups. Each Startup folder is byte-identical to the Startup in a repository of its own, and the root files set what every Startup below inherits.

```text
northfield/
├── studio.ts                        Settings, Policies and Brand every Startup below inherits
├── brand/
├── templates/clinic-scheduling/     a Startup Template the Startups below extend
├── startups/leaseline/              the tree above
└── packages/                        shared code, as a workspace
```

| Path | Holds | Kind |
| --- | --- | --- |
| [`startup.ts`](/code/project-structure/startup-root) | [Startup](/business/nouns/startup) | file |
| [`startups.lock`](/code/project-structure/lockfile) | [Version](/business/nouns/version) | file |
| [`settings.mdx`](/code/project-structure/settings) | [Setting](/business/nouns/setting) | file |
| [`policies.mdx`](/code/project-structure/policies) | [Policy](/business/nouns/policy) | file |
| [`nouns/[Noun].mdx`](/code/project-structure/noun-definition) | [Noun](/business/nouns/noun) | file |
| [`nouns/[Noun].[verb].ts`](/code/project-structure/verb-function) | [Function](/business/nouns/function) | file |
| [`nouns/[Noun].[verb].test.ts`](/code/project-structure/verb-fixtures) | [Function](/business/nouns/function) | file |
| [`verbs/[verb].mdx`](/code/project-structure/shared-verb) | [Verb](/business/nouns/verb) | file |
| [`workflows/[process]/[workflow].ts`](/code/project-structure/trigger-action) | [Trigger](/business/nouns/trigger) | file |
| [`evaluators/[name].ts`](/code/project-structure/evaluator-file) | [Evaluator](/business/nouns/evaluator) | file |
| [`mappings/[source].ts`](/code/project-structure/source-mapping) | [Source](/business/nouns/source) | file |
| [`products/[product].mdx`](/code/project-structure/product-definition) | [Product](/business/nouns/product) | file |
| [`offers/[offer].mdx`](/code/project-structure/offer-definition) | [Offer](/business/nouns/offer) | file |
| [`workflows/[process]/index.mdx`](/code/project-structure/process-definition) | [Process](/business/nouns/process) | file |
| [`plays/[play].mdx`](/code/project-structure/play-definition) | [Play](/business/nouns/play) | file |
| [`agents/[team]/[role].mdx`](/code/project-structure/role-definition) | [Role](/business/nouns/role) | file |
| [`systems/[system].mdx`](/code/project-structure/system-override) | [System](/business/nouns/system) | file |
| [`dashboards/[dashboard].mdx`](/code/project-structure/dashboard-override) | [Dashboard](/business/nouns/dashboard) | file |
| [`sites/[site]/`](/code/project-structure/site-folder) | [Site](/business/nouns/site) | folder |
| [`sites/[site]/**/page.mdx`](/code/project-structure/page-file) | [Page](/business/nouns/page) | file |
| [`sites/[site]/**/layout.mdx`](/code/project-structure/layout-file) | [Page](/business/nouns/page) | file |
| [`sites/[site]/**/[key]/`](/code/project-structure/collection-route) | [Collection](/business/nouns/collection) | folder |
| [`sites/[site]/**/not-found.mdx`](/code/project-structure/not-found-page) | [Page](/business/nouns/page) | file |
| [`apps/[app]/`](/code/project-structure/app-folder) | [App](/business/nouns/app) | folder |
| [`apps/[app]/**/view.mdx`](/code/project-structure/view-override) | [Dashboard](/business/nouns/dashboard) | file |
| [`code/[program]/`](/code/project-structure/code-root) | [Implementation](/business/nouns/implementation) | folder |
| [`generated/`](/code/project-structure/generated-root) | [File](/business/nouns/file) | folder |
| [`_[name]/`](/code/project-structure/unmanaged-folder) | [File](/business/nouns/file) | folder |
| [`.sb/resolved/`](/code/project-structure/resolved-view) | [Startup](/business/nouns/startup) | folder |
| [`.sb/types/`](/code/project-structure/generated-types) | [Noun](/business/nouns/noun) | folder |
| [`studio.ts`](/code/project-structure/studio-root) | [Studio](/business/nouns/studio) | file |
| [`brand/`](/code/project-structure/brand-folder) | [Brand](/business/nouns/brand) | folder |
| [`templates/[template]/`](/code/project-structure/studio-template) | [Startup Template](/business/nouns/startup-template) | folder |
| [`components/[Name].mdx`](/code/project-structure/component-definition) | [Component](/business/nouns/component) | file |
| [`brand/templates/[template].mdx`](/code/project-structure/brand-template) | [Template](/business/nouns/template) | file |
| [`brand/theme.mdx`](/code/project-structure/theme-definition) | [Theme](/business/nouns/theme) | file |
| [`startups/[startup]/`](/code/project-structure/nested-startup) | [Startup](/business/nouns/startup) | folder |
| [`packages/`](/code/project-structure/packages-folder) | [Implementation](/business/nouns/implementation) | folder |
| [`env.ts`](/code/project-structure/env-bindings) | [Setting](/business/nouns/setting) | file |
| [`.sb/repo.jsonc`](/code/project-structure/repo-manifest) | [Startup](/business/nouns/startup) | file |
| [`domains/[host].mdx`](/code/project-structure/domain-definition) | [Domain](/business/nouns/domain) | file |
| [`content/[collection]/[slug].mdx`](/code/project-structure/content-entry) | [Content](/business/nouns/content) | file |
| [`agents/[team]/index.mdx`](/code/project-structure/team-definition) | [Team](/business/nouns/team) | file |
| [`workflows/[process]/[workflow].mdx`](/code/project-structure/workflow-document) | [Workflow](/business/nouns/workflow) | file |
| [`agents/[team]/[role].test.ts`](/code/project-structure/role-tests) | [Role](/business/nouns/role) | file |
| [`tests/[scenario].test.ts`](/code/project-structure/scenario-tests) | [Startup](/business/nouns/startup) | file |
| [`components/[Name].tsx`](/code/project-structure/component-code) | [Component](/business/nouns/component) | file |
| [`experiments/[experiment].mdx`](/code/project-structure/experiment-file) | [Experiment](/business/nouns/experiment) | file |
| [`prompts/[prompt].md`](/code/project-structure/prompt-file) | [Template](/business/nouns/template) | file |