> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opendot.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Contributing

> Set up OpenDot, choose a contribution area, and run the right checks before opening a pull request.

OpenDot is built around one loop: build a voice agent, tune the
VAD/STT/ASR/LLM/TTS pipeline, bind it to a real device, run a session, and
inspect what happened. Good contributions usually make one part of that loop
easier to understand, operate, debug, or extend.

Use this page for setup and pull request expectations. Use Contribution areas
as the canonical map for choosing a track.

<CardGroup cols={2}>
  <Card title="Contribution areas" icon="git-pull-request" href="/contribution-areas">
    Choose a track and see current maturity, project briefs, verification, and starting
    points.
  </Card>

  <Card title="Roadmap" icon="map" href="/roadmap">
    See current, next, and later priorities across voice, platform, transport, device,
    hardware, firmware, docs, and tooling.
  </Card>

  <Card title="Platform architecture" icon="network" href="/architecture">
    See how the console, API, database, runtime, providers, and firmware work together.
  </Card>

  <Card title="Repo map" icon="folder-tree" href="/repo-map">
    Find the files and checks that match the part of OpenDot you want to change.
  </Card>
</CardGroup>

## Local setup

For the fastest full-stack run, use Docker Compose:

```bash theme={null}
cp .env.example .env
docker compose up --build
```

Open the console:

```text theme={null}
http://localhost:5173
```

Create a local email/password account, then open **Agent Studio**. Add
`DEEPGRAM_API_KEY` and `OPENAI_API_KEY` to `.env` before testing real voice
turns. Leave `OPENAI_BASE_URL` blank for OpenAI or set it to an
OpenAI-compatible provider base URL.
`OPENAI_BASE_URL` affects the Sandwich LLM stage only; Speech-to-speech Browser
Test and Speech-to-speech Dot sessions use the runtime's `OPENAI_API_KEY` for
OpenAI Realtime.

For process-by-process development, install the workspace and run the API,
frontend, and runtime separately:

```bash theme={null}
corepack enable
corepack prepare pnpm@11.1.3 --activate
pnpm install
pnpm --filter ./platform run db:migrate

pnpm run api
pnpm run dev
pnpm run runtime
```

See the [Quickstart](/quickstart) for the full setup flow and
[Database inspection](/database-inspection) for Drizzle Studio.

## Choose an area

| Track                                | Common work                                                                                                                           | Minimum check                                           |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| Voice Pipeline & Providers           | VAD, STT/ASR, LLM, TTS, realtime APIs, provider adapters, stage contracts                                                             | Platform checks plus live Browser Test when possible    |
| Voice Agents & Harnesses             | Prompts, knowledge, tools, local model harnesses, evals, framework integration categories                                             | Platform checks and docs when behavior changes          |
| Platform Control Plane               | Agent Studio, Configuration, Browser Test, Dot Device, Settings, runtime diagnostics UX                                               | `pnpm run lint && pnpm run test && pnpm run build`      |
| Platform Backend & Data              | Fastify API, auth, Drizzle/Postgres schema, runtime tokens, settings, deployments                                                     | Platform checks plus migration review when data changes |
| Media Transport                      | WebSocket audio/data sessions, browser WebRTC Realtime sessions, device Realtime bridge, runtime protocols, future SFU/fleet adapters | Platform checks plus manual runtime testing             |
| Device Communication & Fleet         | Device presence, state, commands, telemetry, diagnostics, OTA metadata                                                                | Platform/runtime checks and device notes when relevant  |
| Dot Hardware                         | CAD, enclosure, acoustics, PCB, BOM, fixtures, reference constraints                                                                  | Hardware/source review and docs checks                  |
| Dot Firmware & Edge                  | ESP-IDF drivers, provisioning, wake/audio/display, exploratory MicroPython and inference research                                     | `idf.py build` when ESP-IDF is available                |
| Docs, Tooling & Developer Experience | Setup docs, diagrams, examples, CI, templates, contributor workflow                                                                   | Formatting and link checks                              |

See [Contribution areas](/contribution-areas) for the detailed map, project
briefs, and starting files for each track.

## Before opening a pull request

* Target `develop` for normal pull requests. `main` is the stable release
  branch and receives promotion PRs from `develop`.
* Use a Conventional Commit PR title.
* Keep the pull request focused on one problem or feature.
* Update docs when setup, runtime behavior, configuration, device flow, or
  architecture changes.
* Include screenshots or short recordings for visible UI changes.
* Describe browser, runtime, or device testing when touching audio, WebSocket,
  WebRTC, firmware, activation, or provisioning behavior.
* Keep secrets out of commits. Use `.env` locally and keep `.env.example` safe.

Examples:

```text theme={null}
feat(platform): add device pairing status
fix(runtime): close stale voice sessions
docs: clarify firmware setup
```

## Release flow

OpenDot uses one repository-wide product version for the platform UI, local
runtime, firmware source, docs, and repo tooling. Tags named `vX.Y.Z` and GitHub
Releases are the canonical release record.

Contributor PRs are squash-merged into `develop`; the squash commit comes from
the PR title, so the title must be a valid Conventional Commit. Release-impacting
types are `feat`, `fix`, and `perf`. `docs`, `chore`, `ci`, `test`, `style`,
`refactor`, and `build` do not create releases unless intentionally marked as
breaking with `!` or `BREAKING CHANGE:`.

When a release is ready, maintainers open a promotion PR from `develop` to
`main` and merge it with a normal merge commit. CI on `main` then runs
semantic-release, creates the next `vX.Y.Z` tag, and publishes GitHub Release
notes.

The first public release channel ships source and release notes only. Docker
images, npm packages, firmware binaries, and firmware OTA version syncing are
future packaging tracks.

For repository-wide expectations, also read the root
[`CONTRIBUTING.md`](https://github.com/itsperini/opendot/blob/main/CONTRIBUTING.md).
