Beyond Vibe Coding · design+AI · Lighthouse, Brighton · 24 September 2026

design+AI workshop

Beyond Vibe Coding

From prototyping to shipping like an engineer

Thursday 24 September 2026 · Chris Parsons

Before the start · Welcome

Welcome to the workshop.

If you have not started your setup yet, start it now. The next slide has the five checks. Tell me if anything gets stuck.

This morning you learn to think like a CTO. You can build a working prototype in an afternoon, but shipping it is a different problem. We set up the foundations that engineers rely on first: source control, deployment, tests, checks and rules for the agent. With those in place, the AI becomes a more reliable partner, and you leave with a real app you can keep building.

The agent writes all the code. You decide what to build and check that it works. Ask questions the whole way through.

Before you start: check your setup

  • A terminal. Mac: Terminal. Windows: the Ubuntu window from wsl --install. Do every step below inside it.
  • Node.js. Run node --version. It prints a version number.
  • GitHub. Run gh auth status. It says you are logged in.
  • Cloudflare. You can sign in at dash.cloudflare.com.
  • Your agent. Start Claude Code or Codex in an empty folder. Ask "What folder am I in?" It answers correctly.
Follow along and copy the prompts
chrismdp.com/workshop/beyond-vibe-coding
Venue Wi-Fi
Network: Lighthouse Guest
Password: Submarine

Setup guide: chrismdp.com/workshop/beyond-vibe-coding/setup-guide.pdf

Something not working? Tell me now, before we start. If it cannot be fixed in time, you pair with someone at your table.

Before the start · on screen while people arrive

Show the venue Wi-Fi details while people connect. These are the five checks from the setup guide. Walk the room and ask each table: did all five pass? Anyone stuck on a work laptop that blocks installs, or on an agent account with command-line access turned off, pairs now. Pairing is part of the plan. When we start, move on to the show of hands.

What did you try before today?

What I say
  1. Did you build with Lovable, v0, Bolt or Cursor?
  2. Did you run Claude Code or Codex in a terminal?
  3. Did you use your GitHub account more than once?
  4. Did you make a commit and watch a build run?
  5. Did you work on your team's code, beyond side projects?
  6. Did you release software for other people?
  7. Did you release software for paying customers?
  8. Did you use Cloudflare before today?

Keep your hand up for each question that fits. If you shipped software for paying customers, can you help your table today? If you already know commits and builds, we can spend longer on deployment. If the terminal is new to you, I will talk through the first prompt.

The terminal is awesome

Three commands, then the agent does the rest.

Start here
mkdir lighthouse
cd lighthouse
claude

Using Codex? Type codex instead of claude. Windows: do this inside the Ubuntu window.

What I say

The terminal is the window where you run commands. Open Claude Code or Codex there. If your setup is unfinished, work with someone next to you.

Different types of coding agents

Claude chat or ChatGPT

MCP connects chat to other tools. Chat can read from those tools. It cannot edit or run files on your machine.

Claude Cowork or ChatGPT Work

Works on files in a separate workspace. Its command tools are limited.

Claude Code or Codex

Edits files and installs software on your machine. Runs commands and reads the results. Builds software.

Use Claude Code or Codex for every step today.

What I say

Use Claude Code or Codex today. The agent must run a command and read the result. When a test fails, it can read the error and change the code. Keep the terminal open so you can see that happen.

Check what the agent gives you

  • Give the agent one instruction at a time.
  • Look for the check after each step.
  • If you get stuck, work with someone next to you.
  • Ask questions all morning, of me and of the agent. It can explain any line it wrote.
Today's game
Build a text adventure in a lighthouse. Put four rooms on a 2×2 grid. Move with the arrow keys. Each room describes the view and the exits.
You can use your own idea if it follows these rules.
What I say

You can copy each prompt from this page. After the agent finishes, look for the check beside it. If the result differs, tell me. In our game, you can judge the movement by playing it. The venue gave us the setting: Lighthouse.

The practices you will leave with

Each one is something a CTO sets up on day one. Today you set them up yourself, in this order.

1 · Outside inPrototype first. The screen, then the behaviour, then the code.
2 · Source controlEvery change is a save point. Small commits, often.
3 · Automatic deploymentPush to main and it is live. Set up before it matters.
4 · A real app, same railsNext.js and TypeScript inside the pipeline you already have.
5 · Tests and buildsSay what true looks like first. A broken change never ships.
6 · Types and lintingChecks on every line that you did not have to write.
7 · Rules for the agentAGENTS.md carries the standards between sessions.
8 · More featuresPlan, design, test, check, push.
9 · A databaseData that lives outside the browser. For tables that finish early.

