Thanks for contributing. This doc covers the workflow, conventions, and gotchas you need to know before opening a PR.
If you haven't set up the project yet, start with README.md.
tasks/
├── src/
│ ├── app/
│ │ ├── (auth)/sign-in/ # GitHub sign-in page (unauthenticated layout)
│ │ ├── (app)/ # Authenticated pages + shared layout
│ │ │ ├── layout.tsx # Auth gate + topnav shell
│ │ │ └── projects/ # Project list + board pages
│ │ └── api/
│ │ ├── auth/[...all]/ # better-auth handler
│ │ ├── webhooks/github/ # inbound GitHub webhook endpoint
│ │ └── events/[projectId]/ # Server-Sent Events stream for live board updates
│ ├── components/
│ │ ├── board/ # Board, Column, Card, drag-and-drop
│ │ └── ui/ # shadcn/ui primitives
│ └── lib/
│ ├── db/
│ │ ├── schema.ts # Application tables (edit this for schema changes)
│ │ └── auth-schema.ts # better-auth managed tables - do not edit, regenerate instead
│ ├── auth/ # better-auth server config, browser client, session helper
│ ├── github/ # GitHub App client, org membership check, repos, comments, webhooks, reconcile
│ ├── realtime/ # in-process pub/sub feeding the SSE stream
│ ├── actions/ # server actions for project/column/card CRUD
│ └── ordering.ts # fractional-index helpers for drag-and-drop position
├── drizzle/ # auto-generated migration files - do not edit by hand
└── scripts/
├── seed.ts # demo project seed (needs a real signed-in user first)
└── reconcile.ts # manual run of the missed-webhook safety net
Caution
src/lib/db/auth-schema.ts is managed by better-auth. Do not edit it by hand - run pnpm auth:generate after changing src/lib/auth/auth.ts instead.
Read docs/architecture.mdx before touching anything under src/lib/github/. The short version:
- Sync is one-way: GitHub closing/merging moves a card; the app never writes card-close state back to GitHub.
- One GitHub App does both sign-in (OAuth) and automation (webhooks + API) - see
docs/guides/github-app-setup.mdx. - Every webhook delivery is deduped against the
webhook_eventtable before processing - never bypass that check when adding a new event handler. pnpm reconcilere-polls every linked card against live GitHub state - run it manually if you suspect a webhook was dropped.
- Branch off
mainusing the naming convention below. - Make your changes.
- Run
pnpm check && pnpm testlocally. - Open a pull request against
mainwith a short description of what changed and why.
| Type | Pattern | Example |
|---|---|---|
| Feature | feat/<short-description> |
feat/card-priority |
| Bug fix | fix/<short-description> |
fix/webhook-replay |
| Chore / infra | chore/<short-description> |
chore/update-deps |
Commit messages must follow Conventional Commits. A git hook enforces this automatically - bad commits are blocked before they land.
<type>: <short description>
| Type | When to use |
|---|---|
feat |
New feature or behaviour |
fix |
Bug fix |
chore |
Maintenance, deps, config - no behaviour change |
docs |
Documentation only |
style |
Formatting, whitespace - no logic change |
refactor |
Code restructure with no feature or fix |
perf |
Performance improvement |
ci |
CI/CD changes |
revert |
Reverts a previous commit |
The hook is installed automatically by pnpm install. Use git commit --no-verify only in genuine emergencies.
ESLint and Prettier are configured and run in CI.
pnpm lint # ESLint
pnpm format:check # Prettier check (no writes)
pnpm format # auto-fix formattingTip
In VS Code, install the ESLint and Prettier extensions and enable Format on Save - you won't need to run these manually.
- Keep PRs focused - one concern per PR.
- Write a useful description - explain what changed and why, not just what the diff shows.
- Schema changes need a migration - if your PR touches
src/lib/db/schema.ts, include the generated migration file (see Database Changes).
Always pair a schema edit with a generated migration and commit both together:
# 1. Edit src/lib/db/schema.ts
# 2. Generate the migration
pnpm db:generate
# 3. Apply it locally and verify the app still works
pnpm db:migrate
# 4. Commit schema.ts + the new file in drizzle/ in the same commitWarning
Never edit files inside drizzle/ by hand after they have been committed. Drizzle checksums each migration file and will refuse to run if it detects manual edits. To undo a migration, generate a new one that reverses the change - don't touch the existing file.
| Concern | Local dev | Production |
|---|---|---|
| Database | db/tasks.db in repo root |
/home/trickfire/db/tasks.db |
| Server | pnpm dev (port 3006) |
systemd (trickfire-tasks) + .next/standalone/server.js |
| HTTPS | None (HTTP on port 3006) | Cloudflare Tunnel provides TLS |
| Webhooks | Not reachable unless tunneled (e.g. cloudflared tunnel / ngrok) locally |
Reachable directly at /api/webhooks/github |
Check inline comments first - they're sparse but mark non-obvious behaviour. If you're still stuck, ask in the team Slack.