zest 2.14 · version history is here

Describe the app. Zest writes the code.

Tell Zest what you need in plain words. It plans the database, writes the code, runs it, and puts it online. You keep the code.

a booking app for my pottery studio

✓ full-stack

✓ real database

✓ auth + payments

✓ export to GitHub

ZEST · clay-studio

A booking app for my pottery studio. Weekly classes, 8 seats each, Stripe deposits, and a reminder email the day before.

[✓] Read the prompt

[✓] Planned 5 tables: classes, seats, bookings…

[✓] Set up auth with magic links

[✓] Connected Stripe (test mode)

[✓] Wrote 23 files

[/] Writing the booking flow

Zest is thinking. This takes about as long as making tea.

Ask for a change…

Preview

Code

Versions

Deploy

clay-studio.zest.app

Clay & Co. Studio

Wheel throwing, hand building and glazing. Small classes, muddy hands.

Wheel basics

Tue 18:30 · 3 seats left

Book

Hand building

Thu 10:00 · full, 2 waiting

Waitlist

Glaze night

Fri 19:00 · 5 seats left

Book

Plan · data model

5 tables · 4 relations

classes

id

uuid · pk

title

text

starts_at

timestamp

capacity

int · 8

seats

id

uuid · pk

class_id

→ classes

number

int

held_until

timestamp

bookings

id

uuid · pk

seat_id

→ seats

user_id

→ users

status

enum

users

id

uuid · pk

email

text

name

text

stripe_id

text

payments

id

uuid · pk

booking_id

→ bookings

deposit

int · £10

stripe_ref

text

relations

seats

→ classes

bookings

→ seats

bookings

→ users

payments

→ bookings

// app/bookings/actions.ts

export async function bookSeat(classId: string) {

const user = await auth.require()

const cls = await db.classes.find(classId)

if (cls.seatsLeft === 0) return waitlist(user, cls)

const deposit = await stripe.checkout({

amount: cls.depositCents,

customer: user.stripeId,

})

await db.bookings.create({ user, cls, deposit })

await email.schedule(“reminder”, cls.startsAt - DAY)

}

Version history

14 versions

Added a waitlist when a class is full

v14 · bookings · 2 min ago

Current

Reminder email the day before

v13 · emails · 14 min ago

Restore

Stripe deposits, £10 per seat

v12 · payments · 31 min ago

Restore

First version: classes and bookings

v11 · setup · 48 min ago

Restore

Restoring makes a new version. Nothing gets thrown away.

● LIVE

clayandco.studio

Deployed in 41s · v14

✓

Domain connected

dns ok

✓

SSL issued

auto-renews

✓

Database ready

eu-west

✓

Preview link ready

v14

ZEST · clay-studio

A booking app for my pottery studio. Weekly classes, 8 seats each, Stripe deposits, and a reminder email the day before.

[✓] Read the prompt

[✓] Planned 5 tables: classes, seats, bookings…

[✓] Set up auth with magic links

[✓] Connected Stripe (test mode)

[✓] Wrote 23 files

[/] Writing the booking flow

Zest is thinking. This takes about as long as making tea.

Ask for a change…

Preview

Code

Versions

Deploy

clay-studio.zest.app

Clay & Co. Studio

Wheel throwing, hand building and glazing. Small classes, muddy hands.

Wheel basics

Tue 18:30 · 3 seats left

Book

Hand building

Thu 10:00 · full, 2 waiting

Waitlist

Glaze night

Fri 19:00 · 5 seats left

Book

Plan · data model

5 tables · 4 relations

classes

id

uuid · pk

title

text

starts_at

timestamp

capacity

int · 8

seats

id

uuid · pk

class_id

→ classes

number

int

held_until

timestamp

bookings

id

uuid · pk

seat_id

→ seats

user_id

→ users

status

enum

users

id

uuid · pk

email

text

name

text

stripe_id

text

payments

id

uuid · pk

booking_id

→ bookings

deposit

int · £10

stripe_ref

text

relations

seats

→ classes

bookings

→ seats

bookings

→ users

payments

→ bookings

// app/bookings/actions.ts

export async function bookSeat(classId: string) {

const user = await auth.require()

const cls = await db.classes.find(classId)

if (cls.seatsLeft === 0) return waitlist(user, cls)

const deposit = await stripe.checkout({

amount: cls.depositCents,

customer: user.stripeId,

})

await db.bookings.create({ user, cls, deposit })

await email.schedule(“reminder”, cls.startsAt - DAY)

}

Version history

14 versions

Added a waitlist when a class is full

v14 · bookings · 2 min ago

Current

Reminder email the day before

v13 · emails · 14 min ago

Restore

Stripe deposits, £10 per seat