On the way: secrets stay out of the code and out of the chat, you read a script before you run it, a bad deploy is one revert away, and you learn when to bring in an engineer.

Break 11:00 to 11:15. Finish at 13:00.

What I say

Do not explain them here. Each gets its own slide after you have done it. Say only: these are the nine steps, you will have done at least eight by the end, and none of them needs you to write code.

Step 1

Outside in

Prototype first. The screen, then the behaviour, then the code.

Make a game you can play

Copy to the agent
Create one index.html file for a tiny text adventure set in a lighthouse. Use four rooms on a 2×2 grid. Put the Spiral Stair at the top left and the Lamp Room at the top right. Put the Keeper's Kitchen at the bottom left and the Rocks at the bottom right. Start the player on the Rocks. Show the current room name. Describe what the player can see in two sentences. Show which directions the player can go. Use the arrow keys to move the player. If a direction is blocked, show a short message that says why. Use plain HTML and CSS. Write the game logic in TypeScript and compile it with tsc to a JavaScript file that the page loads. No frameworks. When the page is ready, run the build and open it in my browser.
Check: the page opens. Arrows move you. Walls show a message.

Talk, do not type. Dictate your changes with Wispr Flow, Superwhisper or your computer's own dictation. You say more than you would type, and the agent gets more to work with.

Try these changes, one at a time
Draw an illustration for each room as inline SVG, all in one hand-drawn style, and show it above the description.
(Using Codex? Try first: Generate a real image for each room and show it above the description. If it says it cannot, use the SVG line.)
Give each room a different colour and mood.
Add a small map that marks my room.
Make the rooms fade as I move between them.

Each time, add: Do not make it a full app yet. Keep it a small prototype with no framework, as a reference for the proper app.
After the check

Claude Code cannot generate real images, so its illustrations are SVG drawings. Codex can sometimes make one. If a table gets a real image, show the room. Remind them to dictate their changes with Wispr Flow, Superwhisper or built-in dictation. Speaking gives the agent more detail than typing. Play it before you ask for another change. Does the room name match the map? Does the movement make sense? Give the agent a design change and look again. Leaving it as a design experiment counts as a success. Today we will keep going and put this game online.

Look at what it made

Open the folder. Pick your computer:

Mac
open .
Windows, in Ubuntu
explorer.exe .
Linux
xdg-open .

In Claude Code, put ! in front to run it from the agent's tab. Or tell the agent: "Open this folder for me."

  • index.html: the page. What the browser shows.
  • game.ts: the game logic, in TypeScript. This is the file you can read.
  • dist/game.js: the same logic, compiled for the browser. Never edit this one.
  • package.json and tsconfig.json: the project's name, its build command, its TypeScript settings.
  • node_modules: other people's code the build needs. Do not open it. Do not commit it.
What I say

Walk the folder on the projector. This is a project with several files. One file is the page, one is the logic you described in plain words, one is the compiled copy the browser runs, and two are settings. The agent can pick slightly different names. The files do the same jobs. After the next step a hidden .git folder appears: that is the history.

Step 2

Source control

Every change is a save point.

Sign in to GitHub

  • Create a free account at github.com. Confirm your email.
  • Install gh, the GitHub command. Pick your computer below.
  • Run gh auth login: GitHub.com, HTTPS, Login with a web browser.
  • Check: gh auth status shows that you are signed in.
  • Do this in a new terminal tab (a new Ubuntu tab on Windows). The agent's tab cannot take your typing.
Mac
brew install gh
Windows, in Ubuntu
sudo apt install gh
Linux
sudo apt install gh
Ask the agent for help
Check whether the gh command is signed in to GitHub. If it is not, tell me what to type. Give me one step at a time. Wait for me after each step.
After you sign in
I am signed in to GitHub. Continue.
What I say

If you still need GitHub access, someone at your table can help. The GitHub CLI is the gh command. On Windows, install it inside Ubuntu, the same as Linux. If apt cannot find it, follow the Linux steps at cli.github.com. For gh auth login, choose GitHub.com, HTTPS and Login with a web browser. Copy the code into the browser and finish signing in yourself.

Save your first two versions

