The devknobs npm package and its site, https://knobs.dev, in one monorepo:
| Path | What |
|---|---|
packages/devknobs/ |
The devknobs npm package (README) |
apps/web/ |
The site, knobs.dev |
packages/ui/ |
The site's StyleX components |
The site is a copy of mertbuilds/web-starter with everything a landing page does not need taken out: no api, no database, no auth, no billing, no e2e. What is left is a TanStack Start app on Cloudflare Workers, the StyleX component package behind it, and the tooling that keeps both honest. The founding stack decisions are in docs/adr/0001-stack.md: that record covers the whole boilerplate, and this repo keeps only the web half. Agent rules and workflow live in AGENTS.md.
| Layer | Choice |
|---|---|
| Monorepo | pnpm workspaces + Turborepo, Node 24, TypeScript 7 |
| Web | TanStack Start (React 19 + Compiler) → Cloudflare Workers |
| Styling | StyleX tokens (the devknobs panel's) + Base UI components + Storybook |
| i18n | Paraglide v2 (en only) |
| Analytics | Self-hosted OpenPanel, page views only, /api/op reverse proxy |
| Logging | evlog wide events to an Axiom drain |
| Lint/format | oxlint (@nkzw/oxlint-config, type-aware) + oxfmt, no ESLint/Prettier |
| Tests | Vitest, Storybook stories as tests in real Chromium |
Prereqs: Node 24 (nvm use), pnpm 11 (corepack), bun 1.3 (devknobs builds and tests with it).
pnpm install
cp apps/web/.env.example apps/web/.env
sudo pnpm exec portless proxy start --https # one-time: local HTTPS proxy on 443 + trusted CA
pnpm dev # mprocs: web + storybookLocal URLs come from portless: stable named HTTPS domains instead of ports:
| Service | URL |
|---|---|
| web | https://knobs.localhost |
| storybook | https://storybook.knobs.localhost |
pnpm exec portless service install starts the proxy on boot.
| Command | What it does |
|---|---|
pnpm dev |
Web + storybook, in mprocs panes |
pnpm test |
Story tests in real Chromium + devknobs' bun test |
pnpm lint |
oxlint, type-aware |
pnpm format:check |
oxfmt, the CI check |
pnpm typecheck |
tsc --noEmit per package |
pnpm build |
turbo build (devknobs' dist, then the Workers bundle) |
pnpm storybook |
Component workshop (standalone, :6006) |
pnpm bad-day |
Nuke node_modules + all caches, reinstall (DRY_RUN=1 to preview) |
pnpm skills:check |
Warn when dep majors drift from verified agent skills |
Fonts. None ship. The site uses the devknobs panel's system font stack.
Env. Every var is optional: the site runs with no .env at all, just without analytics.
Deploy. pnpm --filter @knobs/web deploy builds and ships to Cloudflare Workers; a push to
main does the same from CI.
pnpm dev runs the site against devknobs' source, so an edit in packages/devknobs/src reloads
the page. To release a new version: bump version in packages/devknobs/package.json, add the
CHANGELOG.md entry, then:
pnpm --filter devknobs build
cd packages/devknobs
npm pack --dry-run # check the file list
npm publish- Cloudflare: Workers; secrets
CLOUDFLARE_API_TOKEN,CLOUDFLARE_ACCOUNT_IDin GitHub - Custom domains:
knobs.devandwww.knobs.devattached to theknobs-webWorker - OpenPanel: repo variable
OPENPANEL_CLIENT_ID(public project id); without it production ships without analytics - Axiom: dataset + token as Worker secrets (
AXIOM_TOKEN,AXIOM_DATASET) for the evlog drain - Branch protection: PRs only, CI required on
main - Turbo remote cache (optional):
TURBO_TOKENsecret +TURBO_TEAMvar