Skip to content

Development Guide

This guide covers setting up your development environment and working with the Metricis codebase.

Prerequisites

  • Node.js 24.16.0 from .nvmrc (for client, portal, patient portal, landing, and Capacitor tooling)
  • Python 3.11+ (for server)
  • PostgreSQL 15+ (for database)
  • Redis 5.0+ (for session storage and Celery)
  • Git (for version control)

Initial Setup

1. Clone the Repository

git clone https://github.com/lricher7329/metricis.git
cd metricis
nvm use

2. Install Dependencies

Frontend Dependencies

npm install

Backend Dependencies

cd server
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
pip install -r requirements.txt

3. Database Setup

Create a PostgreSQL database:

createdb metricis

Set up environment variables in server/.env:

DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/metricis
JWT_SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
SESSION_SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")

Run migrations:

cd server
source .venv/bin/activate
alembic upgrade head

4. Redis Setup

Install and start Redis:

# macOS
brew install redis
brew services start redis

# Linux
sudo apt-get install redis-server
sudo systemctl start redis

Configure Redis in server/.env:

SESSION_STORAGE_BACKEND=redis
REDIS_URL=redis://localhost:6379/0

Development Servers

Start All Services

npm run dev:all

This starts: - Client: http://localhost:5173 (jsPsych assessment interface) - Portal: http://localhost:3000 (researcher admin portal) - Patient Portal: http://localhost:3001 (patient/caregiver interface) - Server: http://localhost:8030 (FastAPI backend)

Start Services Individually

# Client only
npm run dev:client

# Portal only
npm run dev:portal

# Patient Portal only
npm run dev:patient-portal

# Server only
npm run dev:server

# Client + Server (original dev command)
npm run dev

Verification Source of Truth

Local verification is the authoritative development gate for now. GitHub Actions may still run on pushes and PRs, but remote CI is advisory until the project explicitly switches back to remote CI as the deployment gate closer to release.

For each change, choose the smallest local command set that covers the touched surface and record the commands/results in the handoff:

Change surface Local verification
Client, portal, patient portal, or landing npm run lint:all, npm run typecheck:all, targeted workspace tests, and affected workspace build
Server API, models, services, or migrations cd server && source .venv/bin/activate, then targeted pytest, ruff check app tests, and alembic upgrade head when migrations change
Docs python3 -m mkdocs build --strict --site-dir /private/tmp/metricis-docs
Capacitor/mobile npm run cap:sync:android, npm run cap:sync:ios, affected web build, and native Gradle/Xcode build when platform files change
Release packaging Local Fastlane/native dry runs first; GitHub release workflow becomes authoritative only for deployment/release-candidate work

Do not block ongoing development solely on a remote GitHub Actions failure unless the failure reproduces locally or the current milestone is explicitly a release/deployment milestone.

Background Workers

For reminder notifications and background tasks:

# In a separate terminal
cd server
source .venv/bin/activate

# Start Celery worker
celery -A app.celery_app worker -Q reminders -l info

# Start Celery beat (periodic tasks)
celery -A app.celery_app beat -l info

Project Structure

metricis/
├── client/          # jsPsych assessment frontend (TypeScript + Vite)
├── portal/          # Researcher admin portal (React 18)
├── patient-portal/  # Patient/caregiver portal (React 18)
├── server/          # FastAPI backend (Python 3.11+)
├── docs/            # Documentation (MkDocs)
├── e2e/             # Playwright E2E tests
└── scripts/         # Utility scripts (screenshot capture, etc.)

Common Development Tasks

Database Migrations

Create a new migration:

cd server
source .venv/bin/activate
alembic revision --autogenerate -m "description of changes"

Apply migrations:

alembic upgrade head

Rollback one migration:

alembic downgrade -1

Running Tests

# Server tests (pytest)
cd server
source .venv/bin/activate
pytest tests/ -v

# Portal tests (Vitest)
cd portal
npm run test

# Patient Portal tests (Vitest)
cd patient-portal
npm run test

# E2E tests (Playwright - requires dev servers running)
npm run test:e2e
npm run test:e2e:ui      # With Playwright UI
npm run test:e2e:headed  # With browser visible

Linting

# Client
cd client && npm run lint

# Portal
cd portal && npm run lint

# Server
cd server && ruff check app/

Building for Production

# All web frontends
npm run build:all

# Individual apps
npm run build
npm run build:portal
npm run build:patient-portal
npm run build:landing

Capacitor 8 Native Builds

# Sync native projects
npm run cap:sync
npm run cap:sync:android
npm run cap:sync:ios

# Run or open native projects
npm run cap:run:android -- --list
npm run cap:run:ios -- --list
npm run cap:open:android
npm run cap:open:ios

# Validate native build paths
npm run build:android --workspace=client
npm run build:ios --workspace=client

Android native builds use Java 21, Android SDK 36, Android Gradle Plugin 8.13.0, and Gradle 8.14.3. Release packaging and store uploads are documented in Release Automation and Mobile Deployment.

Code Style and Conventions

Naming Conventions

Context Convention Examples
TypeScript files kebab-case simple-rt.ts, digit-span.ts
TypeScript variables/functions camelCase sessionId, createTimeline()
TypeScript interfaces/types PascalCase SessionConfig, SimpleRTSummary
TypeScript constants UPPER_SNAKE_CASE API_BASE_URL, TASK_CONFIG
Python files snake_case session_store.py
Python variables/functions snake_case session_id, get_session()
Python classes PascalCase SessionStore, REDCapService
API paths kebab-case /api/session/start
API request/response fields snake_case session_id, task_summaries

Git Workflow

  1. Create a feature branch:

    git checkout -b feature/your-feature-name
    

  2. Make your changes and commit:

    git add .
    git commit -m "feat: add new feature"
    

  3. Push and create a pull request:

    git push origin feature/your-feature-name
    

Commit Message Format

Use conventional commits:

  • feat: - New feature
  • fix: - Bug fix
  • docs: - Documentation changes
  • refactor: - Code refactoring
  • test: - Test additions or changes
  • chore: - Build process or tooling changes

Environment Variables

Required for Development

Server (.env)

# Database
DATABASE_URL=postgresql+asyncpg://localhost:5432/metricis

# Security (generate with: python -c "import secrets; print(secrets.token_urlsafe(32))")
JWT_SECRET_KEY=your-secret-key
SESSION_SECRET_KEY=your-session-secret

# Redis
SESSION_STORAGE_BACKEND=redis
REDIS_URL=redis://localhost:6379/0

# Local API port used by root npm scripts
API_PORT=8030

# CORS
ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000,http://localhost:3001

# Rate Limiting
RATE_LIMIT_PER_MINUTE=60
AUTH_RATE_LIMIT_PER_MINUTE=10

Client (.env.local)

# API URL
VITE_API_URL=http://localhost:8030/api

# For mobile development (use your Mac's IP)
VITE_NATIVE_API_URL=http://192.168.1.xxx:8030/api

Troubleshooting

Port Already in Use

If you get "port already in use" errors:

# Find process using port 5173 (or 3000, 3001, 8030)
lsof -ti:5173

# Kill the process
kill -9 $(lsof -ti:5173)

Database Connection Issues

  1. Verify PostgreSQL is running:

    pg_isready
    

  2. Check database exists:

    psql -l | grep metricis
    

  3. Verify connection string in server/.env

Redis Connection Issues

  1. Verify Redis is running:

    redis-cli ping
    # Should return: PONG
    

  2. Check Redis URL in server/.env

Import Errors in Python

Make sure you're in the virtual environment:

cd server
source .venv/bin/activate
which python  # Should point to .venv/bin/python

Next Steps