Skip to content

startup.ts

The root file marks a Startup and holds its name, domain, the Startup Template it extends, and its own values, in TypeScript, MDX or JSON.

startup.ts marks a Startup and holds its name, its Domain, the Startup Template it extends, and its own values. It is the business record as code.

TypeScript
import { Startup } from 'startup-builder'

export default Startup({
  name: 'Leaseline',
  domain: 'leaseline.app',
  extends: 'solo-saas',
})

Reference

One Startup() call with literal values. The file is parsed, never run, so it holds data only. Spreads of Templates are allowed; a loop, a computed value or a call into your own code fails the parse check and names the line.

The Startup's own fields are name, domain, extends, idea, hypothesis (the Founding Hypothesis), msc, offers and routes. Any Setting, such as signup or trial, takes its own value as well (Settings). Every key gives each one's type and default.

Role seats keyed by function, such as support: { agent: 'Rae' }, are shorthand. The full seat lives in Roles.

Every key

Each key the root file takes, with its type, its default and the Builder that reads it. The Startup root file reference adds the errors a push fails with.

KeyTypeDefaultDescription
namestringRequiredThe Startup’s name, as buyers see it. Example: 'Closewise'. Read by StartupBuilder.
domainurlNone.Its home Domain; its Sites, API and docs serve there. Example: 'closewise.com'. Read by SiteBuilder.
extendsstartup-templateNone.The Startup Template it extends; everything it does not set is inherited from it. Example: 'agent-run-services'. Read by StartupBuilder.
ideatextNone.The Idea in one sentence. Example: 'Monthly books for small agencies, reconciled and reviewed.'. Read by StartupBuilder.
hypothesisobjectNone.The Founding Hypothesis, one key per slot. Read by StartupBuilder.
hypothesis.customertextNone.Who it is for. Example: 'Agencies with 5 to 50 staff and no in-house bookkeeper'. Read by StartupBuilder.
hypothesis.problemtextNone.What they struggle with. Example: 'Month-end takes three weeks and still misses entries'. Read by StartupBuilder.
hypothesis.approachtextNone.How the Startup solves it. Example: 'Agents reconcile every entry, and a controller reviews each month'. Read by StartupBuilder.
hypothesis.switchtextNone.What they use today and would leave. Example: 'A part-time bookkeeper and a spreadsheet'. Read by StartupBuilder.
hypothesis.differentiationtextNone.Why they would switch. Example: 'Books done within three business days of month end'. Read by StartupBuilder.
mscobjectNone.The Minimum Success Criteria: the Metric, the value and the date that make the Startup worth keeping. Read by StartupBuilder.
msc.metricmetricNone.The Metric it is judged on. Example: 'outside-revenue'. Read by StartupBuilder.
msc.valuenumberNone.The value the Metric must reach. Example: 5000. Read by StartupBuilder.
msc.bydateNone.The date it must reach it by. Example: '2027-06-30'. Read by StartupBuilder.
reserveobjectNone.The reserve page’s two values nothing else supplies: the ship date and the threshold. Read by SalesBuilder.
reserve.shipsdateNone.The date reservers are told the product ships. Example: '2027-01-15'. Read by SalesBuilder.
reserve.thresholdobjectNone.The bar the reserve test must clear, fixed before the page goes live. Read by SalesBuilder.
reserve.threshold.depositsnumberNone.How many outside deposits pass the test. Example: 8. Read by SalesBuilder.
reserve.threshold.reachednumberNone.How many people the page must reach. Example: 40. Read by SalesBuilder.
reserve.threshold.bydateNone.The date the deposits must arrive by. Example: '2026-11-05'. Read by SalesBuilder.
offersmapNone.Its own Offers, keyed by id; a larger Offer lives in offers/. Read by SalesBuilder.
offers.*.pricemoneyNone.The amount and currency it charges each interval. Example: { amount: 499, currency: 'USD' }. Read by SalesBuilder.
offers.*.intervalstringNone.How often it bills: once, day, week, month or year. Example: 'month'. Read by SalesBuilder.
offers.*.termstextNone.What the buyer gets, in one sentence. Example: 'Books done within three business days of month end.'. Read by SalesBuilder.
routesmapNone.Routes to a Custom Implementation, keyed by path; every other route is generated. Read by SoftwareBuilder.
routes.*.tostringNone.The program in code/ that serves the route. Example: 'code/legacy-webhook'. Read by SoftwareBuilder.
routes.*.reasontextRequiredWhy no Verb, saved query or MCP tool could serve it. Example: 'A partner posts form-encoded webhooks that no Verb accepts.'. Read by SoftwareBuilder.
localestring'en-US'The language and region its Pages and Messages are written for. Example: 'en-GB'. Read by SiteBuilder.
signupstring'email'How a buyer signs up: email, workEmail, magicLink, keyless, apiKey, oauth or agentIdentity. Example: 'magicLink'. Read by SoftwareBuilder.
doubleOptInbooleanfalseWhether a Waitlist sign-up confirms by email before it counts. Example: true. Read by SiteBuilder.
priceUnitstring'seat'The unit its Prices count by default. Example: 'month'. Read by SalesBuilder.
trialstring'14d'How long a trial runs before the first charge. Example: '30d'. Read by SalesBuilder.
agreementstring'clickwrap'How a buyer accepts the terms: clickwrap or msa. Example: 'msa'. Read by SalesBuilder.
termsTemplatestring'standard'Which terms Template its /terms Page is built from: standard, developer, b2b, consumer or agent. Example: 'b2b'. Read by SalesBuilder.
taxDisplaystring'exclusive'Whether Prices show tax: exclusive, inclusive or reverseCharge. Example: 'inclusive'. Read by SalesBuilder.
refundWindowstring'30d'How long after a charge a refund is granted without review. Example: '14d'. Read by SalesBuilder.
consentstring'strictest'Whose consent rules apply: the strictest everywhere, or each region’s own. Example: 'byRegion'. Read by SiteBuilder.
approvalHoursnumber48How long an Approval waits before it escalates. Example: 24. Read by StartupBuilder.
budgetnumber200Its monthly spend budget, in USD, before an Approval. Example: 500. Read by StartupBuilder.
autoUpgradestring'onGreen'When a Startup Template upgrade merges: onGreen, qualityGates or manual. Example: 'manual'. Read by StartupBuilder.
closeByDaynumber5The business day of the month by which the books close. Example: 3. Read by StartupBuilder.

