Skip to content

Commit 505b49b

Browse files
Dispatch 1.0.0: open-source collaborative inbox for teams
Shared Gmail, Microsoft 365 and IMAP inboxes with internal comments, @mentions, assignments, labels, snooze, send later, undo send, canned responses, signatures, rules, team chat, tasks, contacts, analytics, an AI assistant, REST API and signed webhooks, realtime presence and a command palette. Multi-workspace instances with custom roles and permissions, a super admin panel, passwordless magic-link sign-in, optional Stripe billing, a built-in marketing site, and Docker Compose / Coolify deployment where the .env only contains DOMAIN.
0 parents  commit 505b49b

661 files changed

Lines changed: 124388 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.dockerignore‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Keep the build context small and free of local state and secrets.
2+
3+
# dependencies & build output (rebuilt inside the image)
4+
node_modules
5+
.pnpm-store
6+
.next
7+
out
8+
build
9+
dist
10+
coverage
11+
*.tsbuildinfo
12+
next-env.d.ts
13+
14+
# local data, secrets & tooling state
15+
.data
16+
.dev
17+
.omc
18+
.env
19+
.env.*
20+
!.env.example
21+
*.pem
22+
*.log
23+
24+
# VCS, CI & editor files
25+
.git
26+
.github
27+
.vscode
28+
.idea
29+
.DS_Store
30+
31+
# not needed in the image
32+
docs
33+
docker-compose*.yml
34+
Dockerfile
35+
.dockerignore

