Quickstart
Your own product goes live in six steps: sign in, start from Leaseclock, read its three files, buy its plan with Stripe's test card, make it yours, and go live on your domain with your own Stripe account.
Leaseclock tracks lease renewals for property managers, and it runs at leaseclock.com. You start from a copy of it at my-product.test.saas.dev, and you finish with your own product on your own domain, taking payments into your own Stripe account.
With your agent
Paste this into your coding agent, then follow the six steps to see what it does:
Read https://saas.dev/llms.txt. Then start my product on SaaS.Dev in this
folder: sign me in with `npx saas.dev login`, run
`npx saas.dev init my-product --from leaseclock.com`, rename Lease to what my
product tracks, [what your product keeps], push to Test with
`npx saas.dev push`, fix every error it names, open the pricing page so I can
buy the plan with Stripe's test card, then connect my Stripe account and push
to Live when I say so.You need Node.js 20 or later, an empty folder and, for the prompt, a coding agent that runs terminal commands, such as Claude Code or Cursor. Your first product is free, and nothing in Test charges a real card. Every command is on the npx saas.dev page.
Sign in
$ npx saas.dev login
Signed in as you@example.comA browser tab opens on api.saas.dev, and you approve the sign-in there. The CLI keeps an id.org.ai token for this machine, so neither you nor your agent pastes a key. In CI, set SAAS_DEV_TOKEN in the environment and the CLI uses it instead of opening a browser.
Start from Leaseclock
$ npx saas.dev init my-product --from leaseclock.com
Created my-product in Test from leaseclock.com
Noun/Lease.mdx Noun/Unit.mdx Offer/pro.mdx
https://my-product.test.saas.devThe folder my-product/ now holds Leaseclock's three files, and my-product.test.saas.dev already runs them, starting with Leaseclock's Test records: sign-in, the admin, the API, docs, a home page and a pricing page.
Leases
| Unit | Renter | Ends on ↑ | Status | |
|---|---|---|---|---|
| 4BAlder Court | dana.whitfield@example.com | Nov 30, 2027 | Active | Renew |
| 2AAlder Court | marcus.bell@example.com | Dec 15, 2026 | Active | Renew |
| 7CBirch House | lena.okafor@example.com | Jan 31, 2027 | Active | Renew |
| 3DAlder Court | tomas.rivera@example.com | Mar 31, 2027 | Active | Renew |
| 5ABirch House | hannah.cho@example.com | Sep 30, 2026 | Ended | |
| 1FBirch House | owen.price@example.com | Jun 30, 2027 | Active | Renew |
Test is a full copy of the product with its own records and Stripe's test mode, so nothing in it charges a card or emails a real customer. It answers at my-product.test.saas.dev until you add your own domain.
Read the three files
Leaseclock keeps two things: Units, the apartments a property manager rents out, and Leases, which tie a renter to a Unit until a date. Each is a Noun. A Lease can be renewed or ended, and those are its Verbs.
---
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]
end: { does: End the lease, from: [active], to: ended }
---renew has no function, so it does what it declares: it writes the new endsOn onto the lease. The plan customers buy is an Offer, Leaseclock Pro, at $29 a month for up to 200 Units.
Noun/Unit.mdx and Offer/pro.mdx
---
name: Unit
fields:
label: { type: text, required: true }
building: { type: text }
------
name: Leaseclock Pro
price: { amount: 29, currency: USD, unit: month }
limits: { Unit: 200 }
personas: Property manager, Leasing coordinator
status: Live
---These three files are the whole definition. Open my-product.test.saas.dev: the admin lists Units and Leases with a Renew button on each active Lease, /docs/lease explains both Verbs, and /pricing sells Leaseclock Pro.
Buy Leaseclock Pro in Test
$ npx saas.dev open /pricing
Opened https://my-product.test.saas.dev/pricingPress Subscribe on Leaseclock Pro. Stripe Checkout opens under Leaseclock's name, in Leaseclock's teal. Check out as Priya Shah of Northgate Rentals, with Stripe's test card:
Subscribe to Leaseclock Pro
$29.00 per month
Powered by Stripe · Terms · Privacy
| Field | Value |
|---|---|
priya@northgaterentals.com | |
| Card number | 4242 4242 4242 4242 |
| Expiry | Any future date, such as 12/28 |
| CVC | Any three digits |
Checkout returns Priya to the app, signed in to Northgate Rentals' workspace, which holds up to 200 Units. The subscription shows on the admin's Billing screen, and Priya's billing portal lists the paid invoice.
In Test, checkout runs on a Stripe test account that SaaS.Dev opens for your product, so the purchase needs no Stripe account of your own.
Make it yours
Rename Lease to what your product keeps, change a field, and push. Here the product books appointments: rename Noun/Lease.mdx to Noun/Booking.mdx, change name: Lease to name: Booking and endsOn to startsAt, and name the plan Booking Pro in Offer/pro.mdx.
$ npx saas.dev push
my-product · Test
~ Lease → Booking /app/leases → /app/bookings · $.Lease → $.Booking
~ endsOn → startsAt every screen, the API, the SDK and the docs
~ Leaseclock Pro → Booking Pro the pricing page and the Stripe product
Push these changes to Test? (y/N) y
Pushed version 2 · https://my-product.test.saas.devSaaS.Dev shows the change on every surface and waits for a yes before it saves anything.
When a file is wrong
Every file is checked before anything is saved. An error names the file, the line and the fix:
422 Lease.mdx line 6: field "EndsOn" must start lower-case. Rename it to "endsOn".Test stays as it was until the push passes. Your agent reads the line, fixes it and pushes again. Every code and its fix is in Errors.
Go live
Add your domain, connect your Stripe account and push to Live:
$ npx saas.dev domain add bookings.example.com
Add this record at your DNS host: CNAME bookings.example.com my-product.saas.dev
✓ bookings.example.com answers, with its certificate
$ npx saas.dev stripe connect
✓ Stripe connected · acct ending 4f2a
$ npx saas.dev push --live
Push version 2 to Live? (y/N) y
Live · https://bookings.example.com · Stripe: connected (acct ending 4f2a) · Booking Pro sells at $29 a monthYour product now answers at bookings.example.com, and Test moves to test.bookings.example.com. When a customer subscribes to Booking Pro, Stripe Checkout charges their card in Live and the payment lands in your Stripe account, under your product's name. It shows on the admin's Billing screen as Paid, and Stripe pays it out to your bank. SaaS.Dev takes no share of it.
Next
- Errors: every error code, with its cause and fix.
- Nouns and Verbs: describe what your own product keeps and what people do to it.
- Stripe: refunds, trials, taxes and what your customers see.
- Defaults and overrides: change the theme, or replace a screen with your own React component.