# Define Nouns and Verbs. The rest is generated. > Define your SaaS as Nouns and Verbs in a few lines your agent can write. Its App, API, CLI, MCP, SDK, Site, Docs and Blog are generated, with Stripe billing. - [What a definition generates](https://saas.dev/generated.md): every output of one definition - [Every page in one file](https://saas.dev/llms-full.txt). Every page answers `Accept: text/markdown`. Start here, with no key: - `curl https://api.sb/startups/create` previews a Verb. Its preview begins "Nothing ran." - `curl https://api.sb/leaseclock.com/leases/4b/renew` previews the Action Leaseclock's renew block generates. It runs nothing. ## For agents - Types: `https://api.sb/$.d.ts` lists every Noun and its Verbs. `?nouns=` adds one Noun's fields, inputs and Modes. - A `$` call without a mode runs in try mode: it runs in full and stores nothing. A script's writes commit together when it returns, and a script does not read its own writes. - `https://api.sb/mcp`, signed in: three tools, `search`, `fetch` and `do`. Each Verb is a typed method inside `do`, never a new tool. Most of a SaaS is like every other: an API, sign-in, docs, a site, billing and screens. An agent can write it all; then you maintain it all. Write only what is yours: Nouns, Verbs and a price. Leaseclock's are a Unit, a Lease, renew, end and $29 a month, in 27 lines. From them come the App, API, CLI, MCP, SDK, Site, Docs and Blog, with Stripe billing and opinionated defaults. Nothing is scaffolded into your repo, so an improvement to the defaults reaches you on the next request. Override any style or component, and you maintain that one. The constraints are the feature. ## One definition ```mdx title="leaseclock.com/Startup/leaseclock.com.mdx" --- $type: Startup $id: leaseclock.com name: Leaseclock description: Tracks lease renewals for small property managers. pitch: No renewal slips past its date. icp: small property managers brand: Leaseclock --- ``` ```mdx title="leaseclock.com/Noun/Unit.mdx" --- $type: Noun $id: leaseclock.com/nouns/Unit name: Unit fields: label: { type: text, required: true } building: { type: text } --- ``` ```mdx title="leaseclock.com/Noun/Lease.mdx" --- $type: Noun $id: leaseclock.com/nouns/Lease name: Lease fields: unit: { type: link, target: Unit, required: true } renter: { type: email, required: true } endsOn: { type: date, required: true, indexed: true } status: { type: choice, options: [{ key: active }, { key: ended }] } verbs: renew: does: Move the end date forward input: { endsOn: { says: the new end date, type: date, required: true } } from: [active] fn: { kind: code, body: replace } end: { does: End the lease, from: [active], to: ended } --- ``` ```mdx title="leaseclock.com/Offer/pro.mdx" --- $type: Offer $id: leaseclock.com/offers/pro name: Leaseclock Pro price: { amount: 29, currency: USD, unit: month } limits: { Unit: 200 } personas: Property manager, Leasing coordinator status: Live --- ``` ## Refusals - `"properties" is not part of a definition` - `name is a Noun's name: PascalCase, letters and digits, at most 64 (got "lease")` - `Price has no field "interval"` ## Pages - [What a definition generates](https://saas.dev/docs.md): Write four files: a Startup, its Nouns and Verbs, and an Offer. They generate the App, API, CLI, MCP, SDK, Site, Docs and Blog, with Stripe billing. - [The definition](https://saas.dev/docs/definition.md): Four files define Leaseclock: a Startup, two Nouns and an Offer. Every key line carries an anchor and counts the outputs it generates. - [One Lease, every Interface](https://saas.dev/docs/interfaces.md): One grammar reaches the Lease on the API, SDK, CLI, MCP and Docs. Every Verb returns one Action, and every refusal names its fix. - [The App](https://saas.dev/docs/app.md): Every line of the definition makes a screen decision. Your team works in the Admin, and your Customers work in the SaaS App, on your own domain. - [What your Customers get](https://saas.dev/docs/customers.md): Each Customer gets your API, MCP and Docs on your own domain, with their own key, Limit and Tenant, and a sign-in that sets what people and agents may do. - [How generation works](https://saas.dev/docs/how-it-works.md): Your files compile to one model that generates every output on each request. Every output has a default, and the constraints make generation possible. - [Get paid with Stripe](https://saas.dev/docs/get-paid.md): Write the price once in your Offer, and your pricing page, Stripe Checkout and every renewal read it, with the money landing in your own Stripe account. ## Then, signed in 1. Run npx startup-builder login, then run the two export lines it returns. ```bash npx startup-builder login ``` 2. Create the Startup with Prefer: mode=try, then commit it. ```bash curl -X POST https://api.sb/startups/create -H "authorization: Bearer $SB_TOKEN" -H 'Prefer: mode=try' -d '{"domain":""}' ``` Then commit: ```bash curl -X POST https://api.sb/startups/create -H "authorization: Bearer $SB_TOKEN" -H "Idempotency-Key: $(uuidgen)" -d '{"domain":""}' ``` 3. Write Noun/Unit.mdx and Noun/.mdx in Leaseclock’s shape. Try them, then commit. ```bash curl -X POST https://api.sb//nouns -H "authorization: Bearer $SB_TOKEN" -H 'Prefer: mode=try' -F file=@Noun/Unit.mdx -F file=@Noun/Lease.mdx ``` Then commit: ```bash curl -X POST https://api.sb//nouns -H "authorization: Bearer $SB_TOKEN" -F file=@Noun/Unit.mdx -F file=@Noun/Lease.mdx curl -X POST https://api.sb//offers -H "authorization: Bearer $SB_TOKEN" -F file=@Offer/pro.mdx ``` 4. Read https:///llms.txt and show me what it lists. ```bash curl https:///llms.txt ```