Add an app
A new workspace under apps/ — naming, turbo wiring, the root scripts, and the Docker stage that actually ships it.
An app is a deployable. If it is code two apps share, you want a package instead.
The workspace
apps/* is already globbed by the root package.json, so a new directory is
picked up with no config change. Name the package statshub-<dir>, the same string as the directory — the
directory name and the scoped name must agree, because every root script and
turbo filter addresses it by the scoped name.
{
"name": "statshub-reports",
"private": true,
"scripts": {
"dev": "next dev --port 3005",
"build": "next build",
"lint": "eslint .",
"typecheck": "tsc --noEmit"
}
}Pick a free port
Dev ports in use: legacy 3000, docs 3001, web/admin see their own scripts, Expo Metro 8142. Two apps on one port fail in a way that looks like a caching bug.
Then bun install from the repo root, once, to link it.
Turbo picks the tasks up by name
turbo.json declares build, lint, typecheck, test and dev. You do not
register an app — a script whose name matches a task is run by it. bun run lint
at the root now includes yours.
The one thing you DO have to declare is environment: build.env in turbo.json
is the cache key. A variable your build reads that is not in that list means
turbo serves a stale build when the value changes.
bunx turbo ls # confirm the workspace is seen
bunx turbo run typecheck --filter=statshub-reportsRoot scripts
Add the shortcuts next to their neighbours in the root package.json, following
the existing dev:* / build:* / start:* shape:
"dev:reports": "turbo run dev --filter=statshub-reports",
"build:reports": "turbo run build --filter=statshub-reports"Docker
Every deployable app has apps/<name>/Dockerfile built from the REPO ROOT as
context, and a service in docker-compose.yml. The first stage runs
turbo prune statshub-<name> --docker, which cuts the workspace down to that
app and its dependencies so a change elsewhere does not bust the layer cache.
Copy apps/statshub-docs/Dockerfile and change the filter — it is the smallest of them.
NEXT_PUBLIC_* values are baked at build time and must be passed as build args,
not runtime env.
Checklist
bun install
bunx turbo ls | grep reports
bun run typecheck
bun run lint
bun run build:reports
docker compose build reports