Complete guide to setting up a development environment for ODE.
Before setting up the development environment, ensure you have:
packageManager in each package; enable with Corepack: corepack enable && corepack prepare [email protected] --activate)ODE is a monorepo containing multiple components:
ode/
├── formulus/ # React Native mobile app
├── formulus-formplayer/ # React web form renderer
├── synkronus/ # Go backend server
├── synkronus-cli/ # Go command-line utility
├── synkronus-portal/ # React web portal
└── packages/
├── tokens/ # Design tokens package
└── components/ # Shared UI components
ODE JavaScript/TypeScript packages use pnpm ([email protected] via Corepack) with a per-package pnpm-lock.yaml (there is no root workspace install). Run pnpm install inside each component directory you work on.
Recommended install order when setting up several components:
packages/tokens — pnpm install then pnpm run buildpnpm install in formulus-formplayer, formulus, packages/components, synkronus-portal, or desktop as neededCI and Docker use pnpm install --frozen-lockfile for reproducible installs.
git clone https://github.com/OpenDataEnsemble/ode.git
cd ode
cd packages/tokens && pnpm install && pnpm run build && cd ../..
cd formulus
pnpm install
Android builds require the Notifee native core (gitignored). pnpm run android runs preandroid to vendor it automatically; or run pnpm run vendor:notifee before ./gradlew directly.
# Start Metro bundler
pnpm start
# Run on Android
pnpm run android
# Run on iOS (macOS only)
pnpm run ios
ODE enforces consistent formatting and linting:
# Run linting
pnpm run lint
# Run linting with auto-fix
pnpm run lint:fix
# Format code
pnpm run format
# Check formatting (no writes)
pnpm run format:check
# Generate WebView injection script
pnpm run generate
# Generate API client from OpenAPI spec
pnpm run generate:api
cd packages/tokens && pnpm install && pnpm run build && cd ../..
cd formulus-formplayer
pnpm install
# Development server
pnpm start
# Build and copy assets into Formulus (and ODE Desktop)
pnpm run build:copy
# Run linting
pnpm run lint
# Run linting with auto-fix
pnpm run lint:fix
# Format code
pnpm run format
# Check formatting (no writes)
pnpm run format:check
See ODE Desktop Development for setup, scripts, and Formplayer integration.
For testing a local custom app build in the Workbench, see ODE Desktop developer mode.
cd synkronus
go mod download
Create a .env file:
PORT=8080
DB_CONNECTION=postgres://synkronus:password@localhost:5432/synkronus?sslmode=disable
JWT_SECRET=your-secret-key-for-development
LOG_LEVEL=debug
APP_BUNDLE_PATH=./data/app-bundles
# Build
go build -o bin/synkronus cmd/synkronus/main.go
# Run
./bin/synkronus
# Or run directly
go run cmd/synkronus/main.go
Ensure PostgreSQL is running and create a database:
CREATE DATABASE synkronus;
The schema will be created automatically on first run.
cd synkronus-cli
go mod download
# Build
go build -o bin/synk ./cmd/synkronus
# Run
./bin/synk
git checkout -b feature/your-feature-name
Make your code changes following the coding standards.
# Run tests (from each package directory)
cd formulus && pnpm run test --ci --coverage --watchAll=false
cd formulus-formplayer && pnpm run test run
go test ./... # For Go projects (from synkronus/, etc.)
# Check code quality
pnpm run lint
pnpm run format:check
git add .
git commit -m "Description of changes"
git push origin feature/your-feature-name
Create a pull request on GitHub.
gofmt or goimportsgolangci-lint (if configured)The CI pipeline automatically:
# Check all components
cd formulus && pnpm run lint && cd ..
cd formulus-formplayer && pnpm run lint && cd ..
cd synkronus && go test ./... && cd ..
# Format all code
cd formulus && pnpm run format && cd ..
cd formulus-formplayer && pnpm run format && cd ..
cd synkronus && go fmt ./... && cd ..
# Clear and reinstall (run inside the package directory, e.g. formulus/)
rm -rf node_modules
pnpm install
If dependencies are missing after clone, ensure you ran pnpm install in that package directory (and built packages/tokens first when using @ode/tokens or @ode/components).
# Clean module cache
go clean -modcache
go mod download