Skip to content

Local Development Setup

This page is for contributors and anyone who wants to run Doable from source with hot-reload across all services. If you just want to use Doable, the Quick Start is faster.

Prerequisites

Tool Version Notes
Node.js 22+ (20 minimum) nodejs.org or nvm install 22
pnpm 9+ corepack enable && corepack prepare pnpm@9.15.4 --activate
PostgreSQL 16+ With extensions pgvector, pgcrypto, pg_trgm
Git any recent
psmux optional Windows-only terminal multiplexer for dev.ps1

Tip: instead of installing PostgreSQL locally, just run the Docker Postgres service:

docker compose -f docker/docker-compose.yml up postgres -d
It auto-installs pgvector, pgcrypto, and pg_trgm from docker/init.sql.

1. Clone & install

git clone https://github.com/doable-me/doable.git
cd doable
pnpm install

pnpm install uses pnpm workspaces — all packages, services, and apps share a single dependency store under the root node_modules/.

2. Configure environment

cp .env.example .env

At minimum set:

JWT_SECRET=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
INTERNAL_SECRET=$(openssl rand -hex 32)
DATABASE_URL=postgres://doable:doable_secret@localhost:5432/doable

Add an AI key to enable the chat agent (any one):

ANTHROPIC_API_KEY=...
# or
OPENAI_API_KEY=...
# or
COPILOT_CLI_PATH=/usr/local/bin/copilot

The full reference is at Environment Variables.

3. Start PostgreSQL

# Easiest — Docker:
docker compose -f docker/docker-compose.yml up postgres -d

# Or, native install — make sure pgvector/pgcrypto/pg_trgm are installed
psql -U postgres -c "CREATE USER doable WITH PASSWORD 'doable_secret';"
psql -U postgres -c "CREATE DATABASE doable OWNER doable;"
psql -U doable -d doable -c "CREATE EXTENSION IF NOT EXISTS pgcrypto;"
psql -U doable -d doable -c "CREATE EXTENSION IF NOT EXISTS pgvector;"
psql -U doable -d doable -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"

4. Run migrations

pnpm db:migrate

Migrations live in packages/db/migrations/ and are applied in lexicographic order.

5. Start the dev servers

macOS / Linux

pnpm dev          # all services in parallel via Turborepo
# or run individually
pnpm dev:web      # http://localhost:3000
pnpm dev:api      # http://localhost:4000
pnpm dev:ws       # ws://localhost:4001

Windows (psmux)

.\dev.ps1          # creates a psmux session "doable" with web/api/ws windows
.\dev.ps1 -Kill    # stops the session

The script creates one terminal per service and follows the project rule that all dev services bind to 127.0.0.1 (see Network Binding).

6. Open the app

Visit http://localhost:3000, sign up with email/password (or OAuth if you configured it), and create your first project.

Useful commands

Command Effect
pnpm dev All services, watch mode
pnpm build Build everything
pnpm type-check TypeScript check across the monorepo
pnpm lint ESLint across all packages
pnpm format Prettier-format the entire repo
pnpm test Vitest across packages that have tests
pnpm db:migrate Apply pending DB migrations
pnpm clean Remove dist/ and .turbo/ from every workspace

Editor recommendations

  • VS Code with the recommended extensions in .vscode/extensions.json (TypeScript, ESLint, Prettier, Tailwind, PostgreSQL, Hono).
  • Enable “TypeScript: workspace version” so all packages share the same tsc.

Known dev gotchas

  • The API and WS servers use tsx watch — no build step is needed; saving a .ts file restarts them in <1s.
  • Next.js uses Turbopack in dev mode for sub-second HMR.
  • The first pnpm dev after a fresh clone takes longer because Next.js compiles all routes on demand.
  • If you see “ECONNREFUSED ::1:4000” from the web app, make sure API_HOST=127.0.0.1 (not localhost) — Node's resolver may pick IPv6 first.

→ Next: walk through your first project.