v12 · payments · 31 min ago

Restore

First version: classes and bookings

v11 · setup · 48 min ago

Restore

Restoring makes a new version. Nothing gets thrown away.

● LIVE

clayandco.studio

Deployed in 41s · v14

✓

Domain connected

dns ok

✓

SSL issued

auto-renews

✓

Database ready

eu-west

✓

Preview link ready

v14

Apps built on Zest run at

Loop Bikes

holm bakery

FIELDNOTES

Kiln&Co

parcelly

Studio Ostra

how it works

Four steps. You only write the first one.

Zest turns a paragraph into a plan, the plan into code, and the code into a running app with a URL.

01Prompt0:00
A booking app for my pottery studio. Weekly classes, 8 seats each, Stripe deposits, and a reminder the day before.

You write one paragraph. That’s your part done.

02Plan0:40
5 tables · 4 relations

Zest plans the tables, auth, payments and emails.

03Code3:10
23 files · tests pass

Then writes the app and runs the tests.

04Deploy5:50
liveclayandco.studiossl ✓ · deployed in 41s

And ships it to a real URL, SSL and all.

≈ 6 min · average time, prompt to URL

watch it build

One prompt, start to finish.

Scroll to follow a pottery studio booking app from first sentence to live site.

01 · prompt

You write a paragraph.

Plain words. Mention the things that matter to you, like seats per class or when reminders go out.

ZEST · clay-studio

A booking app for my pottery studio. Weekly classes, 8 seats each, Stripe deposits, and a reminder email the day before.

[✓] Read the prompt

[|] Planning the data model

Zest is thinking. This takes about as long as making tea.

Ask for a change…

02 · code

Zest plans, then writes.

Schema first, then server code, then screens. Every file is readable TypeScript you can open.

Preview

Code

Versions

Deploy

Clay & Co. Studio

Wheel throwing, hand building and glazing. Small classes, muddy hands.

Wheel basics

Tue 18:30 · 3 seats left

Book

Hand building

Thu 10:00 · full, 2 waiting

Waitlist

Glaze night

Fri 19:00 · 5 seats left

Book

Plan · data model

5 tables · 4 relations

classes

id

uuid · pk

title

text

starts_at

timestamp

capacity

int · 8

seats

id

uuid · pk

class_id

→ classes

number

int

held_until

timestamp

bookings

id

uuid · pk

seat_id

→ seats

user_id

→ users

status

enum

users

id

uuid · pk

email

text

name

text

stripe_id

text

payments

id

uuid · pk

booking_id

→ bookings

deposit

int · £10

stripe_ref

text

relations

seats

→ classes

bookings

→ seats

bookings

→ users

payments

→ bookings

// app/bookings/actions.ts

export async function bookSeat(classId: string) {

const user = await auth.require()

const cls = await db.classes.find(classId)

if (cls.seatsLeft === 0) return waitlist(user, cls)

const deposit = await stripe.checkout({

amount: cls.depositCents,

customer: user.stripeId,

})

await db.bookings.create({ user, cls, deposit })

await email.schedule(“reminder”, cls.startsAt - DAY)

}

Version history

14 versions

Added a waitlist when a class is full

v14 · bookings · 2 min ago

Current

Reminder email the day before

v13 · emails · 14 min ago

Restore

Stripe deposits, £10 per seat

v12 · payments · 31 min ago

Restore

First version: classes and bookings

v11 · setup · 48 min ago

Restore

Restoring makes a new version. Nothing gets thrown away.

● LIVE

clayandco.studio

Deployed in 41s · v14

✓

Domain connected

dns ok

✓

SSL issued

auto-renews

✓

Database ready

eu-west

✓

Preview link ready

v14

03 · preview

It runs while you watch.

The preview is the real app on a real database. Click around, book a seat, break it on purpose.

Preview

Code

Versions

Deploy

Clay & Co. Studio

Wheel throwing, hand building and glazing. Small classes, muddy hands.

Wheel basics

Tue 18:30 · 3 seats left

Book

Hand building

Thu 10:00 · full, 2 waiting

Waitlist

Glaze night

Fri 19:00 · 5 seats left

Book

Plan · data model

5 tables · 4 relations

classes

id

uuid · pk

title

text

starts_at

timestamp

capacity

int · 8

seats

id

uuid · pk

class_id

→ classes

number

int

held_until

timestamp

bookings

id

uuid · pk

seat_id

→ seats

user_id

→ users

status

enum

users

id

uuid · pk

email

text

name

text

stripe_id

text

payments

id

uuid · pk

booking_id

→ bookings

deposit

int · £10

stripe_ref

text

relations

seats

→ classes

bookings

→ seats

bookings

