Skip to content

Contributing

Archi edited this page Oct 20, 2026 · 2 revisions

Contributing

Nautelle is a TypeScript monorepo — Bun workspaces and Turborepo — with a NestJS API, a Next.js web app, a Bun-compiled runner and a framework-free shared package. This page covers getting a development setup running, the conventions every change follows, how CI decides what to test, and how decisions are recorded. The authority on what Nautelle is and how it is built is docs/: code that disagrees with it is either a bug or an undocumented decision.

flowchart LR
  spec["Spec + issue<br/>(docs/specs)"] --> branch["Branch from develop"]
  branch --> pr["Pull request → develop"]
  pr --> ci["Woodpecker: check · build ·<br/>tests of what changed"]
  ci --> review["Review + merge"]
  review --> staging["Push to develop<br/>deploys staging"]
  staging --> main["Release: develop → main"]
Loading

Repository layout

Path Package Stack
apps/api @nautelle/api NestJS 11, Prisma 7, PostgreSQL 16, BullMQ on Redis 7 — port 8180
apps/web @nautelle/web Next.js 16 (App Router), React 19, Tailwind CSS 4 — port 3517
apps/runner @nautelle/runner, published as nautelle-runner Bun, compiled to a single binary
packages/shared @nautelle/shared framework-free TypeScript shared by the API, the web app and the runner
plugins/nautelle — the Claude Code plugin: hooks, MCP server, commands
docker — PostgreSQL and Redis for local development
deploy — the staging stack, the CI image, release notes
docs — product, architecture, ADRs, specs

Development setup

Requirements: Bun 1.4.0+, Node.js 24+, Docker.

git clone https://github.com/AndreyBegma/Nautelle && cd Nautelle
bun install

cp docker/.env.example docker/.env
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env

bun run db:setup       # PostgreSQL :5421, Redis :6421, migrations, seed
bun run admin:create   # the first admin
bun run start:dev      # API :8180, web :3517

The examples work as they are for local development. See the Getting Started for pairing a local runner.

Commands

Command What it does
bun run start:dev API and web in watch mode
bun run check Biome lint, format and import order, plus the CI and image checks, without writing
bun run format Biome format, writing
bun run test the test suites
bun run typecheck TypeScript across the workspaces
bun run build build everything (Turborepo, cached)
bun run db:setup start PostgreSQL and Redis, apply migrations, seed
bun run db:migrate prisma migrate dev: create and apply a migration
bun run db:generate regenerate the Prisma client
bun run db:studio Prisma Studio

The e2e tests use their own database, TEST_DATABASE_URL, which they wipe on every run — see the e2e test database guide.

Conventions

  • Bun is the package manager, with versions pinned exactly. Never npm install or yarn.
  • Biome is the only linter and formatter: single quotes, trailing commas, 2 spaces. No ESLint or Prettier.
  • TypeScript is strict everywhere, with no any.
  • Prisma is used only by apps/api, through PrismaService. The web app talks to the API over HTTP, never to the database.
  • Schema changes go through prisma migrate dev with a descriptive name. Never edit an applied migration.
  • Every API input is a DTO validated with class-validator; the global ValidationPipe rejects unknown fields.
  • Shared types and pure helpers go in packages/shared, which stays framework-free.
  • Environment variables live in git-ignored apps/*/.env and are documented in .env.example — add a variable to the example in the same change that reads it.
  • Tests sit next to the code as *.spec.ts. A bug fix comes with the test that would have caught it.
  • Everything in the repository is written in English.

Architecture rules

  • The control plane never reads a project's filesystem — that is the runner's job (ADR-0001).
  • The runner accepts typed commands only — no shell strings (ADR-0010).
  • The UI uses only glass-ui components. A missing component is added to glass-ui, not written here (ADR-0011, usage guide).

Pull requests

  1. Branch from develop.
  2. Make the change, with tests and documentation.
  3. Run bun run check, bun run test and bun run build.
  4. Open a pull request into develop. main receives releases from develop.

A push to develop deploys staging.

Specs and decisions

  • A feature starts as a spec in docs/specs/ (<issue>-<slug>.md) and a GitHub issue with acceptance criteria. Specs are written with /code-sentinel:spec.
  • An architectural change records a new ADR in docs/adr/ in the same pull request. ADRs are numbered and never rewritten: a changed decision gets a new ADR that supersedes the old one. Read the relevant ADRs before changing architecture.

CI

CI runs on Woodpecker (.woodpecker/pipeline.yml). check and build run in full every time; which tests run depends on the event:

Event Tests
pull request the packages changed since the merge base, plus their dependents
pull request touching a root file (package.json, bun.lock, turbo.json, tsconfig.json, biome.json, .woodpecker/**, deploy/ci-image/**) the full suite
pull request touching only docs/**, *.md, .github/** none, and build is skipped; check still reports
push to develop none — the pull request already tested it
push to main, manual run the full suite

Pull-request pipelines are untrusted: their steps get no Docker socket, no host volume, no secret and no privileged container. bun run check fails a change that breaks those rules.

Dependencies

New @andrewbehma/glass-ui releases arrive as pull requests into develop from Renovate (renovate.json). Renovate watches only that package, pinned exactly, and a person merges its pull requests. Every other dependency is updated by hand.

See also

Decisions: ADR-0001 · ADR-0010 · ADR-0011 · ADR-0016 · ADR-0018 · ADR-0053

Clone this wiki locally