Development Setup¶
Prerequisites¶
| Tool | Version | Purpose |
|---|---|---|
| Python | 3.11+ | Backend runtime |
| Node.js | 18+ | Frontend runtime |
| pip | Latest | Python package manager |
| npm | Latest | Node package manager |
Installation¶
git clone https://github.com/onegunsamurai/OpenLearning.git
cd OpenLearning
make install
Environment Configuration¶
Backend (backend/.env)¶
cp backend/.env.example backend/.env
| Variable | Required | Default | Description |
|---|---|---|---|
ANTHROPIC_API_KEY |
No | — | Fallback Anthropic API key (users provide their own via BYOK) |
CORS_ORIGINS |
No | http://localhost:3000 |
Allowed CORS origins |
DATABASE_URL |
No | postgresql+asyncpg://openlearning:openlearning@localhost:5432/openlearning |
SQLAlchemy async database URL |
TEST_DATABASE_URL |
No | — | Database URL for tests (used by CI and conftest.py) |
LANGSMITH_API_KEY |
No | — | LangSmith API key (for tracing) |
LANGSMITH_PROJECT |
No | open-learning |
LangSmith project name |
LANGSMITH_TRACING |
No | false |
Enable LangSmith tracing |
GITHUB_CLIENT_ID |
No* | — | GitHub OAuth app client ID |
GITHUB_CLIENT_SECRET |
No* | — | GitHub OAuth app secret |
JWT_SECRET_KEY |
No* | — | JWT signing key (random 256-bit hex string) |
ENCRYPTION_KEY |
No* | — | Fernet key for API key encryption |
FRONTEND_URL |
No | http://localhost:3000 |
Frontend URL for OAuth redirects |
*Required for authentication. Without these, protected endpoints return 501/401. Demo mode works without auth.
Frontend (frontend/.env.local)¶
cp frontend/.env.example frontend/.env.local
| Variable | Required | Default | Description |
|---|---|---|---|
NEXT_PUBLIC_API_URL |
No | http://localhost:8000 |
Backend API URL |
Running Locally¶
# Start both frontend and backend concurrently
make dev
# Or run them separately
make dev-backend # http://localhost:8000
make dev-frontend # http://localhost:3000
Makefile Reference¶
| Target | Command | Description |
|---|---|---|
make dev |
make -j2 dev-backend dev-frontend |
Start both servers concurrently |
make dev-db |
docker compose -f ... up db -d |
Start PostgreSQL container (port 5432 exposed) |
make dev-backend |
cd backend && uvicorn app.main:app --reload --port 8000 |
Start backend with hot reload |
make dev-frontend |
cd frontend && npm run dev |
Start frontend dev server |
make install |
make install-backend install-frontend install-hooks |
Install all dependencies and pre-commit hooks |
make install-backend |
cd backend && pip install -r requirements.txt |
Install Python dependencies |
make install-frontend |
cd frontend && npm install |
Install Node dependencies |
make check |
make lint typecheck test fmt-check build-frontend |
Run all checks (mirrors CI) |
make lint |
make lint-backend lint-frontend |
Lint both codebases |
make lint-backend |
cd backend && ruff check . |
Lint Python code |
make lint-frontend |
cd frontend && npx eslint . |
Lint TypeScript code |
make typecheck |
cd frontend && npx tsc --noEmit |
TypeScript type checking |
make test |
make test-backend test-frontend |
Run all tests (backend + frontend) |
make test-backend |
cd backend && pytest tests/ -v |
Run backend tests |
make test-frontend |
cd frontend && npm test |
Run frontend tests (Vitest) |
make fmt |
cd backend && ruff format . && ruff check --fix . |
Format Python code |
make fmt-backend |
cd backend && ruff format . && ruff check --fix . |
Format Python code (backend only) |
make fmt-check |
make fmt-check-backend |
Check Python formatting (no changes) |
make fmt-check-backend |
cd backend && ruff format --check . |
Verify Python code is formatted |
make build-frontend |
cd frontend && npm run build |
Build frontend for production |
make install-hooks |
pip install pre-commit && pre-commit install |
Install pre-commit git hooks |
make pre-commit |
pre-commit run --all-files |
Run all pre-commit checks manually (runs Ruff, forbid-env-files.sh, and lint-frontend-staged.sh) |
make generate-api |
bash scripts/generate-api.sh |
Generate TypeScript types from OpenAPI spec |
make docs-serve |
mkdocs serve |
Preview docs locally (port 8000 — conflicts with dev-backend; use mkdocs serve --dev-addr 127.0.0.1:8001 to run both) |
make docs-build |
mkdocs build |
Build docs site |
make docker-build |
docker compose build |
Build Docker images |
make docker-dev |
docker compose ... up --build |
Start stack with hot-reload |
make docker-up |
docker compose up --build |
Start production-like stack |
make docker-down |
docker compose down |
Stop containers |
make docker-clean |
docker compose down -v |
Stop and remove volumes |
Pre-commit Hooks¶
make install sets up pre-commit hooks automatically. The hooks run on every commit and include:
- Ruff — Python lint and format checks
scripts/forbid-env-files.sh— Blocks committing.envfiles with secretsscripts/lint-frontend-staged.sh— Lints staged frontend files with ESLint
Configuration lives in .pre-commit-config.yaml. Run make pre-commit to execute all hooks manually.
Type Generation¶
TypeScript types are auto-generated from the backend's OpenAPI spec:
# With backend running
make generate-api
This generates types into frontend/src/lib/generated/. Do not edit these files manually — they are overwritten on each generation.
Database¶
The backend requires PostgreSQL. Start a local instance with Docker:
make dev-db
This uses both docker-compose.yml and docker-compose.dev.yml to start a PostgreSQL container with port 5432 exposed to the host, using default credentials (openlearning:openlearning). Tables are created automatically on first run via init_db().
To use your own PostgreSQL instance, set DATABASE_URL in backend/.env.
For tests, set TEST_DATABASE_URL to point to a separate database (CI uses openlearning_test).
Worktree Docker Environments¶
When developing in a git worktree (.claude/worktrees/issue-<N>), use isolated Docker
environments to avoid port conflicts with other worktrees or the main repo:
make worktree-dev ISSUE=144 # start isolated stack
make worktree-dev-down ISSUE=144 # stop stack
make worktree-e2e ISSUE=144 # run E2E tests against stack
Each worktree gets unique ports derived from the issue number (e.g., issue 144: frontend on 3144, backend on 8144). See Worktree Environments for full details.
| Target | Description |
|---|---|
make worktree-dev ISSUE=N |
Start isolated Docker stack for worktree |
make worktree-dev-down ISSUE=N |
Stop the stack (add VOLUMES=yes to wipe DB) |
make worktree-e2e ISSUE=N |
Start stack + run Playwright E2E tests |