Copy to the agent
Set up git in this folder. Add a .gitignore for node_modules and dist first. Make the first commit. If git asks who I am, set my name and my GitHub noreply email for this project and try again. Create a public GitHub repo called lighthouse. Push to the repo. Show me the repo URL.
Check: the GitHub repo contains index.html.
Change the room name, then save
Make the room name bigger. Commit the change. Push it.
Check: GitHub shows two commits. Open the first version.
After the check

Git keeps the history of your files. A repo holds those files and their history. A commit is a save point. Push sends your commits to GitHub. Open the first commit and compare it with the second. Small commits help you find the change you want to undo.

The repo is public on purpose. Secrets never go in the code, public or private. That is one of the rules of a twelve-factor app: settings and secrets live outside the code. So a public repo costs you nothing, and you can show it to anyone.

Try changes you can undo

  • Return to an earlier version after a mistake.
  • Try a design change with a saved version to return to.
  • Share changes with another person or agent.
  • Read the history to see what changed and why.
What I say

Tools such as Lovable can make commits for you. Open the history yourself and see what each commit changed. Ask the agent for small commits. If a design change makes things worse, you can find it and return to the earlier version.

You do not need to learn git

You need to know what git can do, not how to type it. Ask in plain words, and ask the agent to confirm before it changes anything.

Ask the agent
Show me the last 10 changes, in plain English.
Ask the agent
What changed between the last two versions?
Ask the agent
Undo the change from three changes ago. Tell me what you will do and wait for me to confirm.
Ask the agent
Take the game back to how it looked this morning. Confirm before you do it.
Ask the agent
Try this idea on a separate branch, so I can throw it away if I do not like it.
What I say

Try one now: ask for the last 10 changes. Then try the undo, and watch it ask you first. Git has a lot of commands, and you do not need any of them. The agent knows them all. Your job is to know that every version is saved, that any change can be undone, and to ask for a confirmation before anything is thrown away.

Step 3

Automatic deployment

Push to main and it is live. Set it up before it matters.

Give GitHub access to Cloudflare

  • Sign in at dash.cloudflare.com.
  • Open My ProfileAPI TokensCreate Token.
  • Choose Edit Cloudflare Workers. Create the token. Save it somewhere private.
  • Open Workers & Pages once, so Cloudflare sets up your workers.dev address.
  • From the dashboard home, copy your Account ID.
  • If Cloudflare asks for a workers.dev subdomain, choose a name.
What I say

The API token gives GitHub permission to deploy to Cloudflare. The account ID tells it which account to use. Open your profile at the top right, then My Profile, API Tokens and Create Token. Choose Edit Cloudflare Workers, continue and create the token. Cloudflare shows it once, so copy it somewhere safe. Copy the Account ID from the right of the dashboard home. Never show your token on a shared screen.

Put the game on your phone

Copy to the agent
Set up automatic deployment to Cloudflare Workers. Use a GitHub Actions workflow that runs the TypeScript build, then uses wrangler to deploy the built site as static assets, on every push to main. It needs a Cloudflare API token and account ID as GitHub Actions secrets, named CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID. Do not ask me to paste them into this chat. Write a short script that asks me for them in my terminal and stores them with the GitHub CLI. Show me the script and explain every line before I run it. After I have run it, push the changes, wait for the workflow to finish, and give me the live URL.
!Read the script before you run it. Run it in a new terminal tab, inside the lighthouse folder. It must do two things: ask for the token and the account ID, and store them with gh secret set. If it does anything else, do not run it. Not sure? Ask the person next to you to read it too.
Check: the live URL opens on your phone.
Check: the Actions tab on GitHub shows a green tick.
Change the live page
Set the page title to "Lighthouse, by [your name]". Commit the change. Push it.
Check: reload your phone. The title changes within a minute.
After the check

The agent will not take the token in chat, and it is right. It writes a script and asks you to run it in your own terminal. That is the moment to say: never run code you have not read. Two lines of gh secret set is all it needs. Read them. If you cannot tell, hand the screen to a neighbour or to me. This is the one habit today that protects you from a bad actor, and it takes thirty seconds.

