The packages
The framework is split into six npm packages, all published under the @drawnagency scope. Client repos depend on whichever packages they need — typically all six. A seventh workspace package, @drawnagency/platform, is private (never published): it holds the platform-side provisioning core consumed only by apps/admin and apps/mcp, and is documented at the end of this page.
Dependency graph
Section titled “Dependency graph”primitives (leaf — no internal deps)├── assets-r2 (depends on primitives)├── authoring (depends on primitives + assets-r2)├── github (depends on primitives)├── auth-supabase (depends on primitives)└── core (depends on primitives + github)
platform (private, unpublished — type-only dep on primitives)Publish order follows this graph: primitives → assets-r2 → authoring → github → auth-supabase → core. assets-r2 precedes authoring because authoring’s upload-video imports the R2 signer from it — the order in scripts/publish.sh is the source of truth. Use bash scripts/publish.sh from the monorepo root — never publish packages manually.
Package reference
Section titled “Package reference”@drawnagency/primitives
Section titled “@drawnagency/primitives”The shared foundation. Contains:
- Zod schemas for all section types,
index.json,site-config.json, and image manifest. - Section component registry —
defineSection(),registerSection(),getSectionSchema(), and theSymbol.for-keyed singleton registry. - React section components — the rendered UI for every built-in section type.
mergeSiteContent()andloadStaticSiteContent()— the core content assembly functions.- Auth capability helpers —
deriveUiCapabilities()and related types.
No internal @drawnagency/* dependencies. Safe to import on its own.
@drawnagency/assets-r2
Section titled “@drawnagency/assets-r2”The Cloudflare R2 storage adapter — the bucket half of the storage model. Contains:
r2Assets()— returns anAssetStorebacked by an R2 bucket, used for videos and other bucket-hosted assets.r2Documents()— returns aDocumentStorefor bucket-tier documents (large PDFs), sharing the same credentials.- A dependency-free SigV4 signer for presigned PUT/DELETE URLs.
The template’s default portal.config.mjs imports both. The bucket is optional: a portal can run with no bucket configured at all and still do GitHub-backed media — see Storage model. Depends on @drawnagency/primitives for the AssetStore/DocumentStore interfaces.
@drawnagency/authoring
Section titled “@drawnagency/authoring”The content-population toolchain. Contains:
- The
authoringCLI (validate,process-images,upload-videosubcommands). - The
/populate-siteClaude skill, linked into client repos viapostinstall→link-skills.mjs. - Image processing pipeline (download → WebP conversion → manifest update).
Depends on @drawnagency/primitives for schema validation during validate, and on @drawnagency/assets-r2 for the upload-video subcommand’s presigned uploads.
@drawnagency/github
Section titled “@drawnagency/github”The GitHub storage client. Contains:
createGitHubClientAsync()— instantiates an Octokit client authenticated as the GitHub App installation.- Helpers for reading/writing files, listing branches, and getting commit SHAs from a client repo.
owner,repo,branchconstants resolved from environment variables.
Depends on @drawnagency/primitives.
@drawnagency/auth-supabase
Section titled “@drawnagency/auth-supabase”The Supabase authentication adapter. Contains:
supabaseAuth()— returns anAuthProviderimplementation backed by Supabase Auth.- Session resolution, audience CRUD, user management, and password-auth toggle — all routed through Supabase.
- OAuth PKCE flow helpers.
Depends on @drawnagency/primitives for the AuthProvider interface and shared types.
@drawnagency/core
Section titled “@drawnagency/core”The Astro integration and everything that ties the framework together. Contains:
defineConfig()(from@drawnagency/core/config) /portalIntegration()— the Astro integration that registers routes, sets upnoExternal, creates.portal/symlinks for dev mode, and wiresvirtual:portal/*modules.- Astro pages: viewer index,
/edit, auth API routes, media API route. packages/core/src/middleware.ts— the dual-path auth gate.loadContentFromGitHub()andloadMediaManifestFromGitHub()— GitHub-backed loaders built on@drawnagency/primitives’mergeSiteContent().- Password-only auth adapter (
lib/password.ts) as an alternative to Supabase.
Depends on @drawnagency/primitives and @drawnagency/github.
@drawnagency/platform (private)
Section titled “@drawnagency/platform (private)”The platform-side core — not published to npm and never installed by client repos. Contains:
provisionSite()/teardownSite()— the site lifecycle orchestration (GitHub repo from template, Netlify site, Cloudflare DNS, Supabase records, env vars, webhooks).- Provider clients for the GitHub App (installation tokens), Netlify, and Cloudflare APIs, plus the service-role Supabase admin client.
checkPlatformAccess()— the shared platform identity gate (platform_users/allowed_signups) used by both the admin middleware and the MCP connector’s OAuth callback.
It exports source (./src/*.ts, no dist/) so apps/admin can bundle it without a package build step, and imports @drawnagency/primitives as import type only. Consumed by apps/admin and apps/mcp.
Version constraints
Section titled “Version constraints”All packages use 0.1.x versions. Client repos reference them with ^0.1.0 ranges, which under semver 0.x rules means >=0.1.0 <0.2.0. Bumping to 0.2.0 in any package requires client repos to explicitly widen their range.
Workspace dependencies in the monorepo use workspace:* (or workspace:^). pnpm publish resolves these to real version numbers at publish time — npm publish does not and will break consumer installs silently.