Monorepo Developer Guide
Monorepo Developer Guide
This repository uses three co-existing package managers — Deno, pnpm, and uv — each owning a distinct slice of the monorepo. Understanding which manager governs which workspace prevents dependency confusion and incorrect task invocations.
Table of Contents
- Workspace Layout
- Deno Workspace
- pnpm Workspace
- uv Workspace (Python)
- Task Routing
- Adding a New Package
- Preflight Checks
Workspace Layout
bloqr-backend/├── deno.json ← Root Deno workspace config + all task definitions├── pnpm-workspace.yaml ← pnpm workspace config├── package.json ← minimal; bridges npm scripts for pnpm workspace│├── worker/ ← Deno sub-workspace (Cloudflare Worker / Hono)│ └── deno.json├── examples/│ └── cloudflare-worker/ ← Deno sub-workspace + pnpm package│ ├── deno.json│ └── package.json│├── frontend/ ← pnpm package (Angular 21)│ └── package.json│├── docs/ ← pnpm package (Astro / Starlight)│ └── package.json│└── tools/ ← uv workspace (Python 3.11+) ├── pyproject.toml └── .marimo.tomlManager Ownership
| Path | Manager | Package name |
|---|---|---|
worker/ | Deno | @jk-com/bloqr-compiler-worker (Deno sub-workspace) |
examples/cloudflare-worker/ | Deno + pnpm | bloqr-compiler-worker-example |
frontend/ | pnpm | bloqr-frontend |
docs/ | pnpm | @bloqr/docs |
tools/ | uv | bloqr-backend-tools |
Note:
tools/is intentionally excluded from the pnpm workspace. It has its ownuv.lockand is managed entirely by uv. Do not add it topnpm-workspace.yaml.
Deno Workspace
Declared in deno.json at the root:
{ "workspace": ["./worker", "./examples/cloudflare-worker"]}Sub-workspaces share the root deno.json import map (the "imports" section) so both worker/ and examples/cloudflare-worker/ resolve the same pinned versions of hono, zod, better-auth, etc.
Running Deno tasks from the root
All tasks in deno.json are invoked from the repository root:
# Compile the CLIdeno task compile
# Run all tests (src/ + worker/)deno task test
# Run only worker testsdeno task test:worker
# Type-checkdeno task check
# Lintdeno task lint
# Formatdeno task fmt
# Full preflight (format, lint, type-check, OpenAPI validate, schema drift check)deno task preflightWrangler (Cloudflare Worker deployment)
Wrangler is invoked through Deno to use the pinned version from the import map (npm:wrangler@^4.86.0):
# Local dev serverdeno task wrangler:dev
# Deploy to productiondeno task wrangler:deploy
# Deploy to dev environmentdeno task wrangler:deploy:dev
# Dry-run / verify bundledeno task wrangler:verify
# Stream real-time logsdeno task wrangler:tailSchema & OpenAPI Tasks
# Regenerate Cloudflare API Shield schema + Postman collectiondeno task schema:generate
# Validate OpenAPI specdeno task openapi:validate
# Upload Cloudflare API Shield schemadeno task schema:upload
# Check generated files are not out of date (run in CI)deno task check:driftpnpm Workspace
Declared in pnpm-workspace.yaml:
packages: - 'frontend' - 'examples/cloudflare-worker' - 'docs' # tools/ is NOT listed here — it is managed by uvRunning pnpm workspace commands from root
Individual packages are addressed with --filter <package-name>:
# Install all pnpm workspace dependenciespnpm install
# Build Angular frontendpnpm --filter bloqr-frontend run build
# Start Angular dev serverpnpm --filter bloqr-frontend run start
# Run Angular testspnpm --filter bloqr-frontend run test
# Production buildpnpm --filter bloqr-frontend run buildConvenience aliases via Deno tasks
The root deno.json provides ui:* aliases that delegate to pnpm under the hood:
deno task ui:build:ng # pnpm --filter bloqr-frontend run builddeno task ui:build:ng:dev # pnpm --filter bloqr-frontend run build:devdeno task ui:dev:ng # pnpm --filter bloqr-frontend run startdeno task ui:test:ng # pnpm --filter bloqr-frontend run testdeno task ui:deploy:ng:dev # build:dev + deploy:devThis means you can run all development tasks from the repository root using only deno task, regardless of which sub-system you are working on.
uv Workspace (Python)
The tools/ directory is a standalone Python project managed by uv. It is not part of the pnpm workspace.
# First-time setup — install all Python deps into .venvdeno task runbook:setup# equivalent to: uv sync --directory toolsAll runbook:* tasks delegate to uv run --directory tools ..., so uv does not need to be on PATH globally — Deno locates the uv binary automatically.
Why uv?
- Lock file (
uv.lock) guarantees reproducible installs across machines and CI. uv runcreates/activates the virtual environment inline without a separateactivatestep.- Supports Python 3.11+ target version matching
tools/pyproject.toml.
For the full Python toolchain guide, see docs/tools/MARIMO_UV_TY.md.
Task Routing
The table below shows which command to run for common developer scenarios, all from the repository root:
| Goal | Command |
|---|---|
| Start Worker dev server | deno task wrangler:dev |
| Start Angular dev server | deno task ui:dev:ng |
| Run all tests | deno task test |
| Run Angular tests | deno task ui:test:ng |
| Run Worker tests | deno task test:worker |
| Lint (Deno/TypeScript) | deno task lint |
| Format (Deno/TypeScript) | deno task fmt |
| Lint (Python) | deno task runbook:lint |
| Format (Python) | deno task runbook:fmt |
| Type-check (Python) | deno task runbook:typecheck |
| Run a marimo runbook | deno task runbook:pipeline |
| Edit a marimo runbook | deno task runbook:edit:pipeline |
| Deploy Worker to production | deno task wrangler:deploy |
| Build Angular production | deno task ui:build:ng |
| Generate schemas | deno task schema:generate |
| Full preflight | deno task preflight |
Adding a New Package
Deno sub-workspace
- Create the directory and add a
deno.jsonwith at minimum{ "name": "@jk-com/<name>" }. - Add the directory path to the
"workspace"array in the rootdeno.json. - The new package automatically inherits the root import map.
pnpm package
- Create the directory with a
package.json("name"must be unique in the workspace). - Add the directory path to
pnpm-workspace.yaml. - Run
pnpm installfrom the root to link the new package.
Python module (inside tools/)
Add the dependency to tools/pyproject.toml under [project] dependencies (runtime) or [dependency-groups] dev (dev-only), then run deno task runbook:setup to update the lock file.
Preflight Checks
Before opening a PR, run the full preflight suite:
deno task preflightThis runs in sequence:
deno fmt --check— format checkdeno lint— lintdeno task check— type-checksrc/andworker/deno task openapi:validate— validate OpenAPI specdeno task schema:generate— regenerate Cloudflare schema + Postman collectiondeno task check:drift— ensure generated files are committeddeno task check:lockfile—pnpm install --frozen-lockfile --ignore-scripts
For a complete run that also includes tests and slow-type checks:
deno task preflight:full