Wrangler login: the Cloudflare command-line tool needs its own sign-in, for the D1 stretch and for any wrangler command they run on their laptop. Ask for it here as well: "Run wrangler login so I can use Cloudflare from this terminal." It opens the browser and they click Allow, the same as gh auth login. The token still goes into GitHub for the automatic deploy. Windows users: the browser step can fail inside Ubuntu, so check this one at their table. Open the live URL on your phone. The live URL is the address of your deployed app. Your phone loads the app from Cloudflare. After the title change, reload that same address. If you finish early, ask the agent to explain the workflow file or add a custom domain.

Deploy while the app is small

  • Each push to main sends the app to Cloudflare.
  • Set up deployment while the app is small.
  • Use the same workflow as the app grows.
  • Share the live URL to show your latest change.
  • This is continuous deployment: shipped on every push. The checks come after the break.
  • Your token lives in GitHub's secrets, never in the code, never in a chat. A bad deploy is one revert away. See 12factor.net/config.
  • Never run a script you have not read. It takes thirty seconds.
What I say

A workflow is a set of commands that GitHub runs. This one sends the app to Cloudflare after each push to main. We set it up while the app is small. After the break, we will add checks to stop a broken change going live.

If the live site shows an error, copy the error, paste it into the agent and ask it to fix it. Then push. The same workflow takes the fix live.

Check all three before the break

1Check: your GitHub repo has at least three commits.
2Check: the live workers.dev URL opens on your phone.
3Check: your last push changed the live page.

If a check is missing, tell me. If all three pass, help the next table.

What I say

Open the repo and the live URL beside each other. If you are stuck on the Cloudflare token, tell me and I will come over. Before we start again, everyone must have these three checks or work with someone who does.

Take a break

11:00 to 11:15. Come back for a real app, tests and types.

Step 4

A real app, same rails

Next.js and TypeScript inside the pipeline you already have.

Turn it into a real app

Copy to the agent
Create a new Next.js app in TypeScript with create-next-app. It needs an empty folder, so create it in a new folder first, then move it into this project. Keep the git history and the Cloudflare Worker name, so the live URL does not change. Rebuild the game inside it, using the prototype as the reference. Keep the design unchanged. Add the files needed to run it on Cloudflare Workers with the OpenNext adapter. Update the GitHub Actions workflow to deploy on each push to main. Run the app locally and open it in my browser. Wait for me to check it. When I say it looks right, commit the changes, push them and give me the live URL.
Check it locally first. That is your preview. Say go only when it looks right.
Check: Next.js serves the same design at the same live URL.
After the check

The design, the URL and the workflow have not changed, and underneath there is now a Next.js app in TypeScript. That is the scaffold the page promised, done in one prompt because the rails were already there.

Why bother with a real app?

  • It is optional. The prototype game works as it is.
  • Next.js handles a lot of the caching, the routing and the build for you.
  • It gives the app a standard React structure. Not necessarily the best framework, but the one the AI knows best, and the agent is doing the work.
  • When the app gets more complex, or the design work gets serious, the agent has a real structure to hang that work off.
  • I prefer it to vibe-coding plain JavaScript apps with no shape to them.

From now on you see every change on your own laptop before it goes live. The local copy is your preview. Nothing reaches the live URL until you say go. Later, Cloudflare can also give each branch its own preview URL, so you can share a change with someone else before it goes live.

Why a framework, and why this one

  • Optional. The prototype game works as it is.
  • Next.js does the caching, the routing and the build for you.
  • It is the React setup the agent knows best, and that matters more than which framework is best.
  • When the app grows, or the design work gets serious, it gives the agent a structure to hang the work on.
  • Better than a pile of vibe-coded JavaScript.
  • Some choices are hard to undo: the framework, the database, sign-in, the shape of your data. Take your time on those. Change the rest freely.
What I say

Strictly optional, but useful. Next.js handles a whole bunch of static caching for you. It builds a standard React structure into your app. Not necessarily the best framework, but the one the AI knows best, and that is what matters when the agent is doing the work. When you make something much more complex, or want to do a lot of design work, it gives the agent a real structure to hang that work off. I prefer this to vibe-coding plain JavaScript apps with no shape to them.

Step 5

Tests and builds

Say what true looks like first. A broken change never ships.

Test the locked door first