Examples

Leaseline

TypeScript
import { Startup } from 'startup-builder'

export default Startup({
  name: 'Leaseline',
  domain: 'leaseline.com',
  extends: 'solo-saas',
  idea: 'Small property managers pay to never miss a lease renewal.',
  hypothesis: {
    customer: 'Property managers with 20 to 200 units',
    problem: 'Renewals slip because end dates live in a spreadsheet',
    approach: 'Import the rent roll and send every notice at 60 days',
    switch: 'A spreadsheet and a calendar reminder',
    differentiation: 'Set up in ten minutes from the rent roll',
  },
  signup: 'magicLink',
  trial: '30d',
})

Three spellings

The same Startup in MDX and JSON parses to one fingerprint. npm create startups writes TypeScript, and startups.new writes MDX.

MDX
---
name: Leaseline
domain: leaseline.com
extends: solo-saas
---
Leaseline tracks lease renewals for small property managers, so no renewal slips past its date.
JSON
{ "name": "Leaseline", "domain": "leaseline.com", "extends": "solo-saas" }

What it builds

The StartupBuilder compiles the file and directs the other four Builders.

  • the Startup, created with Startup.create and extended with Template.extend on the first write
  • its Settings, and the Interfaces its Startup Template declares: /api, /app, /docs and MCP
  • the Events Template.extended, then Startup.built when the first build finishes

Routing

The Startup's namespace is its domain: https://api.sb/leaseline.com serves its API, and leaseline.com/api serves the same on its own Domain. A route to custom code needs a reason:

TypeScript
routes: { '/webhooks/partner': { to: 'code/partner-webhook', reason: 'The partner posts form-encoded webhooks that no Verb accepts.' } }

Good to know

  • Two root files in one folder fail. Pick startup.ts, startup.mdx or startup.json.
  • A key set in both startup.ts and settings.mdx fails, so every Setting has one home.
  • npx startup-builder show / prints the whole Startup, own and inherited values.