---
title: Contributing
description: How to develop Dagr and submit changes.
---

# Contributing to Dagr

Thank you for helping build a privacy-centric, self-hostable team chat.

## Development setup

1. Install Go 1.24 or newer.
2. Clone the repository.
3. Install dependencies: `make tidy`
4. Start dependencies: `make compose-infra` (Postgres, Redis, MinIO)
5. Apply migrations: `make migrate-up`
6. Run the API with reload: `make run-watch` (or `make run` once)

`make run-watch` uses [Air](https://github.com/air-verse/air) via `.air.toml`. Full stack in Docker: `make compose-up`.

## Desktop app (development)

The client lives in `client/`. It is an Electron desktop app and a Vite SPA you can host in the browser. Users should follow [Quick start](/quickstart) and the [desktop guides](/desktop). This section is for changing the client.

You need Node.js 20+, pnpm, and a [shadcnblocks](https://www.shadcnblocks.com) Pro key in `client/.env`:

```bash
SHADCNBLOCKS_API_KEY=sk_live_your_key
```

```bash
make client-install
make client-dev
```

`make client-dev-2` opens a second Electron window with its own session (invites, DMs, notifications). `make client-dev-web` starts the same UI in the browser (no Electron window).

Build-time defaults: `VITE_DAGR_CLOUD_URL` (Cloud tab), `VITE_DAGR_SELF_HOSTED_URL` (suggested self-hosted URL), and `VITE_DAGR_DEFAULT_MODE` (`cloud` or `selfhosted`). See `client/.env.example`. Keep the self-hosted default in sync with `HTTP_ADDR`.

Typecheck and build the renderer with `make client-build`. Build the browser SPA with `make client-build-web`. Package installers with `make client-package` (runs electron-builder for your current platform).

## Releasing the desktop app

GitHub Actions packages macOS (universal DMG) and Windows (NSIS) when you add a [SemVer 2.0.0](https://semver.org) tag without a `v` prefix. That includes `1.2.3`, `1.2.3-alpha.1`, `1.2.3-rc.1`, and `1.2.3+build.5`.

1. Set the version you want in `client/package.json`, or let the workflow take it from the tag.
2. Create **only a git tag**. Do not use “Draft a new release” or publish a prerelease in the GitHub UI first.
   `git tag 1.2.3-alpha.1 && git push origin 1.2.3-alpha.1`
3. Wait for **Release desktop**. One job creates a single **draft** for that tag. The macOS and Windows jobs only attach files to it.
4. When both `Dagr_<version>.dmg` and `Dagr_<version>.exe` are on that draft, publish it. For an alpha, publish it as a prerelease.

If you already published a GitHub Release for that tag, CI deletes that release (the tag stays) and creates a draft so the files can be uploaded.

The download site lists the newest published release that has installers, including prereleases. The packaged app uses electron-updater to download and install that release. Keep these files on the published GitHub release: `latest-mac.yml`, `latest.yml`, `Dagr_<version>.zip`, `Dagr_<version>.exe`, and the matching `.blockmap` files. The in-app update checker follows the Stable or Pre-release choice in App settings. Drafts are ignored. Stable uses published full releases. Pre-release sets `allowPrerelease`.

The GitHub repository must be public for those checks to work in the packaged app. A private repo makes the unauthenticated GitHub API return 404. The website can set `GITHUB_TOKEN` if you still need to read a private repo. The desktop app can use `DAGR_GITHUB_TOKEN` or `GITHUB_TOKEN` for local checks only. Do not ship a token in the app.

Builds are unsigned in this pass. Unsigned macOS builds often cannot replace the running app, so the UI falls back to opening the GitHub DMG. Signing and notarization come later.

## Download website

The public download page lives in `website/`. It is a Next.js app you can host in Docker.

```bash
make website-install
make website-dev
```

Build a production image from the repository root so the context matches Coolify and other hosts that default to `/`:

```bash
make website-docker
```

Use Dockerfile `/website/Dockerfile` and base directory `/`. Do not add the site to the API Compose stack.

## Documentation

Docs are authored as MDX under `docs/` and configured by root `docs.json` for [docs.page](https://docs.page).

Preview locally:

```bash
make docs-preview
```

Check links and MDX:

```bash
make docs-check
```

## Workflow

- Keep changes focused and minimal.
- Prefer British English in user-facing docs.
- API routes belong under `/api/v1/`.
- Self-hosting must stay one-command via Docker Compose where possible.
- Do not introduce required external SaaS dependencies.

## Checks

```bash
make build
make test
make lint
```

## Pull requests

- Describe the problem and the approach.
- Link related issues when applicable.
- Include a short test plan for behavioural changes.

## Licence

By contributing, you agree that your contributions are licensed under the Apache License 2.0.
