The Entire System
Overview
In the previous lesson we covered what we're building: a three-phase resurgence experiment that runs in a participant's browser. This lesson covers what the experiment is built out of.
Here's why this matters. Throughout this course, Claude Code will write most of the code for you. You will describe what you want in plain language, and it will produce the implementation. That changes what you need to know. You don't need to memorize syntax or learn to write code from scratch. What you do need is a clear mental model of the system: what the pieces are, what each one is responsible for, and how they talk to each other.
The Big Picture
The whole system is six pieces. Two of them are where the experiment lives, and four of them are tools you use to build and run it.
participants to the app
with a completion code
A participant only ever touches two things in this diagram: Prolific, where they find your study, and the app running on Vercel, where the experiment happens. That's it. They never touch the database. When they press a button, the app records it and the app writes it to Neon on their behalf, which is why Neon is labeled "app-only access." And they never see GitHub, VS Code, or Claude Code. Those are your side of the system, and nothing that happens there is visible to a participant.
Notice also that the arrows form two separate cycles that meet in the middle. The building cycle is yours: you tell Claude Code what you want the experiment to do, it changes the project, you save that new version, and the live experiment updates to match. Change, save, see it live, over and over, until the experiment does what your study needs. The data collection cycle belongs to participants: Prolific sends a person to your experiment, the experiment walks them through each screen, everything they do is recorded, and they return to Prolific to get paid.
Let's walk through each piece.
Frontend and Backend
When developers (or Claude Code) talk about a web app, two words come up constantly: frontend and backend. The split maps cleanly onto something you already know — the difference between running a session and keeping the record of it.
The frontend is the session room. It's everything the participant directly experiences, and it runs in their browser, on their computer. The screens are the stimuli. The circles are the operanda. The point counter ticking up is the consequence, delivered the instant the response occurs. Like any session room, it has to feel immediate — no lag between click and feedback.
The backend is the observer behind the one-way mirror. It runs on a server you control, and the participant never sees it. It's the half that runs the protocol: it applies the reinforcement schedule and decides whether a given click earns a point, it checks that no one reaches the task without consenting, and it scores every event. Because it lives on the server, nothing about it can be inspected or tampered with by a curious participant — which is exactly the property you want in the thing enforcing your procedure.
Here is the part that matters most, and it's the reason this course sets up a database in its very first build lesson: the frontend cannot keep data. A browser's memory is like a frequency count you're keeping in your head — real while the session is running, gone the instant it ends. When a participant closes the tab, loses their connection, or finishes and moves on, everything the frontend knew evaporates. A response that only ever existed in the browser is an unwritten datasheet.
So the full chain for every single response looks like this: the response is emitted in the frontend, observed and scored by the backend, and filed in the database. All three links have to hold, and only the last one is permanent. In this system the rule is absolute: if it never reached the database, it was never collected.
The session room: stimuli are presented, responses are emitted, consequences are delivered — all in real time.
- Shows every screen: consent, instructions, the moving circles
- Registers each click the instant it happens
- Delivers immediate feedback — the +1, the point counter
The observer behind the one-way mirror: runs the protocol, scores every response. Participants can't see it or tamper with it.
- Applies the schedule: was this click reinforced?
- Enforces the gates: no consent, no task
- Hands every scored event to the database
The binder of filed datasheets: written down, timestamped, and kept — no matter what happens in the session room.
- One row per response, with phase, button, and timestamp
- Survives closed tabs, lost connections, and dropouts
- The only thing you export and analyze at the end
The diagram traces one blue-circle click through all three layers. Every response in your experiment makes this exact trip, and it happens in milliseconds — the participant only ever experiences the top layer.
This vocabulary pays off immediately when you work with Claude Code. "Participants should see…" or "when they click…" is frontend talk. "Record…," "check whether…," or "don't let them advance until…" is backend-and-database talk. Describe both halves of what you want — what the participant experiences and what should be written down — and Claude Code will put the code in the right place.
The Participant's Journey
The architecture above is the system at rest. Here is the same system in motion: one participant, from clicking your study on Prolific to getting paid. Each screen is a page in the app with its own address, and — this is the part that matters for your science — each step writes something specific to the database at that moment, not at the end. A participant who drops out at step 4 still left you steps 1 through 3.
- PProlific
The participant finds your study, accepts it, and follows the link to your app.
- 1Prolific ID entryyourapp.com/
They type their Prolific ID and click Begin — before anything else happens.
Participant row created — even dropouts leave a recordID already used → an “already been used” message appears; no second row is created - 2Informed consent/consent
The full consent document, with an explicit agree-or-decline choice.
consented → trueDeclines → cookie cleared, back to the start; the row keeps consented: false - 3Demographics/demographics
Age, gender, and education, collected in one short form.
Demographics row created, linked to the participant - 4Instructions + comprehension check/instructions
Three short screens, then a question that must be answered correctly to continue.
instructionsCompleted → true, attempts countedWrong answer → sent back to review the instructions and try again - 5The three-phase task/task
Three timed phases. The rules change between phases; nothing announces what changed.
Phase 1 · blue circle earns pointsPhase 2 · green circle earns pointsPhase 3 · nothing earns — the resurgence testEvery click → a Response row (phase, button, reinforced); at the end, taskCompleted → true - 6Debrief/debrief
Explains what the study was really about — only reachable once the task is complete.
- PBack to Prolific
The completion code confirms they finished; you approve the submission and Prolific pays them.
Two design decisions are worth noticing in this flow, because they'll come up when we build it:
- The ID is captured first, before consent or anything else, so every arrival leaves a record and dropouts are visible in the data rather than invisible.
- Every gate is enforced by the app, not by trust. You can't reach the debrief without finishing the task, can't reach the task without passing the comprehension check, and can't create two records with one Prolific ID. Each lesson that builds a page also builds its gate.
When Something Breaks
The payoff of knowing the architecture is diagnostic. Different failures live in different pieces, and naming the piece is most of the battle:
| Symptom | Piece to suspect |
|---|---|
| A page shows a 404 | The app — no page exists at that address yet |
| A response was made but no row appears | The database write — the app-to-Neon path |
| Works on your machine, fails on the live URL | Vercel environment variables |
| The live site doesn't show your latest change | GitHub — the change was never pushed, so Vercel never saw it |
| Participants can't find the study | Prolific — screening or publication settings |
| It worked yesterday and you changed something today | GitHub history — compare versions, or step back a checkpoint |
You don't have to fix any of these by hand. Claude Code is your troubleshooter as much as your builder — the rest of this section is how to put it to work.
Troubleshooting with Claude Code
When something breaks, resist the urge to describe it vaguely ("it's not working"). A good bug report to Claude Code has the same shape as a good clinical note: what you did, what you expected, what actually happened, and where you think the problem lives. Then let it read the code and investigate.
I entered a Prolific ID and clicked Begin. I expected to land on the
consent page, but the page just reloaded. The Participant table in
Prisma Studio has no new row, so I suspect the ID never reached the
database. Find out why.
That last sentence is the architecture paying off: "the row isn't in the database" narrows the search from the whole system to one link in the chain. The researcher who can name the layer gets a fix in one round trip. And you don't need to be right — a wrong suspicion stated clearly is still faster than no suspicion at all, because Claude Code can rule it out and move on.
Try to Break It Before Participants Do
Debugging fixes the failures you've seen. Before real participants arrive, you also want to hunt for the failures you haven't seen — the software version of a treatment-integrity check. Security testers call this penetration testing: deliberately behaving like the worst-case user to see which protections hold. Your worst-case participant isn't malicious, just unpredictable — they refresh mid-task, use the back button, close the tab and come back tomorrow. So spend ten minutes being that participant on purpose:
- Type
/taskdirectly into the address bar without consenting first. - Enter the same Prolific ID twice.
- Hit the back button from the debrief and try to redo the task.
- Refresh the page in the middle of Phase 2.
- Decline consent, then try to walk back in.
Every one of these should hit a gate you built: a redirect, a message, a refusal. When one doesn't — you skip straight to the task, or a second ID creates a second record — that's a finding, and you hand it to Claude Code like any other bug. You can also run the whole exercise as a question first:
Read through the participant flow. If someone navigates directly to
/debrief without doing the task, or refreshes during Phase 2, what
happens? List every way a participant could reach a page out of order.
Testing the States of the Experiment
A participant's session isn't one thing — it's a chain of states recorded in the database: arrived → consented → demographics done → instructions passed → task complete. Testing means visiting each state and checking two things: the participant sees the right page, and the database shows the right values.
Prisma Studio (npm run db:studio) is your window into that second half.
Keep it open while you click through the flow and watch the row change:
consented flips to true the moment you agree, Response rows accumulate
as you click, taskCompleted flips at the end of Phase 3. Each new test run
needs a fresh state — use a new made-up Prolific ID, or ask Claude Code to
clean up after you:
Delete all my test participants and their responses from the database
so I can run through the flow fresh.
Validating the Output
The last check is the one closest to your training: don't just confirm data appears — confirm the right data appears. It's the same logic as checking a new observer against a criterion record before trusting their datasheets. Emit a known sample of behavior and verify the record matches it exactly.
Run the task yourself with a plan: exactly 10 clicks on the blue circle in
Phase 1, exactly 5 on the red distractor, nothing else. Then open the
Response table and audit it — 15 rows, correct button labels, correct
phase numbers, reinforced true only where the schedule says it should be,
timestamps in order. Or have Claude Code do the audit with you:
I just did a test run: 10 clicks on blue in Phase 1 and 5 on red.
Query the Response table for my newest test participant and check the
rows match — counts, buttons, phases, and reinforced flags.
If the record matches the behavior, your measurement system is calibrated and you can trust what it collects from strangers. If it doesn't, you found that out for the price of one test run instead of one pilot batch.
💡 You don't need to memorize any of this now. Every piece gets set up hands-on in the coming lessons — this page is the map you can flip back to whenever you lose track of where a piece fits.