Framework packages (npm)
Xentium is a framework, and this CMS is the first app built on it. We publish the
framework layer to npm under the @xentium
scope (public, MIT), so you can build other things on it too.
These are the packages core runs on. We don’t keep a separate “public API” that lags behind what we use ourselves.
| Package | What you get |
|---|---|
@xentium/contracts |
shared types, permission keys, pagination and the XEC error-code registry |
@xentium/errors |
XentiumError, the XEC registry and the Express error middleware |
@xentium/server-kit |
settings with a TTL cache, pagination, encryption at rest, rate limiting, upload validation, storage |
@xentium/auth |
minting and verifying tokens, argon2 hashing, a revocation denylist, request guards |
@xentium/plugin-engine |
manifest validation, the DDL-only migration guard, the plugin registry and router |
pnpm add @xentium/errors @xentium/server-kitWe’re still in prerelease, so these go out under the alpha dist-tag. Pin it:
pnpm add @xentium/errors@alphaAnything with a dependency is a factory. Nothing grabs a module-level singleton, so your app passes in its own database, secret, Redis client or filesystem root:
import { createErrorMiddleware } from "@xentium/errors";import { createSettings } from "@xentium/server-kit";
app.use(createErrorMiddleware({ isProd, logger, persist }));
const settings = createSettings({ get: (key) => db.setting.findUnique({ where: { key } }), getMany: (keys) => db.setting.findMany({ where: { key: { in: keys } } }),});The rule we hold these packages to: a framework package doesn’t know what a user, an
article or a page is. So the layout/block system, appearance and everything else
that’s CMS-specific stays in apps/ and isn’t published.
For plugin developers
Section titled “For plugin developers”[!IMPORTANT]
@xentium/plugin-sdkisn’t on npm yet. It’s the authoring contract you need, and we’re holding it back on purpose: we’re splitting it into a generic half and a CMS-specific half, which is a breaking change. We’d rather make you wait than publish a version we already know we’ll break.Until then, take it from the repo: copy
packages/plugin-sdk/src/index.tsinto your plugin, or add the repo as a git dependency. It’s types only, so nothing extra ships at runtime either way.
The rest of the framework is useful in a plugin today: @xentium/contracts for
permission keys and XEC codes, and @xentium/errors so your plugin’s errors come back
in the same shape as ours.
You don’t need @xentium/server-kit, @xentium/auth or @xentium/plugin-engine in
a plugin. The host already runs them, and ctx.host gives you what it has: prisma,
queues, logger, the auth middleware. If you install your own copy, you get a second
instance that isn’t connected to anything.
The full walkthrough is in the Plugin development guide.