Contributing
How we develop Alchemify — conventions for anyone contributing code (human or AI).
Versioning
Section titled “Versioning”Milestones use plain numbers: 0.1, 0.2, 0.3. No “v” prefix, no patch number. Semver formality comes later when there’s something to ship.
GitHub milestones track which issues belong to which release. Current state:
- 0.1 — Core backend (auth, SQL proxy, schema introspection) + frontend app shell
- 0.2 — Docker, architecture hardening, runtime security
- 0.3 — Reserved for future work
Testing
Section titled “Testing”- Framework: Vitest + Supertest
- Database: Tests run against the real
alchemifydatabase, not mocks - Isolation: Tables are truncated between test runs (
beforeEach) - Pattern: Test helpers in
test/setup.tshandle seeding (orgs, users, magic links) - Run:
pnpm testfrom repo root
Write tests for new endpoints and SQL functions. Follow the existing pattern in test/auth.test.ts.
E2E tests
Section titled “E2E tests”End-to-end tests use Playwright and live in the root e2e/ directory. They exercise the full stack (frontend + server + database).
pnpm test:e2e # run all E2E tests (headless)pnpm test:e2e:ui # open Playwright's visual test runnerThe webServer config in e2e/playwright.config.ts starts both the backend and frontend dev servers automatically. If servers are already running, they’ll be reused.
Tests use unique emails (*@test.local) to avoid collisions with manual data. A global teardown deletes all @test.local users after each run.
Page diagnostics
Section titled “Page diagnostics”The diagnose tool launches a headless browser, logs in as a test user, navigates to a page, and reports console errors — useful for debugging AI-generated custom pages without opening DevTools manually.
pnpm diagnose /our-employees # admin role (default)pnpm diagnose /dashboard --role staff # specific rolepnpm diagnose / --role member # root page as memberRequires the backend (pnpm dev) and frontend (pnpm dev:web) servers running, plus the test seed applied (psql alchemify dba -f apps/server/test-seed.sql). Screenshots are saved to tools/diagnose/screenshots/ (gitignored). Exit code 0 = no errors, 1 = errors found.
Console messages are categorized (compilation, render, execution) and sandbox infrastructure noise (CSP, Vite HMR, WebSocket) is filtered automatically.
AI exploratory testing
Section titled “AI exploratory testing”The explorer uses Claude Code + Playwright MCP for open-ended exploratory testing of the builder pipeline. Unlike scripted tests, it evaluates non-deterministic AI output, explores freely, and finds issues that deterministic tests can’t.
e2e/explorer/run.sh prompt.md # interactive (env=local)e2e/explorer/run.sh poc.md --env staging -p # staging, print modee2e/explorer/cron.sh # batch run all testse2e/explorer/cron.sh --env staging # batch run against stagingThe --env flag selects the target environment (local or staging). Config is in e2e/explorer/config.ts. Staging requires EXPLORER_EMAIL and EXPLORER_TOKEN env vars.
Requires all 3 dev servers running (for local) plus the test seed applied. The prompt instructs the AI tester to log in, create tables and data, request custom pages, verify rendering, and check console errors. Batch results go to e2e/explorer/results/ (gitignored).
See e2e/explorer/README.md for full setup and cleanup instructions.
Chat API tests
Section titled “Chat API tests”Chat tests use Claude Code + pnpm chat CLI to test the AI builder directly — no browser involved. Claude reads plain-English scenario files, uses the CLI to send messages, then verifies results via SQL queries.
apps/chat/test/run.sh scenarios/poc.md # interactiveapps/chat/test/run.sh scenarios/poc.md -p # print mode (JSON)apps/chat/test/run.sh scenarios/tier1-simple.md --timeout 30m -p # with timeoutapps/chat/test/run.sh scenarios/tier2-choice-fields.md --max-turns 50 -pRequires the backend (pnpm dev) and chat (pnpm dev:chat) servers running. Config is in apps/chat/cli/config.ts. Scenarios are in apps/chat/test/scenarios/. Reports are saved to apps/chat/test/output/ (gitignored). See apps/chat/cli/README.md for CLI documentation.
Documentation
Section titled “Documentation”The docs site lives at apps/docs/ (Starlight/Astro). Two sections:
- User Guide — Non-technical. How to use the app. Written for people who don’t code.
- Developer Guide — Technical. Architecture, setup, API, extension points.
Convention: When making user-visible changes, update the relevant docs. User-facing features go in the User Guide. Technical changes go in the Developer Guide.
pnpm dev:docs --host # dev server (port 4321)pnpm build:docs # static buildSchema management
Section titled “Schema management”The base schema lives in apps/server/schema.sql (includes numbered files from schema/). Migrations live in apps/server/migrations/ using dbmate format.
Fresh installs use the base schema (schema.sql) — it’s idempotent and produces a complete database.
Existing databases are upgraded via migrations. This repo defines the migration files; the admin repo runs them against HQ and tenant databases.
Dual maintenance: every migration must also update the corresponding base schema file, so reset-dev.sh and migrations produce the same result.
# Dev: full reset from base schema (no migrations needed)./scripts/reset-dev.sh
# Base schema conventions# - IF NOT EXISTS for roles and tables# - CREATE OR REPLACE for functions# - Re-apply: psql -U dba -d alchemify -f apps/server/schema.sqlSee apps/server/migrations/CONVENTIONS.md for migration format, naming, and rules around breaking changes.
Workflow
Section titled “Workflow”- Discuss the change
- Create a GitHub issue (requirements, not implementation details)
- Implement on the
backendbranch - Write or update tests
- Run
pnpm lintandpnpm formatbefore committing - Update docs if user-visible
- Commit with a clear message
Issues created from the backend branch should include the backend label.
Linting & formatting
Section titled “Linting & formatting”The project uses ESLint (with type-checked rules) and Prettier for consistent code quality. Both are configured at the repo root and apply to all workspaces.
pnpm lint # ESLint — check for errorspnpm format # Prettier — auto-format all filespnpm format:check # Prettier — check without writingKey rules enforced:
- No floating promises —
awaitorvoidevery promise - No unused variables — prefix with
_if intentionally unused - Consistent type imports —
import { type Foo }style - Double quotes, semicolons, trailing commas — handled by Prettier (100-char line width)
The ops/check.sh script runs lint, format checks, typecheck, unit tests, and E2E tests.
Code style
Section titled “Code style”- Simple over clever — direct solutions, no over-engineering
- No extras — don’t add error handling, comments, types, or refactoring beyond what’s needed
- Delete, don’t deprecate — remove unused code completely, no backwards-compat shims
- Security first — watch for injection, XSS, and OWASP top 10; flag immediately