Copy to the agent
Add this rule: the Lamp Room door stays locked until the player visits the Keeper's Kitchen. Put the room-movement rules in a plain function that does not need a browser. First, write a failing test for this behaviour. At the start, pressing up from the Rocks must leave the player on the Rocks. The message must be "The lamp room door is locked." After visiting the Keeper's Kitchen, pressing up from the Rocks must take the player into the Lamp Room. Run the test. Show me that it fails. Then change the code to make it pass.
Check: the test fails first, with red output.
Check: the same test passes after the code changes.
Run the checks before deployment
Add lint and the type check alongside the tests. Run the tests, lint and the type check as separate jobs in the workflow for pushes to main. Deploy only if tests, lint and the type check all pass. Push the changes.
Check: GitHub shows three passing checks before deployment.
What I say

The game lets you enter the Lamp Room today. Our new rule must fail its first test because we have not added the lock. Read the failure before the agent fixes it. The game must remember a visit to the Keeper's Kitchen. Lint checks the code for common mistakes. Add all three checks to the workflow before deployment.

Check behaviour without reading code

  • Write down the behaviour you expect.
  • See the test fail before the agent changes the code.
  • Run the same test after later changes.
  • Stop deployment when a check fails.
What I say

You chose a rule you can check by playing the game. The test checks that rule after later changes too. A green tick proves the rules were followed, and says nothing about the design. You still choose what the game does and whether it is worth keeping. If you need help before shipping, ask an engineer.

Why this is useful: tests matter most for complex checks, where the only other way to know is to read the code. Developers still write them for important step-by-step things like sign-in, and for complex code they could not follow otherwise. They do not bother for trivial or low-risk systems. So match the checks to the risk.

Stop a broken change
going live

This error is planned. It is the input to the next step.

Remove the lock
Change the code so the Lamp Room door never locks. Leave the test unchanged. Commit the change. Push it.
Check: GitHub shows a red cross.
Check: reload your phone. The live game still locks the door.
Give the agent the failed run
Read the failed workflow run. Restore the lock. Do not change the test. Push the fix.
Check: GitHub shows a green tick and the fix goes live.
After the check

This error is planned. It is the input to the next step. Look at the failed run on GitHub, then play the live game. The door must still lock there. Some machines pass first time and some show a different error. That is normal variation. Read the failure you have before you ask the agent to fix it.

Step 6

Types and linting

Checks on every line that you did not have to write.

Break the types, then run the linter

Make a type error
Change the move function to take a number for the direction instead of a word. Leave the code that calls it unchanged. Run the type check. Show me the result.
Check: the type check names the error. Then restore the function.
Break the linter, on purpose
Add an unused variable near the top of the game component. Run the linter. Show me what it reports. Then remove the variable, run the linter again and show me it is clean.
Check: the linter names a file and a line. Then it reports nothing.
After the check

A type says what kind of value the code expects. Our move function expects a direction word. We changed it to expect a number, but the caller still sends a word. Read the line named by the type check. Then tell the agent: "Restore the move function to take a word for the direction." Lint is the same idea for style and common mistakes: it reads every line, and the agent fixes what it names.

Checks you did not write

  • Find mismatched values before deployment.
  • Read the error to find the line that failed.
  • Give the agent the error so it can fix the code.
  • Lint applies your conventions on every line. Nobody reviews style by eye.
What I say

The type check found a mismatch before you played the game. The agent can use that error to find the line and fix it. TypeScript adds checks throughout the code, like tests you did not write. Types cannot tell you whether the door locks at the right time. Your test from step 5 already covers that rule.

Step 7

Rules for the agent

AGENTS.md carries the standards between sessions.

Keep the rules between sessions

Copy to the agent
If this project already has an AGENTS.md, keep what is there and add these rules to it. If not, create one with these rules. Before changing behaviour, write a failing test. Before saying a change is done, run tests, lint and the type check. If a check fails, do not push. Commit after each small change. Ask before adding a library. Before you push, run the app locally and wait for me to check it.
Check: restart the agent. Ask for the rules. It lists your six.
After the check

Close the agent and start a new session. Ask: "Which project rules must you follow?" Listen for all six rules. Claude Code, Codex and Cursor all read AGENTS.md. The file gives the next session the same instructions. Add rules for choices that the automated checks cannot make.

Step 8

More features

Plan, design, test, check, push.

Build a feature of your own

Before anything
I want to build: ______. Ask me one question at a time until you have enough information to build it. Then tell me your plan. Do not change any code until I say go.
  • Design the screen. Use fixed example data. Change the look first.
  • Test the behaviour. Write a failing test, then change the code.
  • Check it locally. Look at it on your laptop. Change it until it is right.
  • Put it online. Commit and push. Check the live URL.
