Skip to content

Monorepo Developer Guide

Monorepo Developer Guide

Back to README

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

  1. Workspace Layout
  2. Deno Workspace
  3. pnpm Workspace
  4. uv Workspace (Python)
  5. Task Routing
  6. Adding a New Package
  7. 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.toml

Manager Ownership

PathManagerPackage name
worker/Deno@jk-com/bloqr-compiler-worker (Deno sub-workspace)
examples/cloudflare-worker/Deno + pnpmbloqr-compiler-worker-example
frontend/pnpmbloqr-frontend
docs/pnpm@bloqr/docs
tools/uvbloqr-backend-tools

Note: tools/ is intentionally excluded from the pnpm workspace. It has its own uv.lock and is managed entirely by uv. Do not add it to pnpm-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:

Terminal window
# Compile the CLI
deno task compile
# Run all tests (src/ + worker/)
deno task test
# Run only worker tests
deno task test:worker
# Type-check
deno task check
# Lint
deno task lint
# Format
deno task fmt
# Full preflight (format, lint, type-check, OpenAPI validate, schema drift check)
deno task preflight

Wrangler (Cloudflare Worker deployment)

Wrangler is invoked through Deno to use the pinned version from the import map (npm:wrangler@^4.86.0):

Terminal window
# Local dev server
deno task wrangler:dev
# Deploy to production
deno task wrangler:deploy
# Deploy to dev environment
deno task wrangler:deploy:dev
# Dry-run / verify bundle
deno task wrangler:verify
# Stream real-time logs
deno task wrangler:tail

Schema & OpenAPI Tasks

Terminal window
# Regenerate Cloudflare API Shield schema + Postman collection
deno task schema:generate
# Validate OpenAPI spec
deno task openapi:validate
# Upload Cloudflare API Shield schema
deno task schema:upload
# Check generated files are not out of date (run in CI)
deno task check:drift

pnpm Workspace

Declared in pnpm-workspace.yaml:

packages:
- 'frontend'
- 'examples/cloudflare-worker'
- 'docs'
# tools/ is NOT listed here — it is managed by uv

Running pnpm workspace commands from root

Individual packages are addressed with --filter <package-name>:

Terminal window
# Install all pnpm workspace dependencies
pnpm install
# Build Angular frontend
pnpm --filter bloqr-frontend run build
# Start Angular dev server
pnpm --filter bloqr-frontend run start
# Run Angular tests
pnpm --filter bloqr-frontend run test
# Production build
pnpm --filter bloqr-frontend run build

Convenience aliases via Deno tasks

The root deno.json provides ui:* aliases that delegate to pnpm under the hood:

Terminal window
deno task ui:build:ng # pnpm --filter bloqr-frontend run build
deno task ui:build:ng:dev # pnpm --filter bloqr-frontend run build:dev
deno task ui:dev:ng # pnpm --filter bloqr-frontend run start
deno task ui:test:ng # pnpm --filter bloqr-frontend run test
deno task ui:deploy:ng:dev # build:dev + deploy:dev

This 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.

Terminal window
# First-time setup — install all Python deps into .venv
deno task runbook:setup
# equivalent to: uv sync --directory tools

All 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 run creates/activates the virtual environment inline without a separate activate step.
  • 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:

GoalCommand
Start Worker dev serverdeno task wrangler:dev
Start Angular dev serverdeno task ui:dev:ng
Run all testsdeno task test
Run Angular testsdeno task ui:test:ng
Run Worker testsdeno 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 runbookdeno task runbook:pipeline
Edit a marimo runbookdeno task runbook:edit:pipeline
Deploy Worker to productiondeno task wrangler:deploy
Build Angular productiondeno task ui:build:ng
Generate schemasdeno task schema:generate
Full preflightdeno task preflight

Adding a New Package

Deno sub-workspace

  1. Create the directory and add a deno.json with at minimum { "name": "@jk-com/<name>" }.
  2. Add the directory path to the "workspace" array in the root deno.json.
  3. The new package automatically inherits the root import map.

pnpm package

  1. Create the directory with a package.json ("name" must be unique in the workspace).
  2. Add the directory path to pnpm-workspace.yaml.
  3. Run pnpm install from 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:

Terminal window
deno task preflight

This runs in sequence:

  1. deno fmt --check — format check
  2. deno lint — lint
  3. deno task check — type-check src/ and worker/
  4. deno task openapi:validate — validate OpenAPI spec
  5. deno task schema:generate — regenerate Cloudflare schema + Postman collection
  6. deno task check:drift — ensure generated files are committed
  7. deno task check:lockfilepnpm install --frozen-lockfile --ignore-scripts

For a complete run that also includes tests and slow-type checks:

Terminal window
deno task preflight:full