Thanks for your interest in contributing! This document covers how to set up a dev environment, the change-management workflow, and what we expect in a pull request.
- One issue per PR. If your change spans multiple concerns, split it.
- Search existing issues and discussions before opening a new one.
- Substantial features (new packages, new ports, API-breaking changes) should be discussed in an issue first — we want to agree on the shape before you invest time writing code.
packages/core @launchstack/core — framework-agnostic engine (published to npm)
packages/features vertical features that sit on top of core (private, not published)
apps/web Next.js reference app that wires the engine
services/ Python/ML sidecars (sidecar, ocr-router, ocr-worker)
The core/features/host boundary is enforced by ESLint (see eslint.config.js):
@launchstack/coremust not import Next.js, Clerk, React, orprocess.env. It's Node-only and framework-agnostic.@launchstack/featuresmust not import from the host app (~/*) or pull in Next/Clerk/React. Features can readprocess.env.- Violations fail lint.
- Node.js 20+
- pnpm 10+ (matches the
packageManagerfield inpackage.json; usecorepack enableif you don't have it) - Docker & Docker Compose (for the full local stack with Postgres + sidecars)
git clone https://github.com/launchstack/launchstack.git
cd launchstack
pnpm install
cp .env.example .env # fill in DATABASE_URL + CLERK + OPENAI keys
pnpm db:push # sync Drizzle schema
pnpm dev # Next.js + Inngest dev server (concurrently)make up # lite stack (~400MB RAM, native OCR only)
make up-ocr # full stack with Docling for Office docs
make up-fast # build Next on host first, then compose (fastest for testing prod image)
make down # tear down
make down-clean # tear down + wipe volumesOnce the stack is up: app at localhost:3000, Inngest dashboard at localhost:8288, sidecar API at localhost:8000/docs.
Run before opening a PR:
pnpm check # eslint + pnpm -r typecheck
pnpm test # Jest (apps/web)All three must pass in CI. Boundary rules (no process.env in core, no ~/* in features) are checked by ESLint — don't try to work around them with /* eslint-disable */; talk to us if the rule seems wrong.
We publish @launchstack/core to npm using Changesets. If your PR changes anything under packages/core/, you must add a changeset:
pnpm changesetFollow the prompt — pick patch / minor / major and write a short user-facing summary of what changed. The tool writes a Markdown file under .changeset/ that you commit with your PR.
On merge to main, the Changesets bot opens (or updates) a "Version Packages" PR. Merging that PR publishes the new version to npm.
Changes to packages/features/ and apps/web/ do not need a changeset — they're private.
Before requesting review:
- Commits are focused and have meaningful messages
-
pnpm checkpasses -
pnpm testpasses - Changeset added if
packages/core/changed - New env vars documented in
.env.exampleandapps/web/src/env.ts - If the change touches UI, you've exercised the flow in a browser (not just a successful build)
- PR description explains why, not just what
- TypeScript strict mode; prefer
typeoverinterfacefor shapes - Import types with
import type - Don't add comments that restate the code. Only comment when the why is non-obvious.
- Match the surrounding file's style — no sweeping refactors in feature PRs
- Questions: GitHub Discussions
- Bug reports: New issue
- Security: see SECURITY.md — do not open public issues for vulnerabilities
By contributing, you agree that your contributions will be licensed under the Apache License 2.0.