Two apps, two test suites, and the packages that make up the system — a
lockstep set under the @apograph scope, one version number across the whole
set (sixty published at 0.5.2, and the number goes up with each plugin
group added).
Three do not follow that rule. create-apograph-app is unscoped, so that both
npx create-apograph-app and npm create apograph-app work; it is released in
lockstep with everything else. nx and copilot-provider-fake are private
and never published at all — the first is repository tooling, the second is the
end-to-end suite’s model fixture.
Apps
| Project | What it is |
|---|---|
admin | React 19 + Vite SPA. Composes admin plugins via createAdmin. |
server | NestJS API. Composes server plugins via createServer. Owns your content types. |
admin-e2e | Playwright page-object suite for the admin, with /api mocked. |
server-e2e | In-process testcontainer and supertest suite for the API. |
Hosts and infrastructure
| Package | Role |
|---|---|
bootstrap-admin | Host. createAdmin({ plugins }) — React root, router, providers. |
bootstrap-server | Host. createServer({ plugins }) — Nest app, /api prefix, validation, API reference. |
database | Plugin. One Drizzle connection, the unit of work, and the transactional outbox. |
utils-server, utils-admin | Shared plumbing. The admin’s apiClient, query client, slots and error handling. |
design-system | shadcn/ui component library and Tailwind tokens. |
nx | Nx plugin. Infers the db:generate, db:migrate and db:studio targets. |
cli | The apograph binary — build, run and migrate an installed app. |
create-apograph-app | The scaffolder. Unscoped, so npx create-apograph-app works. |
cli and nx are two adapters over one implementation. Everything needed to
operate an app used to live in nx, which is private and will never be
published — so an app installed from npm had no way to migrate its database at
all. See the CLI reference.
Content
| Package | Role |
|---|---|
content-domain | The framework-free kernel: validation, the publish gate, rich-text rules. |
content-server | Plugin. The registry, the DSL, entries, revisions, the public API. |
content-admin | Plugin. The content library, the records table, the entry editor. |
content-graphql | Plugin. GraphQL as a protocol adapter over the public API. |
alarms-server | Plugin. Content rules and findings. Two tables; never blocks a write. |
alarms-admin | Plugin. The rules page, the entry rail’s checks block, “Save as rule”. |
segments-domain | The framework-free entitlement kernel: the canRead rules. |
segments-server | Plugin. Audiences, per-entry access, and the public read predicate. |
segments-admin | Plugin. The audience directory and the entry’s access controls. |
protection-domain | The framework-free kernel: evaluateProtection, which counts approvals against a rule. |
protection-server | Plugin. Three tables, the publish guard, /api/protection. Published with the next release. |
protection-admin | Plugin. The entry’s Review section and publish verdict, the settings tab, the Reviews page. |
Webhooks
| Package | Role |
|---|---|
webhooks-domain | The framework-free kernel: the event catalogue, the envelope, the signature, the retry ladder, the URL policy. |
webhooks-server | Plugin. Three tables, the outbox fan-out subscriber, the delivery worker, /api/webhooks. |
webhooks-admin | Plugin. The global /webhooks pages in the directory group: endpoints, the delivery log, redeliver, rotate, test. |
The domain package is what a receiver can import to verify a signature with the same code that produced it. See webhooks.
Identity, users and workspaces
| Package | Role |
|---|---|
identity-domain | The framework-free SSO seam: the provider port, the profile, the conformance kit. |
identity-server | Plugin. Auth, sessions, RBAC, API tokens, preferences, SSO. |
identity-admin | Plugin. Login and accept-invite pages, auth state. |
identity-provider-oidc | Generic OpenID Connect, plus presets for five named vendors. |
identity-provider-github | GitHub and GitHub Enterprise. OAuth2, so not a preset. |
identity-provider-saml | SAML 2.0 — a POST binding and XML signatures. |
identity-provider-fake | Scripted and offline. Published and installed everywhere, registered nowhere. |
users-server | Plugin. Member management — list, invite, edit, disable, sessions. |
users-admin | Plugin. The members roster, invite flow, user detail, preferences. |
workspaces-server | Plugin. Workspaces, memberships, content grants. |
workspaces-admin | Plugin. The workspace table, create wizard, and workspace shell. |
api-tokens-admin | Plugin. The API Tokens page. |
activity-server | Plugin. The audit schema and read API. |
activity-admin | Plugin. Activity logs and the home recent-activity panel. |
Media, localization and editing
| Package | Role |
|---|---|
media-server | Plugin. Assets, folders, derivatives, the public media API. |
media-admin | Plugin. The media library, the entry editor’s Media tab. |
media-provider-local | Local filesystem storage adapter. The default install. |
media-provider-s3 | S3-compatible: AWS, R2, MinIO, Spaces, B2, Wasabi. |
media-provider-azure | Azure Blob Storage — the one store with no S3 compatibility. |
media-provider-gcs | Google Cloud Storage, with native Google auth. |
media-provider-vercel-blob | Vercel Blob. Every blob is world-readable. |
media-provider-memory | In-memory. For tests and offline development, never a deployment. |
media-provider-testkit | The contract suite a storage provider is written against. |
transfer-domain | The transfer kernel: the document contract, the four formats, identity. |
transfer-server | Plugin. One-hop export, two-phase import. Owns no tables. |
transfer-admin | Plugin. Export and import in the Content Library’s menus. |
i18n-server | Plugin. Locale policy, bound to content’s entry-extension port. |
i18n-admin | Plugin. Locale switcher, locale panel, coverage card. No routes. |
wysiwyg-admin | Plugin. The rich-text control. One slot contribution, no routes. |
query-builder-admin | The filter and query-builder UI. |
shell-admin | Plugin. The authenticated chrome — sidebar, layout, home. |
insights-admin | Plugin. The Insights dashboard frame. Ships no widgets. |
AI and agents
| Package | Role |
|---|---|
copilot-domain | The framework-free core: the model port, tool contracts, the untrusted-content fence. |
copilot-server | Plugin. The run engine, the SSE route, the write path, skills. |
copilot-admin | Plugin. The docked chat window and the full-page Agents view. |
copilot-provider-anthropic | Native Claude adapter. The only one that may import a vendor SDK. |
copilot-provider-openai | Any OpenAI-wire endpoint — Ollama, vLLM, Azure, OpenAI. |
copilot-provider-fake | Scripted and deterministic. Private and unpublished — the e2e fixture. |
tools-server | The shared, transport-neutral agent tool registry. |
mcp-server | Plugin. The Model Context Protocol endpoint. Owns no tools. |
How they resolve
Workspace packages are consumed from source: their exports point at
./src/index.ts, and a custom TypeScript condition makes that resolve. No build
step is needed to consume one.
That is also why publishing has a pack step that rewrites each manifest — a
consumer outside the workspace cannot resolve from source.
Run npx nx sync after changing cross-project dependencies, and npx nx graph
to see the graph.