Umbral
Back to the blog
PluginSpotlight Jul 9, 2026 8 min read

Twenty-one plugins, one contract: a tour of the Umbral toolbox

Auth, admin, REST, background jobs, realtime, storage, multi-tenancy — in Umbral they're all plugins, structurally identical to one you'd write yourself. Here's the whole toolbox, and why 'it's just a plugin' is the most important sentence in the framework.

Most frameworks have a core and then some extensions. The core gets special privileges — hooks the extensions can't reach, a fast path only the built-ins get to use. Extensions are second-class citizens, and you feel it the first time you try to build something the authors didn't anticipate.

Umbral made a different bet, and it's the bet that shapes everything else: the core is thin, and everything else is a plugin — including the batteries. Auth, sessions, the admin, REST, the task queue: structurally, each is identical to a plugin you'd write yourself. There is no privileged path. If a built-in couldn't be expressed as a plugin, that would be a bug in the plugin contract, not a reason to cheat.

Cargo enforces this for us. umbral-core doesn't depend on the REST plugin — so "serializers are a plugin" isn't a slogan, it's a fact the compiler won't let us break. A REST-free app compiles with zero serializer code in the binary.

Here's the toolbox that contract produced.

The parts you reach for first

umbral-admin turns every model into a control panel — list views, search, combinable filters, relation pickers, dashboards. umbral-auth and umbral-permissions give you users, groups, argon2 hashing, and role-based access the admin and API already understand. umbral-sessions keeps the identity around; umbral-oauth adds "sign in with Google/GitHub" and account connection.

Declare a model, mount these four, and you have a login page and an admin before you've written a route.

The parts that make it an API

umbral-rest turns the same models into JSON resources — serializers, viewsets, pagination, filtering — safe-by-default, with object-level scoping so nobody reads across a boundary. umbral-openapi documents them and mounts a Swagger UI, and umbral-playground drops a mini-Postman right into your app so you can share an endpoint with a frontend teammate without anyone installing anything.

The parts that move work off the request

umbral-tasks is a database-backed job queue — define work with #[task], enqueue it, drain it with a worker, scale horizontally with SKIP LOCKED. umbral-realtime pushes updates to the browser over SSE or WebSockets, targeted at a single user or a room, with connection and rate caps so no one client can flood you. umbral-email sends the transactional mail your reset flows need, and umbral-cache memoises the expensive stuff.

The parts that keep you safe and sane in production

umbral-security ships CSRF, HSTS, and clickjacking protection on by default. umbral-rls pushes tenant isolation into Postgres itself, and umbral-tenants routes each customer to their own schema and binds the tenant to the caller. umbral-storage serves both your static assets and user uploads through one pluggable backend — filesystem in dev, S3 in prod. umbral-health answers the probes your load balancer asks for. umbral-logs logs the real client IP, and umbral-analytics captures product events without dragging down the request path.

The parts you only notice when they're gone

umbral-livereload refreshes your browser the instant you save a template or CSS — inert in production. umbral-signals lets you hang audit logs, cache-busting, and notifications off your data without touching the write code.

Why "it's just a plugin" matters to you

Count them and it's twenty-one first-party plugins. But the number isn't the point. The point is that your plugin sits at exactly the same table. The extension point that powers the admin is the one you use to add your billing integration. The signal the framework fires on save is the one your code subscribes to. There's no inside track you're locked out of.

That's the real batteries-included promise: not a fixed menu of features, but a toolbox where the tools you build are indistinguishable from the ones that came in the box. Browse the whole set on the plugin directory — and then go write the twenty-second.