Skip to content

Try every change on a copy first

Verified: 2026-10-13

In developers' words: Preview vs production, environment variables, the database

By the end of this level your app has a preview: a second copy at its own address with its own test database, and every change goes there first, where nothing counts.

TIME: 6 MINPROMPTS: 3 + 4CODE: 0
The moment

"Don't test on your users."

You tried the new signup form. It worked, green tick. The next morning a user wrote to say they signed up and nothing happened. You checked: your test signup is in the database, theirs is not. Or worse, your test signups sit in the same table as the real ones, and you cannot tell which is which. Every test you run, you run in front of your users, in their database. That is how one test becomes a mess you clean up by hand, one row at a time.

Developers keep a second copy of the app at its own address, with its own settings and its own database, and every change goes there first: a preview, or staging. The gates are closed, and nothing there counts. The live copy, the one your users are in, is production. Three sentences.

Why this matters

The green tick is the page talking, not the database

  • A form that says "success" is reporting on itself. Where the row landed is a different question, and the only way to answer it is to look. The tick has nothing to say about it.
  • Your test rows are in with your users'. One test signup in the real table is a row you delete by hand. Ten, and you can no longer tell a user from a test, and neither can your app.
  • Production has settings the editor does not. A real database, a real email key, a real payment key. A change that works in the editor can fail at the real address, in front of a user, and the first you hear of it is their email.
  • You can't avoid it. "Preview", "staging", "production", "environment variable": every hosting page and half the error messages use them. Better to learn them now, on a copy, than later, from a user.
  • Six minutes now, or a weekend later. After this, "try it first" costs you one sentence.
The map

The level in one picture

One box per word: production is 1, the preview is 2, its environment variable is 3. The yellow arrow is the rule.
Step 1

Make a preview at its own address

The preview is a second copy of your app at its own address, built from its own line of commits, where no user can reach it.

On Claude Code and Cursor your hosting service's preview deployments do this, and the prompt asks for them. On Lovable and Bolt.new the preview inside the editor is not this: it is your own session. Ask for a deployed preview on a branch.

Prompt: Set up a preview version of this app that builds from a separate branch, at its own address, so I can try changes there before they reach the live site. Give me the preview address and tell me how I send a change there.

✓ A second address, often with "preview" or a name in it, that shows your app. The live address is unchanged. No hosting service connected yet? It will say so, and can only make the separate line of commits. Ask "which hosting service would give this app preview addresses, and what does it cost?" and decide before you go on. That answer is the step, not a failure.

  1. GATES OPENyour-app.com
    Before

    One copy of your app, production, your users inside.

  2. OPENliveCLOSEDpreview
    After the prompt

    The preview, gates closed, at its own address. Production is untouched.

Step 2

Read which database each copy writes to

Each copy has a line that names its database, its email service, its payment provider: its environment variables. The green tick says the page did its part; these lines decide where the data went. This step reads them and changes nothing.

Prompt: List every environment variable in this app that points at a database, an email service, a payment provider, or any other outside service. For each, tell me whether the preview copy uses a test version or the same one as the live site. Don't change anything yet.

✓ A short table: the setting, what it points at, and "same as live" or "separate". A name with DATABASE or SUPABASE in it is the database. If its row says "same as live", ask "make a separate test database for the preview and point only the preview at it", then send the prompt again until that row says "separate".

  1. DATABASE_URL= same as live
    Before

    The preview's database line points at production's database. A test there is not a test.

  2. DATABASE_URL= a test one
    After the prompt

    You know where each copy writes, and the preview's environment variables point at a test database.

Step 3

Send one change to the preview, then look where the row landed

The tick is the page talking; the database shows the row. This step sends a change to the preview only and asks where the data went. Use the form on the preview address yourself first, then send the prompt.

Nothing new to send? Make a small change first, like the page title. No signup form? Any page that saves something will do, like a contact form.