→ users

payments

→ bookings

// app/bookings/actions.ts

export async function bookSeat(classId: string) {

const user = await auth.require()

const cls = await db.classes.find(classId)

if (cls.seatsLeft === 0) return waitlist(user, cls)

const deposit = await stripe.checkout({

amount: cls.depositCents,

customer: user.stripeId,

})

await db.bookings.create({ user, cls, deposit })

await email.schedule(“reminder”, cls.startsAt - DAY)

}

Version history

14 versions

Added a waitlist when a class is full

v14 · bookings · 2 min ago

Current

Reminder email the day before

v13 · emails · 14 min ago

Restore

Stripe deposits, £10 per seat

v12 · payments · 31 min ago

Restore

First version: classes and bookings

v11 · setup · 48 min ago

Restore

Restoring makes a new version. Nothing gets thrown away.

● LIVE

clayandco.studio

Deployed in 41s · v14

✓

Domain connected

dns ok

✓

SSL issued

auto-renews

✓

Database ready

eu-west

✓

Preview link ready

v14

04 · deploy

One click, one URL.

SSL, a domain, and a database in the region you pick. Most deploys finish in under a minute.

Preview

Code

Versions

Deploy

Clay & Co. Studio

Wheel throwing, hand building and glazing. Small classes, muddy hands.

Wheel basics

Tue 18:30 · 3 seats left

Book

Hand building

Thu 10:00 · full, 2 waiting

Waitlist

Glaze night

Fri 19:00 · 5 seats left

Book

Plan · data model

5 tables · 4 relations

classes

id

uuid · pk

title

text

starts_at

timestamp

capacity

int · 8

seats

id

uuid · pk

class_id

→ classes

number

int

held_until

timestamp

bookings

id

uuid · pk

seat_id

→ seats

user_id

→ users

status

enum

users

id

uuid · pk

email

text

name

text

stripe_id

text

payments

id

uuid · pk

booking_id

→ bookings

deposit

int · £10

stripe_ref

text

relations

seats

→ classes

bookings

→ seats

bookings

→ users

payments

→ bookings

// app/bookings/actions.ts

export async function bookSeat(classId: string) {

const user = await auth.require()

const cls = await db.classes.find(classId)

if (cls.seatsLeft === 0) return waitlist(user, cls)

const deposit = await stripe.checkout({

amount: cls.depositCents,

customer: user.stripeId,

})

await db.bookings.create({ user, cls, deposit })

await email.schedule(“reminder”, cls.startsAt - DAY)

}

Version history

14 versions

Added a waitlist when a class is full

v14 · bookings · 2 min ago

Current

Reminder email the day before

v13 · emails · 14 min ago

Restore

Stripe deposits, £10 per seat

v12 · payments · 31 min ago

Restore

First version: classes and bookings

v11 · setup · 48 min ago

Restore

Restoring makes a new version. Nothing gets thrown away.

● LIVE

clayandco.studio

Deployed in 41s · v14

✓

Domain connected

dns ok

✓

SSL issued

auto-renews

✓

Database ready

eu-west

✓

Preview link ready

v14

ZEST · clay-studio

A booking app for my pottery studio. Weekly classes, 8 seats each, Stripe deposits, and a reminder email the day before.

[✓] Read the prompt

[|] Planning the data model

Zest is thinking. This takes about as long as making tea.

Ask for a change…

Preview

Code

Versions

Deploy

clay-studio.zest.app

Clay & Co. Studio

Wheel throwing, hand building and glazing. Small classes, muddy hands.

Wheel basics

Tue 18:30 · 3 seats left

Book

Hand building

Thu 10:00 · full, 2 waiting

Waitlist

Glaze night

Fri 19:00 · 5 seats left

Book

Plan · data model

5 tables · 4 relations

classes

id

uuid · pk

title

text

starts_at

timestamp

capacity

int · 8

seats

id

uuid · pk

class_id

→ classes

number

int

held_until

timestamp

bookings

id

uuid · pk

seat_id

→ seats

user_id

→ users

status

enum

users

id

uuid · pk

email

text

name

text

stripe_id

text

payments

id

uuid · pk

booking_id

→ bookings

deposit

int · £10

stripe_ref

text

relations

seats

→ classes

bookings

→ seats

bookings

→ users

payments

→ bookings

// app/bookings/actions.ts

export async function bookSeat(classId: string) {

const user = await auth.require()

const cls = await db.classes.find(classId)

if (cls.seatsLeft === 0) return waitlist(user, cls)

const deposit = await stripe.checkout({

amount: cls.depositCents,

customer: user.stripeId,

})

await db.bookings.create({ user, cls, deposit })

await email.schedule(“reminder”, cls.startsAt - DAY)

}