Choose an idea
Add a fifth room with its own rule.
Pick up a key in the Keeper's Kitchen. Show it in an inventory.
Remember my room when I reload the page.
Redraw the room illustrations in a style you choose. Art-direct the agent.
What I say

Spec first. The agent asks one question at a time, so you answer each in a sentence and nothing gets missed. When it has enough, it tells you the plan. Correct it in plain words, then say go. The answers are the spec, and the design and the test do the rest. Start with the screen: "Add a screen for X. Hard-code the data. Open it in my browser." The hard-coded version will look wrong in places, because the data is fake. That is expected until the behaviour lands. Change the design until it looks right. Then ask: "Write a failing test for X. Change the code to make it pass." Finish with: "Commit the change. Push it." If you finish early, go on to step 9.

Step 9

A database

Data that lives outside the browser. For tables that finish early.

What I say

Optional. If your feature is done and pushed, carry on here. The game's rooms move out of the code and into a database on Cloudflare.

Move the rooms into a database

Copy to the agent
Move the rooms into a Cloudflare D1 database. Create the database with wrangler. Write a migration to create a rooms table and add the four rooms. Store each room's name, description and grid position, and work out the exits from which rooms sit next to each other, so one new row adds a room and its doors. Read the rooms from the database on every request. Apply the migration locally, then remotely. Add the binding to the wrangler configuration. Load the rooms from the database in a route handler. Keep the movement rules pure so the existing tests still pass. Make the GitHub Actions workflow apply migrations before deployment. Push the changes. Give me the live URL.
!First, edit your Cloudflare token: add Account → D1 → Edit. The Workers template does not include it.
Then sign wrangler in
Run wrangler login so I can use Cloudflare from this terminal.
Check: the live URL shows the same four rooms, now loaded from the database.
Step 9 · optional · What I say

This uses the token from step 3. Check that it grants D1 access. D1 stores the room data outside the browser for the first time. Keep movement rules pure: they take values and return results without reading the database. If it fails, ask the agent to remember your room after a reload instead.

Add a room without deploying

Copy to the agent
Add a fifth room called the Cellar below the Keeper's Kitchen. Use one SQL insert against the remote database. Do not change any code. Do not deploy.
Check: reload the live URL. The Cellar appears without a deployment.
Step 9 · optional · What I say

No code changed and nothing was deployed, but the game has a new room. The rooms are data now, so the world can grow without a release.

Change rooms without changing code

  • Keep the room data outside the browser.
  • Show each player the same set of rooms.
  • Add the Cellar with one SQL insert.
  • Change the room data without deploying new code.
What I say

If you tried D1, show us the Cellar at your live URL. A database stores data that the app reads. D1 holds the rooms in a table outside the browser. One SQL insert adds the Cellar to that table. The app reads the extra room without a new deployment. Your position and visited rooms still stay in the browser.

Change the shape with a migration

  • A migration is a small numbered file that changes the database's shape. For example, it adds a table or a column.
  • It lives in git, next to the code.
  • It runs in order, the same on your laptop and on the live site.
  • Your workflow applies it before each deploy, so the database and the code stay in step.
  • Shape goes through migrations. Content, like the Cellar, can go straight in.
Step 9 · optional · What I say

You wrote a migration in the D1 prompt: it created the rooms table. Every change to the shape of the database goes the same way. Each one is a new numbered file, committed to git and run by the workflow before it deploys. Nobody changes the live database's shape by hand, because then your laptop and the live site no longer match. Adding the Cellar was different: that was content, not shape, so one insert was fine.

Data is harder to undo than code

  • Code goes back with one revert. Deleted data does not.
  • A migration that drops a column deletes that data for good.
  • D1 can restore the database to any minute in the last 7 days on the free plan, or 30 on the paid plan.
  • For a copy you keep, wrangler d1 export saves the database to a file.
  • Store data about people, and you are responsible for it: what you keep, who can see it, how you delete it. That is GDPR.
Step 9 · optional · What I say

Everything this morning could be undone with git. Data is the exception. Before a migration that removes anything, make a backup: ask the agent to export the database first. D1 also keeps a history you can restore from, with wrangler d1 time-travel restore, but the restore overwrites what is there now. The bigger line is people. The lighthouse stores rooms. The moment your app stores names, emails or anything about a person, the stakes change, and that is a conversation with an engineer before you ship.