Prompt: Send my latest change to the preview only. Then tell me which database the preview wrote to when I used the form, and show me the row it added.

✓ The change is on the preview address, not the live one. The answer names the test database and shows your row, and the live database has nothing new. If it cannot see the database, open your database page yourself: the newest row in the signups table.

  1. ✓"success"
    Before

    You used the form on the preview. The page says success. That is all it can say.

  2. test: your rowreal: nothing new
    After the prompt

    Your row is in the test database. Production's has nothing new. Now you know.

Keep that sentence. It is your gates closed, and the one line on this page to remember: "send this to the preview only".

Your turn

Change the preview, and watch production stay

v1-works is behind you and the gates are closed on the preview, so put anything you like on it. Put TEST there and see that your users never do. Four prompts, one at a time.

Prompt 1: Change my home page's headline to the word TEST, and send that change to the preview only.

The preview address, with TEST on it. Open it and refresh.

Prompt 2: What does the live site's headline say right now?

Your real one. Open the live address too: it must not say TEST.

Prompt 3: What does the preview's headline say right now?

TEST. Two copies, two answers, and only one of them has users in it.

Prompt 4: Put the preview's headline back to what v1-works has, and send that to the preview only.

The preview shows your real headline again. It may ask to commit that on the preview's own line. Say yes.

  1. CLOSEDTEST
    Prompt 1

    TEST is on the preview, at its own address.

  2. OPENWelcome✓
    Prompt 2

    Production still says your real headline. Your users saw nothing.

  3. CLOSEDTEST?
    Prompt 3

    Asked, the tool reads the preview back: TEST.

  4. CLOSEDWelcome
    Prompt 4

    The preview is back to v1-works. Both copies match again.

That is the habit. Next Tuesday, when the new form is ready, you type "send this to the preview only", use it there, and ask where the row landed. Nobody writes to you the next morning.

The limit

A preview catches what you tried, not what you didn't

One limit. The preview shows you what a change does when you use it the way you use it. A user's phone, a user's typo and a user's slow connection are not on the page until a user brings them. Level 4 is for the fix that keeps missing, and for reading a user's complaint when one still comes.

If it didn't work

Common problems

  • On Lovable and Bolt.new.

    The preview inside the editor is your own session, not a second deployed copy. Ask "is the preview address a separate deployment, or the editor's preview?" If it is the editor's, ask for a deployed preview on a branch. Not yet tested there.

  • It said no hosting service is connected.

    Then there is nowhere to put a second copy yet. Ask "which hosting service would give this app preview addresses, and what does it cost?" and decide.

  • It gave me names, not values.

    That is fine for step 2. The preview's values live on the hosting service's settings page, usually a tab of their own called "Preview". Open it to see which database the preview points at.

  • One settings file, and every line says "same as live".

    There is only one copy, so there is only one answer. Do step 1 first, then ask for the test database.

  • The database row still says "same as live".

    Then a test signup on the preview lands in your real users' table. Ask "make a separate test database for the preview and point only the preview at it", and send step 2's prompt again until the row says "separate".

  • The row turned up in the live database.

    Step 2 is not finished: one setting still points at live. Go back to it and run its prompt until the database row says "separate". Then delete the test row by hand.

  • No row turned up anywhere.

    You have found the green tick with the failed write behind it. Ask "the form said it worked but nothing was saved; what did it actually do with the data?" Verified 2026-10-13.

  • The app on my own computer: is that the preview?

    No. The copy running on your computer is a third thing: you alone, with whatever settings the file on your computer holds. The preview is the one at the preview address, with the preview's environment variables.

The words

Each thing on this page, with its three names

In the game Developers say Plain
the guests your users people who use your app
the gates open production the live copy, the one your guests are in
the gates closed a preview, staging a second copy at its own address, where nothing counts
opening the gates publishing, going live letting a change through to the live copy
the copy's world settings an environment variable the line that says which database a copy uses
the guest book the database what your guests wrote