Version history

14 versions

Added a waitlist when a class is full

v14 · bookings · 2 min ago

Current

Reminder email the day before

v13 · emails · 14 min ago

Restore

Stripe deposits, £10 per seat

v12 · payments · 31 min ago

Restore

First version: classes and bookings

v11 · setup · 48 min ago

Restore

Restoring makes a new version. Nothing gets thrown away.

● LIVE

clayandco.studio

Deployed in 41s · v14

✓

Domain connected

dns ok

✓

SSL issued

auto-renews

✓

Database ready

eu-west

✓

Preview link ready

v14

Preview

Code

Versions

Deploy

Clay & Co. Studio

Wheel throwing, hand building and glazing. Small classes, muddy hands.

Wheel basics

Tue 18:30 · 3 seats left

Book

Hand building

Thu 10:00 · full, 2 waiting

Waitlist

Glaze night

Fri 19:00 · 5 seats left

Book

›

A booking app for my pottery studio. Weekly classes, 8 seats each, Stripe deposits, and a reminder email the day before.

Plan · data model

5 tables · 4 relations

classes

id

uuid · pk

title

text

starts_at

timestamp

capacity

int · 8

seats

id

uuid · pk

class_id

→ classes

number

int

held_until

timestamp

bookings

id

uuid · pk

seat_id

→ seats

user_id

→ users

status

enum

users

id

uuid · pk

email

text

name

text

stripe_id

text

payments

id

uuid · pk

booking_id

→ bookings

deposit

int · £10

stripe_ref

text

relations

seats

→ classes

bookings

→ seats

bookings

→ users

payments

→ bookings

// app/bookings/actions.ts

export async function bookSeat(classId: string) {

const user = await auth.require()

const cls = await db.classes.find(classId)

if (cls.seatsLeft === 0) return waitlist(user, cls)

const deposit = await stripe.checkout({

amount: cls.depositCents,

customer: user.stripeId,

})

await db.bookings.create({ user, cls, deposit })

await email.schedule(“reminder”, cls.startsAt - DAY)

}

Version history

14 versions

Added a waitlist when a class is full

v14 · bookings · 2 min ago

Current

Reminder email the day before

v13 · emails · 14 min ago

Restore

Stripe deposits, £10 per seat

v12 · payments · 31 min ago

Restore

First version: classes and bookings

v11 · setup · 48 min ago

Restore

Restoring makes a new version. Nothing gets thrown away.

● LIVE

clayandco.studio

Deployed in 41s · v14

✓

Domain connected

dns ok

✓

SSL issued

auto-renews

✓

Database ready

eu-west

✓

Preview link ready

v14

made with zest

A tailor, a teacher and a bike shop.

Three people who had a problem, wrote it down, and shipped something by the end of the day.

Fittings

Replaced a paper diary with a fitting tracker his whole shop uses.

Arjun Mehta

Quizbox

Built auto-marked quizzes for 180 students over a weekend.

Lena Okafor

Zest's pixel lime-slice mascot beside a pixel bike with a dark lime frame, standing in for Tom Reyes of Loop Bikes

Stockroom

Runs inventory for two bike shops from his phone.

Tom Reyes

what you get

A real app, not a demo.

Everything a working product needs is there from the first build.

01

Full-stack by default

Frontend, backend and API routes in one project. No glue code, no separate repos to keep in sync.

02

A real database

Postgres with migrations Zest writes and explains. Your data is yours, not locked in a spreadsheet.

03

Sign-in that works

Email, magic links, Google and roles for your team. Password resets included, obviously.

04

Payments

Stripe checkout, subscriptions and deposits. Test mode first, so nobody gets charged by accident.

05

GitHub export

Push to your repo whenever you like. Keep building in Zest or take it from there in your editor.

06

Custom domains

Point your domain, Zest does SSL and redirects. Most domains are live in five minutes.

pricing

Start free. Pay when it matters.

Plans are based on credits. One credit is roughly one change Zest makes.

Free

$0

For trying ideas. 30 credits a month.

Pro

$25

For people shipping. 500 credits and custom domains.

Team

$30

Per seat. Shared projects and roles.

Enterprise

Let’s talk

SSO, data residency, a named human.

Your app is one paragraph away.

Free to start. No card needed. The mascot gets excited when you deploy.

zest

Describe the app. Zest writes the code, runs it and puts it online.

© 2026 Zest Labs. Made by people who like making things.

[ status: all systems building ]

zest

Describe the app. Zest writes the code, runs it and puts it online.

© 2026 Zest Labs. Made by people who like making things.

[ status: all systems building ]

Create a free website with Framer, the website builder loved by startups, designers and agencies.