Welcome to Integral's Take-Home Challenge! We need your help building a privacy-conscious clinical trial enrollment system.
The Scenario: A pharmaceutical research company is running multiple clinical trials and needs a secure platform where patients can submit enrollment applications. Trial coordinators must screen applications against eligibility criteria while protecting patient privacy during the initial review process. Only after a patient progresses through screening should their full personal information be revealed.
Your task: Build a web application that balances thorough data collection with privacy protection, enabling patients to submit comprehensive enrollment applications while allowing trial coordinators to perform initial screenings with masked personally identifiable information (PII).
Build a web app where:
- A user can login as a Patient or Reviewer (Trial Coordinator)
- A Patient submits an enrollment application with personal information and supporting documents
- The enrollment application appears in a Review Queue for trial coordinators
- A Reviewer can toggle between privileged (full data) and redacted (masked PII) views
- Reviewers can update status (Pending → In Review → Approved/Rejected)
- The system records an audit trail of all actions for compliance
- Patients can upload supporting documents (medical records, insurance cards, etc.)
Requires Node ^20.19 || ^22.12 || >=24.0 (see .nvmrc — nvm use will pick it up).
- Clone the repository to your local machine
- Copy the environment file:
cp .env.example .env - Install dependencies:
npm install - Generate Prisma client:
npx prisma generate - Run database migrations:
npx prisma migrate dev - Seed the database:
npm run db:seed - Start the development server:
npm run dev - Visit
http://localhost:3000/in your browser - Sanity check that the database is wired up:
curl http://localhost:3000/api/usersshould return the two demo users below
A pre-seeded dev.db is checked in, so steps 5 and 6 are no-ops on a fresh clone. Re-seeding
regenerates record IDs, so dev.db will show up as modified in git status — that's expected,
and committing it is fine.
Design references and mockups are available in the /public/design-inspiration/ folder. You can view them at:
http://localhost:3000/design-inspiration/[filename]
These are provided as optional visual guidance. Feel free to implement your own design approach.
Heads up: the mockups are from an earlier iteration of this exercise and are intentionally
not authoritative — they label the submitter role "Client" rather than "Patient", show a
"Full Address" field that isn't in the schema, and don't show document uploads. Where they
disagree with this README or prisma/schema.prisma, this README and the schema win.
The project uses Prisma with SQLite. The schema is defined in prisma/schema.prisma:
id,email,name,role(PATIENT or REVIEWER),organization- Patients submit enrollment applications, Reviewers (trial coordinators) screen them
- Applicant information:
clientName,clientEmail,clientPhone,dateOfBirth,ssn - Application details:
description,notes - Status:
PENDING,IN_REVIEW,APPROVED,REJECTED - Relations:
submittedBy(User),reviewer(User, optional),documents(Document)
action: Type of action (CREATED, STATUS_CHANGED, VIEWED, ASSIGNED, DOCUMENT_UPLOADED)details: JSON string with additional context- Relations:
user(who performed the action),intake(which intake)
- Supporting files uploaded by an applicant (medical records, insurance cards, prescriptions, ID photos, etc.)
fileName,fileType,fileSize,filePath,description- Relations:
intake(cascade deletes with the intake) - Note: This model is already provided. Your task is the upload handling and file storage, not the schema design.
The database is seeded with two demo users:
| Role | Organization | |
|---|---|---|
patient@demo.com |
PATIENT | Trial Participant |
reviewer@demo.com |
REVIEWER | PharmaCorp Trial Coordinator |
src/
├── app/
│ ├── layout.tsx # Root layout
│ ├── globals.css # Global styles
│ ├── page.tsx # Home page with challenge overview
│ ├── login/
│ │ └── page.tsx # Login page (stub)
│ ├── intake/
│ │ └── page.tsx # Patient enrollment application page (stub)
│ ├── queue/
│ │ └── page.tsx # Reviewer queue page (stub)
│ └── api/
│ ├── intakes/
│ │ ├── route.ts # GET all intakes, POST new intake (stub)
│ │ └── [id]/
│ │ └── route.ts # GET/PATCH single intake (stub)
│ └── users/
│ └── route.ts # GET users (implemented — reference example)
├── components/
│ ├── AuditLog.tsx # Audit trail display (stub)
│ ├── IntakeDetail.tsx # Privileged/redacted detail view (stub)
│ └── Add additional components as needed...
├── lib/
│ └── prisma.ts # Prisma client singleton
prisma/
├── schema.prisma # Database schema
├── seed.ts # Seed script
└── migrations/ # Migration history
dev.db # SQLite database (repo root)
GET /api/users is already implemented as a working reference for the Prisma + route
handler pattern — use it to confirm your setup works before building anything else.
Everything else marked "(stub)" is yours to fill in.
- User Authentication: Implement an authentication system for patient and reviewer login
- Enrollment Application: Implement the application form for patients to submit their information
- Document Uploads: Allow patients to upload supporting documents (medical records, insurance cards, prescriptions, etc.)
- Review Queue: Display a list of applications for trial coordinators to manage
- Detail View: Show application details with toggle between privileged and redacted views for sensitive fields (phone, DOB, SSN)
- Status Updates: Allow reviewers to change application status
- Audit Trail: Record and display all actions taken on applications for compliance
The system implements a privacy-conscious review process:
- For Patients: Always see their own complete, unmasked information
- For Reviewers: Can toggle between two views:
- Redacted View (default): Masks PII during initial screening (e.g., SSN shows as
***-**-6789, phone as***-***-1234) - Privileged View: Shows complete data when reviewer needs full information (e.g., after initial screening passes)
- Redacted View (default): Masks PII during initial screening (e.g., SSN shows as
This approach protects patient privacy during the initial eligibility screening while allowing full access when necessary for enrollment processing.
- Filter/search in the review queue (by status, date range, eligibility criteria)
- Pagination for large datasets
- Document preview/viewer for uploaded files
- Real-time updates when applications change status
- Export audit logs for compliance reporting
- Bulk actions for reviewers (approve/reject multiple applications)
- Email notifications when application status changes
npm run dev- Start Next.js development servernpm run build- Build for productionnpm run lint- Run ESLintnpm run typecheck- Run the TypeScript compiler with no emitnpm run db:migrate- Run Prisma migrationsnpm run db:seed- Seed the databasenpm run db:reset- Reset database and re-seed
Please limit yourself to 4 hours on this project. We're interested in how you approach problems and prioritize work within time constraints, not just completion.
Important:
- Track your time: Note when you start and stop working
- Commit frequently: Make regular git commits as you work. This helps us understand your development process
- Include in your submission:
- Total time spent (e.g., "Time spent: 3.5 hours")
- What you prioritized and why
- What you would improve with more time
- Loom recording preferred
We value quality decision-making over feature completion.
You are welcome to use AI tools (e.g., GitHub Copilot, ChatGPT, Claude) to assist with this challenge. However, you are fully responsible for all code submitted. We will evaluate the quality, architecture, and implementation of your solution regardless of how it was created. Make sure you understand and can explain any code you submit.
Once you've completed the challenge, please commit your changes, push them to your own forked GitHub repository, and share the link with us. Alternatively, emailing a zip file of the repository is acceptable — if you zip it, please exclude node_modules/ and .next/.
Q: Can I modify the Prisma schema?
A: Yes! Feel free to modify the schema to better suit your approach. Note, once you modify the schema file you'll have to issue a migration via npx prisma migrate dev and restart your server.
Q: Can I add additional libraries? A: Yes, but keep in mind the time constraint. The existing setup should be sufficient for the core requirements.
Q: How should I handle authentication? A: For simplicity, you can use a basic approach (e.g., credentials). Full authentication is a bonus.
We wish you the best of luck and look forward to reviewing your solution!