Story: bad data outlasts the outage. On 8 September this year, a software defect at NATS produced corrupted flight data in a millisecond. The system was back that evening, but more than 2,000 flights were cancelled, and it took airlines over two more days to get planes and crews back in place. The 2023 NATS failure was the same shape: about four hours down, around 1,600 cancellations, 700,000 people affected, and disruption until the weekend. The fix was quick. Clearing up after bad data was not. Bigger version: the TSB banking migration in 2018, where moving customer data to a new system caused problems that ran for months.

A workflow for your next project

  • Prototype the screen as a small page, no framework. Change the look until it is right.
  • Put it in git. Push it to GitHub.
  • Deploy on every push, while the app is small.
  • Make it a typed app. Same workflow, same URL.
  • Write the failing test for the next rule. Make it pass. Deploy only when tests, lint and types pass.
  • Write the project rules in AGENTS.md.
  • Every feature: design, then test, then check it locally, then push.

What the page said you would leave with:

  • A Next.js + TypeScript application built on production-ready foundations
  • A GitHub repository with CI configured
  • Automated testing and linting workflows
  • A reusable AGENTS.md setup
  • A workflow you can immediately apply to future projects

This page stays up at chrismdp.com/workshop/beyond-vibe-coding/v1. Your app is in your GitHub and on your Cloudflare. chrismdp.com/coding-with-ai has the longer version.

What I say

This list is the workflow. On Monday it is the same for a real product as it was today for a lighthouse. The order matters more than the tools. Next: when to talk to an engineer.

When to talk to an engineer

You can build and ship this far on your own. Bring in an engineer before any of these:

  • Sign-in, or anything where people have accounts.
  • Payments.
  • Storing names, emails or anything else about a person.
  • Other people depend on it staying up.
  • A change to your data that you cannot undo.
  • Costs that grow with use.
  • The agent goes round in circles on the same error.
Bring them
The live URL.
The GitHub repo.
The tests for the behaviour you want.
Name someone to talk to
Before I ship this, I must speak to ______.
What I say

Everything this morning was safe to try alone: one game, no users, no personal data, and every change could be undone. Real products cross lines where a mistake costs more than a morning. Those are the moments to bring in an engineer. Sign-in is the big one. The moment the app has a login, you hold other people's accounts and you decide who can see what.

You do not arrive empty-handed. A live URL, a repo and tests for the behaviour you want give an engineer something concrete to work with. Write the name of one person you will speak to before you ship.

What you learned

Each one is something a CTO sets up on day one. You did at least eight of them this morning.

1 · Outside inYou designed the lighthouse as a small prototype before the real app.
2 · Source controlEvery change you made is saved, and any of them can be undone.
3 · Automatic deploymentEvery push went live at your own URL.
4 · A real app, same railsThe game became a Next.js app in TypeScript, at the same URL.
5 · Tests and buildsThe locked door went red, then green. A broken change stopped before it went live.
6 · Types and lintingThe checks caught mistakes you never wrote a test for.
7 · Rules for the agentAGENTS.md carries your rules to the next session.
8 · More featuresYou planned, designed, tested, checked and pushed a feature of your own.
9 · A databaseIf you got this far, the rooms moved into a database, and the Cellar arrived without a deploy.

You just did what a CTO does on day one of a product. The agent typed and you judged.

What I say

These are the same nine cards as the start of the morning. Then they were a promise. Now each one is something you did. None of them needed you to write code. Then we have time for questions. There is more at chrismdp.com/coding-with-ai.

Thank you

Any questions?

Chris Parsons
chrismdp.com
linkedin.com/in/chrisparsons

This page stays up: chrismdp.com/workshop/beyond-vibe-coding/v1

What I say

Thank you. Any questions? Scan the QR code to connect with me on LinkedIn, and there is more on my website. This page stays up, so you can come back to the prompts.

Shortcuts. They work in either window, and both windows move together.

  • Space PageDown next slide
  • PageUp previous slide
  • Home first slide · End last slide
  • Type a number, then Enter: go to that slide
  • Esc clear a number you are typing, or leave fullscreen
  • P switch this window between notes and slides
  • N open the notes window
  • ? show or hide this help
  • F fullscreen: hide the top bar and footer
  • D switch between deck and one long page
  • Reload either window and the other reloads too
  • Click a picture below to go to that slide

© Chris Parsons

change slide · N notes window · ? help · F fullscreen · D switch view · Home go to start