# Install dependencies and setup hooks
yarn setup
# Start full development stack (auto-assigns unique ports per worktree)
yarn dev # or equivalently: make devyarn dev/make dev: Start full dev stack with worktree-isolated ports. A dev portal at http://localhost:9900 auto-starts showing all running stacks.yarn dev:down/make dev-down: Stop the dev stack for the current worktreemake dev-portal: Start the dev portal manually (auto-started byyarn dev)yarn lint: Run linting across all packagesyarn dev:unit: Run unit tests in watch mode (per package)
.env.development: Development environment variables- Docker Compose manages ClickHouse, MongoDB, OTel Collector
- Hot reload enabled for all services in development
When multiple git worktrees need to run the dev stack simultaneously (e.g.
multiple agents or developers working in parallel), use make dev instead of
yarn dev. This automatically assigns unique ports per worktree.
- A deterministic slot (0-99) is computed from the worktree directory name (via
cksum) - Each service gets a unique port:
base + slot(see table below) - Docker Compose runs with a unique project name (
hdx-dev-<slot>) - Volume paths include the slot to prevent data corruption between worktrees
Ports are allocated in the 30100-31199 range to avoid conflicts with CI integration tests (14320-40098) and E2E tests (20320-21399).
| Service | Base Port | Range | Env Variable |
|---|---|---|---|
| API server | 30100 | 30100 - 30199 | HYPERDX_API_PORT |
| App (Next.js) | 30200 | 30200 - 30299 | HYPERDX_APP_PORT |
| OpAMP | 30300 | 30300 - 30399 | HYPERDX_OPAMP_PORT |
| MongoDB | 30400 | 30400 - 30499 | HDX_DEV_MONGO_PORT |
| ClickHouse HTTP | 30500 | 30500 - 30599 | HDX_DEV_CH_HTTP_PORT |
| ClickHouse Native | 30600 | 30600 - 30699 | HDX_DEV_CH_NATIVE_PORT |
| OTel health | 30700 | 30700 - 30799 | HDX_DEV_OTEL_HEALTH_PORT |
| OTel gRPC | 30800 | 30800 - 30899 | HDX_DEV_OTEL_GRPC_PORT |
| OTel HTTP | 30900 | 30900 - 30999 | HDX_DEV_OTEL_HTTP_PORT |
| OTel metrics | 31000 | 31000 - 31099 | HDX_DEV_OTEL_METRICS_PORT |
| OTel JSON HTTP | 31100 | 31100 - 31199 | HDX_DEV_OTEL_JSON_HTTP_PORT |
The dev portal is a centralized web dashboard that discovers all running worktree stacks by inspecting Docker container labels and slot files.
# Start the portal (runs on fixed port 9900)
make dev-portal
# Open in browser
open http://localhost:9900The portal auto-refreshes every 3 seconds and shows each worktree's:
- Branch name and slot number
- All services with status (running/stopped) and clickable port links
- Separate cards for each active worktree
# Use a specific slot instead of the auto-computed one
HDX_DEV_SLOT=5 make dev- Unit Tests: Jest with TypeScript support
- Integration Tests: Jest with database fixtures
- Frontend Testing: React Testing Library + Jest
- E2E Testing: Playwright (frontend) and Custom smoke tests with BATS (ingestion)
- TDD Approach: Write tests before implementation for new features
- Test organization: Tests co-located with source files in
__tests__/directories - Mocking: MSW for API mocking in frontend tests
- Database testing: Isolated test databases with fixtures
For integration testing:
# Build dependencies (run once before first test run)
make dev-int-build
# Run API integration tests (spins up Docker services, runs tests, tears down)
make dev-int FILE=<TEST_FILE_NAME>
# Run common-utils integration tests
make dev-int-common-utils FILE=<TEST_FILE_NAME>Multi-agent / worktree support:
The make dev-int command automatically assigns unique Docker ports per
worktree directory, so multiple agents can run integration tests in parallel
without port conflicts.
- A deterministic slot (0-99) is computed from the worktree directory name
- Each slot gets its own Docker Compose project name and port range
- Override the slot manually:
make dev-int HDX_CI_SLOT=5 FILE=alerts - The slot and assigned ports are printed when
dev-intstarts
Port mapping (base + slot):
| Service | Default port (slot 0) | Variable |
|---|---|---|
| ClickHouse HTTP | 18123 | HDX_CI_CH_PORT |
| MongoDB | 39999 | HDX_CI_MONGO_PORT |
| API test server | 19000 | HDX_CI_API_PORT |
| OpAMP | 14320 | HDX_CI_OPAMP_PORT |
CI Testing Notes:
- Uses separate Docker Compose configuration (
docker-compose.ci.yml) - Isolated test environment with unique
-p int-<slot>project name - Includes all necessary services (ClickHouse, MongoDB, OTel Collector)
- Tests run against real database instances for accurate integration testing
E2E tests use the same slot-based isolation pattern as integration tests, with their own dedicated port range (20320-21399) so they can run simultaneously with both the dev stack and CI integration tests.
E2E port mapping (base + slot):
| Service | Base Port | Range | Env Variable |
|---|---|---|---|
| OpAMP | 20320 | 20320 - 20419 | HDX_E2E_OPAMP_PORT |
| ClickHouse HTTP | 20500 | 20500 - 20599 | HDX_E2E_CH_PORT |
| ClickHouse Native | 20600 | 20600 - 20699 | HDX_E2E_CH_NATIVE_PORT |
| API server | 21000 | 21000 - 21099 | HDX_E2E_API_PORT |
| MongoDB | 21100 | 21100 - 21199 | HDX_E2E_MONGO_PORT |
| App (local) | 21200 | 21200 - 21299 | HDX_E2E_APP_LOCAL_PORT |
| App (fullstack) | 21300 | 21300 - 21399 | HDX_E2E_APP_PORT |
# Run all E2E tests
make e2e
# Run a specific test file (dev mode: hot reload, containers kept running)
make dev-e2e FILE=navigation
# Run a specific test by grep pattern
make dev-e2e FILE=navigation GREP="help menu"
# Grep across all files
make dev-e2e GREP="should navigate"
# Open HTML report after tests finish (screenshots, traces, step-by-step)
make dev-e2e FILE=navigation REPORT=1
# Or call the script directly for more control
./scripts/test-e2e.sh --ui --last-failed
# Override the slot manually
HDX_E2E_SLOT=5 ./scripts/test-e2e.sh- A deterministic slot (0-99) is computed from the worktree directory name
- Each slot gets its own Docker Compose project name (
e2e-<slot>) and port range - The slot and assigned ports are printed when E2E tests start
Port range safety: E2E has its own dedicated port range (20320-21399) that does not overlap with CI integration tests (14320-40098) or the dev stack (30100-31199), so all three can run simultaneously from the same worktree.
- API First: Define API endpoints and data models
- Database Models: Create/update Mongoose schemas and ClickHouse queries
- Frontend Integration: Build UI components and integrate with API
- Testing: Add unit and integration tests
- Documentation: Update relevant docs
- Check browser and server console output for errors, warnings, or relevant logs
- Add targeted logging to trace execution and variable states
- For persistent issues, check
fixes/directory for documented solutions - Document complex fixes in
fixes/directory with descriptive filenames
The project uses Husky + lint-staged to automatically run:
- Prettier for formatting
- ESLint for linting
- API doc generation (for external API changes)
These run automatically on git commit for staged files.
If you need to manually lint:
# Per-package linting with auto-fix
cd packages/app && yarn run lint:fix
cd packages/api && yarn run lint:fix
cd packages/common-utils && yarn lint:fix
# Check all packages
yarn run lint- Config:
packages/api/src/config.ts,packages/app/next.config.mjs,docker-compose.dev.yml - Models:
packages/api/src/models/ - API Routes:
packages/api/src/routers/ - Controllers:
packages/api/src/controllers/ - Pages:
packages/app/pages/ - Components:
packages/app/src/ - Shared Utils:
packages/common-utils/src/