Quick Start
This guide walks you through running the Web, API, and NLP services together on your development machine from scratch. For deeper configuration options, see the per-service pages.
Prerequisites
| Requirement | Version | Notes |
|---|---|---|
| PHP | 8.2+ | With extensions: pdo_mysql, redis, gd, zip, bcmath |
| Composer | 2.x | PHP package manager |
| Node.js | 24+ | Required for Web service |
| npm | 10+ | Bundled with Node.js 24 |
| Python | 3.11 | For NLP service |
| MySQL | 8.0 | App database + OMOP vocabulary database |
| Redis | 7.x | Queue and cache backend |
| Docker | 24+ | Required only for somop synthetic data tool |
macOS with Homebrew
1. Clone the repos
mkdir cohort-discovery && cd cohort-discovery
git clone https://github.com/HDRUK/cohort-discovery-service-api
git clone https://github.com/HDRUK/cohort-discovery-service-web
git clone https://github.com/HDRUK/cohort-discovery-service-nlp
2. Start the NLP service
Start NLP first — the API calls it during operation.
cd cohort-discovery-service-nlp
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install pip --upgrade
pip install -r requirements.txt
cp .env.example .env
Edit .env to point at your OMOP vocabulary database (shared with the API):
DB_HOST=127.0.0.1
DB_PORT=3306
DB_NAME=omop
DB_USER=root
DB_PASS=yourpassword
OMOP_VIEW=distributions_and_concept_view
APP_ENV=development
Start the service:
Verify: curl http://localhost:5001/health/ready — 503 while concepts load, then 200 with "status": "ready".
3. Set up and start the API
cd ../cohort-discovery-service-api
composer install
npm install
cp .env.example .env
php artisan key:generate
Minimum .env for standalone local development:
APP_ENV=local
APP_DEBUG=true
APP_OPERATION_MODE=standalone
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=cohort_discovery
DB_USERNAME=root
DB_PASSWORD=yourpassword
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null
COHORT_DISCOVER_NLP_SERVICE_BASE_URI=http://localhost:5001
JWT_SECRET=a-long-random-string-for-local-dev
Set up databases
Primary app database:
mysql -u root -p -e "CREATE DATABASE cohort_discovery;"
php artisan migrate:fresh --seeder=DevDatabaseSeeder
DevDatabaseSeeder is the development one: reference data, demo users and sample collections. A plain --seed runs DatabaseSeeder, which has the reference data but no demo accounts to log in with.
OMOP vocabulary database (minimal — no Athena download required):
Add the OMOP connection to .env:
DB_OMOP_CONNECTION=omop
DB_OMOP_HOST=127.0.0.1
DB_OMOP_PORT=3306
DB_OMOP_DATABASE=omop
DB_OMOP_USERNAME=root
DB_OMOP_PASSWORD=yourpassword
Run the OMOP schema and minimal seeder:
php artisan migrate --database omop --path database/migrations_omop
php artisan db:seed --class=MinimalOmopSeeder --database=omop
Full OMOP vocabulary
For production-quality concept search, download vocabularies from Athena and load them with omop-lite. The minimal seeder covers enough concepts for local UI and API development.
Start the API
This runs four processes concurrently:
php artisan serve— dev server on port 8100php artisan queue:listen --tries=1— Redis job queuephp artisan pail --timeout=0— log streamingnpm run dev— Vite asset compilation
Verify: curl -i http://localhost:8100/up should return 200.
4. Start the Web service
Minimum .env for standalone mode:
API_BASE_URL=http://localhost:8100
APPLICATION_MODE=standalone
NEXT_PUBLIC_LOGIN_URL=http://localhost:3000/auth/login
Start the dev server:
Open http://localhost:3000. You should see the login page.
5. Smoke test
| Service | Check | Expected |
|---|---|---|
| NLP | curl http://localhost:5001/health/ready |
200, "status": "ready" |
| API | curl -i http://localhost:8100/up |
200 |
| Web | Open http://localhost:3000 |
Login page loads |
Default demo credentials
In standalone mode DevDatabaseSeeder runs StandaloneDemoSeeder, which creates:
| Role | Password | |
|---|---|---|
| Admin | Set via DEMO_USER_EMAIL in .env |
Set via DEMO_USER_PASSWORD |
| Researcher | Set via DEMO_RESEARCHER_EMAIL in .env |
Set via DEMO_RESEARCHER_PASSWORD |
Set those four variables before seeding. If you have already seeded without them, set them and run php artisan db:seed --class=StandaloneDemoSeeder.
Next steps
- API Service — full environment variable reference, custom artisan commands, testing
- Web Service — environment variables, testing with Jest and Cypress, project structure
- Deploying your own instance — running the services for real, identity providers, claim mapping and branding
- NLP Service — tuning fuzzy matching, debugging concept resolution
- Integrated mode — HDR UK's own Gateway-hosted deployment only
- Synthetic Data (somop) — spin up a local BUNNY instance with synthetic OMOP data for end-to-end testing