Consent Page
Overview
Before a participant can begin the task, they need to read the informed consent form and actively agree to participate. Informed consent is an ethical and legal requirement for human subjects research: participants must be told what the study involves, what risks exist, that participation is voluntary, and how their data will be handled before they do anything. Collecting data from a participant who has not consented is not permitted, regardless of what your IRB approval says about the study itself.
The entry page already gave every participant a record with consented
set to false. This page flips it to true when they agree, and later pages
will use that value to confirm that anyone who reaches the task actually
consented. Anyone who declines gets sent back to the start with no further
data collected.
What You're Building
This is a preview of the page we are building.
Informed Consent
Introduction
This research will ask you to complete a computer-based behavioral task in your browser. The purpose of the study is to investigate how behavior changes across different conditions.
Participation
Taking part in this study is completely voluntary. You may withdraw your participation at any time. All data will remain completely anonymous.
Electronic Consent
Continuing with this application indicates that you have read the above information, that you are voluntarily agreeing to participate, and that you are 18 years of age or older.
The preview shows the look; the real page adds three behaviors:
- Agreeing is recorded. Clicking "I Agree to Participate" updates the
participant's record to
consented: trueand moves them to the demographics page. - Declining is respected and still informative. Clicking "I Do Not
Agree" ends their session and returns them to the start. Their record
stays in the database with
consented: false, so you can count how many people arrived but chose not to participate. - No one gets here uninvited. If someone opens this page directly without entering a Prolific ID first, they are sent back to the start.
Building It With Claude Code
Same pattern as the entry page: describe the outcomes, attach the relevant
files, and let Claude Code build it. The consent page does not exist yet, so
the prompt tells Claude Code where to create it. No schema changes and no
migration this time; the consented field is already there.
@prisma/schema.prisma
Create an informed consent page at src/app/consent/page.tsx. It should:
1. Check for the participant cookie set by the entry page. If it is
missing, redirect to /.
2. Display informed consent text with sections for Introduction,
Participation, Risks and Benefits, and Anonymity, followed by an
Electronic Consent section.
3. Show two buttons: "I Agree to Participate" and "I Do Not Agree to
Participate".
4. Agreeing should update the participant's record to set consented to
true, then redirect to /demographics.
5. Declining should delete the participant cookie and redirect to /,
leaving the record in the database with consented still false.
Claude Code will create the new file and folder itself. Approve the edit, read the summary, and you're ready to test.
Testing What You Built
With npm run dev running, go to http://localhost:3000, enter a new
Prolific ID, and click Begin. You should land on the consent page instead of
the 404 from last lesson. The building behind those directions now exists.
Click I Agree to Participate. You will hit a 404 at /demographics,
which is next lesson's building. Open Prisma Studio with npm run db:studio
and check the Participant table: the row for the ID you just entered
should now show consented: true.
Go back to the start, enter a different ID, and this time click I Do Not
Agree to Participate. You should be returned to the entry page. Check
Prisma Studio: that participant's record exists with consented: false.
That's a countable decline, not a lost visitor.
Finally, open a private browser window and go straight to
http://localhost:3000/consent. You should be bounced back to the entry
page, because there's no participant cookie in that window. The gate works.
If You Get Stuck
Same troubleshooting pattern as before: what you did, what you expected, what happened instead, plus any error text. Common symptoms:
- Agreeing works but
consentedstays false in Prisma Studio. The page moved you along without recording the decision. "I clicked I Agree on the consent page and landed on /demographics, but the participant's consented field in Prisma Studio is still false. The agreement is not being saved. Find out why." - Declining doesn't return to the start. "Clicking I Do Not Agree should send me back to the entry page, but nothing happens. Fix the decline button."
- The consent page is reachable without an ID. This is a broken gate. "I can open /consent directly in a private window without entering a Prolific ID. It should redirect to the entry page. Fix the check."
- An error mentions the participant not being found. The cookie points at a record that doesn't exist, which happens if you cleared the database but kept the browser cookie. Start fresh: "I'm getting a participant not found error on the consent page. Walk me through clearing my cookie and starting over with a new ID."
Make It Your Own
The consent text in this lesson is a placeholder. Your actual study will need language that matches your IRB approval, institution, and the specific procedures involved. Tell Claude Code:
@src/app/consent/page.tsx
Update the consent form text to reflect my study. The study involves
participants pressing a button on screen to earn points across three phases.
Compensation is $X for approximately Y minutes. The institution is [your
institution]. Contact information is [your contact].
The layout and buttons stay the same. Only the text changes.
The Code, If You're Curious
You don't need to read anything in this section to continue the course. It's here for the curious and for anyone who wants to compare against the checkpoint branch.
The consent page: the text, the two buttons, and the gate
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import prisma from "@/lib/prisma";
async function agreeToConsent() {
"use server";
const cookieStore = await cookies();
const participantId = cookieStore.get("participantId")?.value;
if (!participantId) {
redirect("/");
}
await prisma.participant.update({
where: { id: participantId },
data: { consented: true },
});
redirect("/demographics");
}
async function declineConsent() {
"use server";
const cookieStore = await cookies();
cookieStore.delete("participantId");
redirect("/");
}
export default async function ConsentPage() {
const cookieStore = await cookies();
const participantId = cookieStore.get("participantId")?.value;
if (!participantId) {
redirect("/");
}
return (
<div className="max-w-2xl mx-auto px-6 py-12">
<h1 className="text-3xl font-bold text-zinc-900 dark:text-white mb-8">
Informed Consent
</h1>
<div className="space-y-8">
<section>
<h2 className="text-xl font-semibold text-zinc-800 dark:text-zinc-200 mb-3">
Introduction
</h2>
<p className="text-zinc-600 dark:text-zinc-400">
This research will ask you to complete a computer-based behavioral
task in your browser. The purpose of the study is to investigate how
behavior changes across different conditions.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-zinc-800 dark:text-zinc-200 mb-3">
Participation
</h2>
<p className="text-zinc-600 dark:text-zinc-400">
Taking part in this study is completely voluntary. You may withdraw
your participation at any time. You are free to stop the task at any
point. There are no right or wrong responses. All data will remain
completely anonymous.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-zinc-800 dark:text-zinc-200 mb-3">
Risks and Benefits
</h2>
<p className="text-zinc-600 dark:text-zinc-400">
Taking part in this study involves no foreseeable risks beyond those
encountered in typical computer use. The benefit of participating is
monetary compensation for your time. The broader benefit of this
study is a better understanding of behavioral patterns in online
research settings.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-zinc-800 dark:text-zinc-200 mb-3">
Anonymity
</h2>
<p className="text-zinc-600 dark:text-zinc-400">
Your name or identity will not be used in any reports or
presentations of the findings. Your Prolific ID will be used only to
confirm study completion and process payment. All response data is
stored on a secure, password-protected database.
</p>
</section>
<section className="bg-zinc-50 dark:bg-zinc-900 p-6 rounded-lg">
<h2 className="text-xl font-semibold text-zinc-800 dark:text-zinc-200 mb-4">
Electronic Consent
</h2>
<p className="text-zinc-600 dark:text-zinc-400 mb-6">
Continuing with this application indicates that you have read the
above information, that you are voluntarily agreeing to participate,
and that you are 18 years of age or older.
</p>
<form action={agreeToConsent}>
<button
type="submit"
className="w-full bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 font-semibold py-3 px-6 rounded mb-4"
>
I Agree to Participate
</button>
</form>
<form action={declineConsent}>
<button
type="submit"
className="w-full border border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 font-semibold py-3 px-6 rounded"
>
I Do Not Agree to Participate
</button>
</form>
</section>
<p className="text-sm text-zinc-500 dark:text-zinc-500 text-center">
For questions or concerns about this research, please contact the
research team at [researcher contact information].
</p>
</div>
</div>
);
}The short version: the page checks the cookie before showing anything, so uninvited visitors bounce back to the start. Each button has its own small server function. Agreeing updates the record and moves the participant forward; declining deletes the cookie and sends them home, leaving the record behind as evidence they arrived and said no.
🌿 Checkpoint branch: 03-consent-page: This is the finished consent
page. Check out this branch to see the completed page and catch up to this
point in the course.
⚠️ If you built earlier lessons yourself and then switch to this
branch: your database was set up by your own migrations, not this
branch's, so npm run db:migrate will report a mismatch and offer to
reset the database. Accepting the reset is the right move during the
course: it deletes your practice data and rebuilds the tables to match
this branch. Never accept a reset once real participant data is in the
database.