‎.env.example‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# The public hostname Dispatch is served on (no protocol, no path).
2+
# This is the only setting: secrets are generated on first boot and everything
3+
# else is configured in the browser at https://<DOMAIN>/setup.
4+
DOMAIN=mail.example.com
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Bug report
2+
description: Something in Dispatch doesn't work as expected
3+
labels: ["bug", "triage"]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Thanks for taking the time to report a bug.
9+
**Security issues:** please do not open a public issue. Report them privately via
10+
[GitHub security advisories](https://github.com/codextde/dispatch/security/advisories/new) instead.
11+
- type: textarea
12+
id: what-happened
13+
attributes:
14+
label: What happened?
15+
description: A clear description of the bug. Screenshots or screen recordings help a lot.
16+
validations:
17+
required: true
18+
- type: textarea
19+
id: steps
20+
attributes:
21+
label: Steps to reproduce
22+
placeholder: |
23+
1. Go to …
24+
2. Click on …
25+
3. See error …
26+
validations:
27+
required: true
28+
- type: textarea
29+
id: expected
30+
attributes:
31+
label: Expected behavior
32+
validations:
33+
required: true
34+
- type: dropdown
35+
id: deployment
36+
attributes:
37+
label: Deployment
38+
options:
39+
- Dispatch Cloud
40+
- Self-hosted with Docker Compose
41+
- Self-hosted with Coolify
42+
- Local development
43+
- Other
44+
validations:
45+
required: true
46+
- type: input
47+
id: version
48+
attributes:
49+
label: Version
50+
description: Shown at `https://<your-domain>/api/health` or the image tag you run.
51+
placeholder: "1.0.0"
52+
- type: dropdown
53+
id: provider
54+
attributes:
55+
label: Mail provider (if relevant)
56+
options:
57+
- Not related to a mailbox
58+
- Gmail / Google Workspace
59+
- Outlook / Microsoft 365
60+
- Other IMAP / SMTP
61+
- type: input
62+
id: browser
63+
attributes:
64+
label: Browser and OS
65+
placeholder: "Safari 19 on iOS 20"
66+
- type: textarea
67+
id: logs
68+
attributes:
69+
label: Relevant logs
70+
description: "Output of `docker compose logs app worker --tail 200`. Remove email addresses, tokens and other personal data."
71+
render: shell

‎.github/ISSUE_TEMPLATE/config.yml‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: Questions and ideas
4+
url: https://github.com/codextde/dispatch/discussions
5+
about: Ask questions, share setups and discuss ideas with the community.
6+
- name: Report a security vulnerability
7+
url: https://github.com/codextde/dispatch/security/advisories/new
8+
about: Please report security issues privately, never in a public issue.
9+
- name: Documentation
10+
url: https://github.com/codextde/dispatch/tree/main/docs
11+
about: Self-hosting, Coolify, configuration and API guides.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Feature request
2+
description: Suggest an idea or improvement for Dispatch
3+
labels: ["enhancement"]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Before opening a request, please check the [roadmap](https://github.com/codextde/dispatch#roadmap) and
9+
[existing issues](https://github.com/codextde/dispatch/issues?q=is%3Aissue). Open-ended ideas fit well in
10+
[Discussions](https://github.com/codextde/dispatch/discussions).
11+
- type: textarea
12+
id: problem
13+
attributes:
14+
label: What problem are you trying to solve?
15+
description: Describe the situation and why the current behavior falls short.
16+
validations:
17+
required: true
18+
- type: textarea
19+
id: solution
20+
attributes:
21+
label: Proposed solution
22+
description: How would you like it to work?
23+
validations:
24+
required: true
25+
- type: textarea
26+
id: alternatives
27+
attributes:
28+
label: Alternatives and workarounds
29+
description: Anything you've tried, or how other tools handle it.
30+
- type: checkboxes
31+
id: contribute
32+
attributes:
33+
label: Contribution
34+
options:
35+
- label: I'd be willing to open a pull request for this

‎.github/PULL_REQUEST_TEMPLATE.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## What does this change?
2+
3+
<!-- A short summary of the change and why it's needed. Link related issues: "Closes #123". -->
4+
5+
## How was it tested?
6+
7+
<!-- Steps you took to verify it works: manual testing, new tests, screenshots for UI changes. -->
8+
9+
## Checklist
10+
11+
- [ ] `pnpm typecheck`, `pnpm lint` and `pnpm test` pass
12+
- [ ] Every tenant query filters by `orgId`; conversation access goes through `src/server/access.ts`
13+
- [ ] New mutations check permissions and are audited where it matters
14+
- [ ] Database changes include a generated migration (`pnpm db:generate --name <change>`)
15+
- [ ] UI works at 375px width and in dark mode
16+
- [ ] Docs updated if behavior, configuration or the API changed

‎.github/dependabot.yml‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: npm
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
day: monday
8+
open-pull-requests-limit: 10
9+
groups:
10+
next-react:
11+
patterns: ["next", "eslint-config-next", "react", "react-dom", "@types/react", "@types/react-dom"]
12+
tiptap:
13+
patterns: ["@tiptap/*"]
14+
aws-sdk:
15+
patterns: ["@aws-sdk/*"]
16+
production:
17+
dependency-type: production
18+
update-types: ["minor", "patch"]
19+
development:
20+
dependency-type: development
21+
update-types: ["minor", "patch"]
22+
23+
- package-ecosystem: github-actions
24+
directory: /
25+
schedule:
26+
interval: weekly
27+
day: monday
28+
groups:
29+
actions:
30+
patterns: ["*"]
31+
32+
# Base images in the Dockerfile. Node majors are chosen deliberately (LTS),
33+
# so only minor/patch updates are proposed.
34+
- package-ecosystem: docker
35+
directory: /
36+
schedule:
37+
interval: weekly
38+
day: monday
39+
ignore:
40+
- dependency-name: node
41+
update-types: ["version-update:semver-major"]

‎.github/workflows/ci.yml‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
permissions:
9+
contents: read
10+
11+
concurrency:
12+
group: ci-${{ github.ref }}
13+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
14+
15+
env:
16+
NEXT_TELEMETRY_DISABLED: 1
17+
18+
jobs:
19+
check:
20+
name: Typecheck, lint, test & build
21+
runs-on: ubuntu-24.04
22+
timeout-minutes: 20
23+
steps:
24+
- uses: actions/checkout@v7
25+
26+
- uses: pnpm/action-setup@v6
27+
with:
28+
cache: true
29+
30+
- uses: actions/setup-node@v7
31+
with:
32+
node-version: 24
33+
34+
- name: Install dependencies
35+
run: pnpm install --frozen-lockfile
36+
37+
- name: Generate route types
38+
run: pnpm next typegen
39+
40+
- name: Typecheck
41+
run: pnpm typecheck
42+
43+
- name: Lint
44+
run: pnpm lint
45+
46+
- name: Test
47+
run: pnpm test
48+
49+
- name: Restore Next.js build cache
50+
uses: actions/cache@v6
51+
with:
52+
path: .next/cache
53+
key: nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('src/**', 'public/**', 'next.config.ts') }}
54+
restore-keys: |
55+
nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-
56+
57+
- name: Build
58+
run: pnpm build
59+
60+
compose:
61+
name: Validate docker-compose.yml
62+
runs-on: ubuntu-24.04
63+
timeout-minutes: 5
64+
steps:
65+
- uses: actions/checkout@v7
66+
- name: docker compose config
67+
run: |
68+
DOMAIN=ci.example.com docker compose -f docker-compose.yml config --quiet
69+
cp docker-compose.override.example.yml docker-compose.override.yml
70+
DOMAIN=ci.example.com docker compose config --quiet

‎.github/workflows/docker.yml‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Docker image
2+
3+
# Builds ghcr.io/codextde/dispatch for linux/amd64 and linux/arm64 on native
4+
# runners (no QEMU) with Docker's reusable github-builder workflow, which adds
5+
# SLSA provenance, an SBOM and signed attestations.
6+
#
7+
# push to main → :main, :sha-<short> (edge builds)
8+
# tag v1.2.3 → :1.2.3, :1.2, :1, :latest, :sha-<short> (releases; no :latest for pre-releases)
9+
# pull request → build only, nothing is pushed
10+
11+
on:
12+
push:
13+
branches: [main]
14+
tags: ["v*"]
15+
pull_request:
16+
paths:
17+
- Dockerfile
18+
- .dockerignore
19+
- docker/**
20+
- package.json
21+
- pnpm-lock.yaml
22+
- .github/workflows/docker.yml
23+
workflow_dispatch:
24+
25+
permissions:
26+
contents: read
27+
28+
concurrency:
29+
group: docker-${{ github.ref }}
30+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
31+
32+
jobs:
33+
image:
34+
uses: docker/github-builder/.github/workflows/build.yml@v1
35+
permissions:
36+
contents: read
37+
id-token: write
38+
packages: write
39+
attestations: write
40+
with:
41+
output: image
42+
push: ${{ github.event_name != 'pull_request' }}
43+
platforms: linux/amd64,linux/arm64
44+
meta-images: ghcr.io/codextde/dispatch
45+
meta-tags: |
46+
type=ref,event=branch
47+
type=semver,pattern={{version}}
48+
type=semver,pattern={{major}}.{{minor}}
49+
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
50+
type=sha
51+
set-meta-labels: true
52+
set-meta-annotations: true
53+
cache: true
54+
cache-mode: max
55+
sbom: true
56+
secrets:
57+
registry-auths: |
58+
- registry: ghcr.io
59+
username: ${{ github.actor }}
60+
password: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)