This is a reusable web platform for running diary studies. Researchers create studies with custom questions; participants log in daily to submit entries.
- Multi-study — create as many studies as you need, reuse the platform across projects
- Question types — free text, rating scales, multiple choice, yes/no, event date/time, screenshot upload, content blocks
- Roles — admin (researcher) and participant, each with their own view
- Daily entries — one entry per participant per study per day, enforced server-side
- Admin dashboard — manage studies, add/remove participants, browse all entries
- CSV export — download all responses for any study as a CSV
- Node.js 20+ (installed via nvm in this project)
- A PostgreSQL database (see options below)
Copy the example file and edit .env:
cp .env.example .envMinimum local values:
DATABASE_URL="postgresql://user:password@host:5432/diary_study"
# Generate a secret: openssl rand -base64 32
SESSION_SECRET="your-secret-here"
# Only needed if you want screenshot uploads (Vercel Blob)
BLOB_READ_WRITE_TOKEN="your-blob-token"
# Only needed if you want email reminders
RESEND_API_KEY="your-resend-api-key"
EMAIL_FROM="diARI <research@yourdomain.com>"
NEXT_PUBLIC_APP_URL="https://your-deployed-app.com"Free PostgreSQL options:
- Neon — generous free tier, works great on Vercel
- Supabase — free tier with extras
- Local:
brew install postgresqlor Docker
For local development:
npm run db:migrateFor production deployments, run checked-in migrations:
npx prisma migrate deployDo not use prisma db push against production. It bypasses migration history and makes schema changes harder to review or roll back.
npm run create-admin your@email.com yourpassword "Your Name"npm run devOpen http://localhost:3000 — you'll be redirected to the admin dashboard.
- Push this repo to GitHub
- Import it in vercel.com
- Add environment variables in the Vercel dashboard:
DATABASE_URL— your Neon/Supabase connection stringSESSION_SECRET—openssl rand -base64 32NEXT_PUBLIC_APP_URL— your stable production URLCRON_SECRET—openssl rand -base64 32, used to protect reminder cron callsBLOB_READ_WRITE_TOKEN— from Vercel Blob (Storage tab)RESEND_API_KEYandEMAIL_FROM— required for invitation/reminder emailsANTHROPIC_API_KEY— required for AI tagging/grouping whenAI_PROVIDER=anthropic
- Deploy.
- Run database migrations with
npx prisma migrate deployas part of the deployment process or immediately after deploy.
vercel.json schedules /api/reminders/run once per day so deployments work on Vercel Hobby. Vercel Hobby rejects cron expressions that run more than once daily. If the project needs near-real-time reminder delivery, use Vercel Pro and change the schedule back to a more frequent cadence such as */15 * * * *, or trigger /api/reminders/run from an external scheduler.
- Log in as admin → New study
- Add questions (all types supported)
- Ask participants to Sign up at your app URL
- In the study page, add each participant by their email
- Participants see "Submit today's entry" on their dashboard each day
- View or export results from the study admin page
- Follow the full operating checklist in
docs/operating-guide.md. - Use HTTPS in production.
- Generate a strong
SESSION_SECRETand never reuse the development placeholder. - Generate a separate strong
CRON_SECRETfor reminder automation. - Verify your email sending domain before relying on reminders.
- Set
NEXT_PUBLIC_APP_URLto the deployed app URL so reminder links point to the right place. - Decide whether AI-assisted analysis is approved for participant data before enabling
ANTHROPIC_API_KEY. - Confirm consent text, contact email, active parts, and preview flow before inviting participants.
- Export a test CSV and confirm it contains the columns you need.
- Keep database backups enabled in your hosting provider.
The analysis tag lab can use AI to suggest answer tags and group tags into themes. By default this uses Anthropic when AI_PROVIDER is unset or set to anthropic.
That means free-text participant answers and existing tag labels may be sent to Anthropic during AI tagging/grouping. Confirm this is acceptable under your company privacy, consent and data-processing rules before using the feature with real participant data.
For local experimentation, developers can set AI_PROVIDER=ollama to use a local OpenAI-compatible Ollama endpoint instead.
Run a fast production sanity check after a deploy:
SMOKE_BASE_URL="https://diary-study-app.vercel.app" npm run smokeTo also verify a specific invite link:
SMOKE_BASE_URL="https://diary-study-app.vercel.app" \
SMOKE_INVITE_URL="https://diary-study-app.vercel.app/join/your-token" \
npm run smokeThe smoke check confirms public auth pages load, protected pages redirect to login, the reminder endpoint is protected, and the optional invite link renders.
For the full QA pass, seed stable QA fixtures and run the public, participant, and admin checks:
QA_BASE_URL="https://diary-study-app.vercel.app" npm run qaThis creates two clearly named QA studies, a participant account, and checks the public auth pages, participant dashboard, profile return path, simple and journey entries, researcher pages, data table, analysis page, and CSV export. Use a database and app URL that point to the same environment.
If you need to debug a specific layer, run the pieces separately:
npm run qa:env
npm run qa:actions
npm run qa:dataset
npm run qa:tag-lab
npm run qa:study-shell
npm run qa:scaling
npm run qa:seed
QA_BASE_URL="https://diary-study-app.vercel.app" npm run smoke
QA_BASE_URL="https://diary-study-app.vercel.app" npm run qa:flowThe architecture checks are intentionally small and focused:
npm run qa:tag-labkeeps the tag lab split into focused modules instead of drifting back into one large file.npm run qa:study-shellkeeps study tabs on the shared shell, without duplicate navigation/session wrappers or blocky route-level loading placeholders.npm run qa:scalingkeeps the larger-data seams in place: dedicated Data/Analysis loaders, dedicated participant dashboard loading, and explicit database SSL handling.
To run the real browser check, which signs in as the QA participant and submits a simple entry through the UI:
QA_BASE_URL="https://diary-study-app.vercel.app" npm run qa:browserIf this is the first time running browser QA on a machine, install the Chromium browser once:
npx playwright install chromiumTo review database query plans after importing production-like data:
npm run review:indexesThis is a diagnostic check, not a pass/fail QA gate. It helps decide whether common researcher Data and Analysis queries need new or adjusted database indexes.
Two workflows keep the app safer:
CIruns automatically on pushes and pull requests. It checks environment basics, participant action rules, answer dataset rules, TypeScript, and production build.Production QAis manual. Open GitHub Actions, chooseProduction QA, keep the production URL, and run it after Vercel deploys.
The manual production QA workflow needs these GitHub repository secrets:
DATABASE_URLSESSION_SECRET
Use the same values that are configured in Vercel so the QA fixtures are created in the production database being tested.
Screenshot uploads require BLOB_READ_WRITE_TOKEN from Vercel Blob. Without it, the upload API will fail. If you don't need screenshot questions, simply don't add screenshot-type questions to your studies.