---
url: https://saas.dev/docs/quickstart
md: https://saas.dev/docs/quickstart.md
---

# Quickstart

Three commands, and each one ends on an address you can open.

Leaseclock tracks lease renewals for property managers, and it runs at [leaseclock.com](https://leaseclock.com). You start from a copy of it in Test, make it yours, and finish with your own product on your own domain, taking payments into your own Stripe account.

You need Node.js 20 or later and an empty folder. Your first product is free, and nothing in Test charges a real card. Every command is on the [`npx saas.dev`](https://saas.dev/docs/saas-dev-cli.md) page.

With a coding agent, paste the prompt and it runs the same three steps. [Build with your agent](https://saas.dev/docs/agents.md) covers the rest.

```text title="Prompt"
Read https://saas.dev/AGENTS.md. Then build me a SaaS on SaaS.Dev that tracks
[what your product keeps]: start with
`npx saas.dev init my-product --from leaseclock.com`, push to Test, fix every
error, and send me the Test URL it prints. Go Live only through the approval
link, when I say so.
```

## Start from Leaseclock

```console title="Terminal"
$ npx saas.dev init my-product --from leaseclock.com
Signed in as you@example.com
Created my-product in Test from leaseclock.com
  Noun/Lease.mdx  Noun/Unit.mdx  Offer/pro.mdx  AGENTS.md
https://my-product.test.saas.dev
```

The first run opens a browser tab on api.saas.dev to sign you in, and the CLI keeps an id.org.ai token for the machine. The folder `my-product/` holds Leaseclock's files, and `my-product.test.saas.dev` already runs them with Leaseclock's Test records: sign-in, the app, the admin, the API, docs, a home page and a pricing page.

[Leaseclock's Leases list for Northgate Rentals, on its Active tab, with 4B renewed to Nov 30, 2027 and Undo](https://leaseclock.com/app/leases)

In CI, set `SAAS_DEV_TOKEN` in the environment and the CLI uses it instead of a browser.

### What you started

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.

```mdx title="Noun/Lease.mdx"
---
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.

<details>
<summary>Noun/Unit.mdx and Offer/pro.mdx</summary>

```mdx title="Noun/Unit.mdx"
---
name: Unit
fields:
  label: { type: text, required: true }
  building: { type: text }
---
```

```mdx title="Offer/pro.mdx"
---
name: Leaseclock Pro
price: { amount: 29, currency: USD, unit: month }
limits: { Unit: 200 }
personas: Property manager, Leasing coordinator
status: Live
---
```

</details>

### Buy it in Test

Open `my-product.test.saas.dev/pricing` and press **Subscribe**. Stripe Checkout opens in Leaseclock's teal. In Test it runs on a Stripe test account SaaS.Dev opens for your product, so it takes Stripe's test card and needs no Stripe account of your own.

| Card | Expiry | CVC |
| --- | --- | --- |
| `4242 4242 4242 4242` | Any future date | Any three digits |

Checkout returns you to the app, and the subscription shows on the admin's Billing screen.

## 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`.

```console title="Terminal"
$ 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.dev
```

SaaS.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, and every error comes back at once, each with the file, the line and the fix:

```console title="Terminal"
$ npx saas.dev push
422  Booking.mdx line 6: field "StartsAt" must start lower-case. Rename it to "startsAt".

$ npx saas.dev push --fix
Pushed version 2 · https://my-product.test.saas.dev
```

`--fix` applies each error's edit, then previews. Test stays as it was until a push passes. Every code and its fix is in [Errors](https://saas.dev/docs/errors.md).

## Go live

Add your domain, connect your Stripe account and push to Live:

```console title="Terminal"
$ 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 ••••4f2a

$ npx saas.dev push --live
Booking Pro sells at $29 a month
Approve at https://api.saas.dev/approve/v2
Approved by you@example.com · Live serves version 2
Live · https://bookings.example.com
```

Your product answers at `bookings.example.com`, and Test moves to `test.bookings.example.com`. When a customer subscribes to Booking Pro, the payment lands in your Stripe account, under your product's name, and shows on the admin's Billing screen as Paid. SaaS.Dev takes no share of it.

## Next

- [Build with your agent](https://saas.dev/docs/agents.md): the MCP server, AGENTS.md and every key a file takes.
- [Nouns](https://saas.dev/docs/nouns.md) and [Verbs](https://saas.dev/docs/verbs.md): describe what your own product keeps and what people do to it.
- [Stripe](https://saas.dev/docs/stripe.md): refunds, trials, taxes and what your customers see.
- [Defaults and overrides](https://saas.dev/docs/overrides.md): change the theme, or replace a screen with your own React component.
