BarakoCMS modules
Add a module when the server needs a rule
A module’s version moves only when that module changes. A module runs on any core of the same major version.
External / social sign-in module for barakoCMS: "Continue with Facebook / Google / LinkedIn / GitHub" via OAuth, matched to a global user by verified email, plus any OpenID Connect provider configured by issuer URL (Apple included) and an id token grant for native apps, issuing the same tenant-scoped, device-bound token as the built-in flows. Captures profile details (photo, birthday, location) per provider.
Optional file-attachment module for barakoCMS: upload and retrieve files (receipts, photos, documents) stored in Postgres via Marten.
Content portability for barakoCMS: export content-type definitions and their content data as a JSON bundle, and import a bundle into another instance (upsert types by name, recreate content via events). For backup, migration, seeding, and sharing content-type templates.
Optional bulk-import module for barakoCMS: analyze .xlsx/CSV uploads and bulk-create content. Zero-dependency parsing via Talaan.
Resend email-provider module for barakoCMS: implements IEmailService via the Resend HTTP API, plus a delivery webhook that records bounces/complaints as EmailEvent documents.
Client error logging for barakoCMS: apps POST captured browser errors (message, stack, page, user, tenant) to /api/client-errors; they're deduplicated by fingerprint with an occurrence count and browsable by Admin/SuperAdmin at GET /api/client-errors so you can retrieve and fix them later.
Umami web-analytics module for barakoCMS: proxies a self-hosted Umami instance behind admin-only endpoints so the CMS admin can show visitors, top pages, referrers and countries, and register new tracked sites, without exposing an Umami API key to the browser.
Optional double-entry accounting module for barakoCMS: accounts, balanced journal entries, and reporting.
AI module for barakoCMS: semantic (vector) search over published content using a self-hosted embedding model (Ollama by default). Indexes only public fields, searches only published, document-Public entries, and needs no third-party API key.
PWA install tracking for barakoCMS: records when the app is added to the home screen / run as an installed app, anonymously or tied to the signed-in user, so the admin can see adoption and who installed it.
Lean feature-flag module for barakoCMS: create a flag, toggle it on/off, and target it ("true for this and that") by tenant, by user, or by percentage rollout. Global flags with per-tenant targeting, evaluated server-side and exposed at GET /api/feature-flags for the UI.
Optional trusted-device module for barakoCMS: records the device behind each sign-in, binds sessions to devices, and can require OTP approval for new devices.
S3-compatible object storage provider for the barakoCMS Files module. Works with AWS S3, Cloudflare R2, and self-hosted S3-compatible stores such as SeaweedFS. Public files get a direct, CDN-friendly URL; private files are proxied through the API.
Public forms for barakoCMS: a content type marked as a form accepts anonymous submissions at POST /api/public/forms/{slug}, validated against its own schema and stored as a Sensitive entry that delivery never serves, with a per-client rate limit, a honeypot, optional Cloudflare Turnstile and optional verification of an email field by a one-time code.
Page tree for barakoCMS: refuses a parent cycle, a page too deep or a reserved root slug on a configured content type, per tenant, and serves the nested navigation, path resolution with breadcrumbs, and an authenticated tree with drafts for the console.
SMTP email-provider module for barakoCMS: implements IEmailService over any SMTP relay (a host's mail server, Google Workspace, Amazon SES, a corporate relay) using MailKit. Registers itself only when a host is configured.
Registry of outside services for barakoCMS: register a service, take its heartbeats, and see whether it is Healthy, Late or Down. The base the message state and operator actions build on.
Loads barakoCMS configuration values, such as JWT:Key, Secrets:Key and module credentials, from Google Secret Manager at startup, authenticating as the instance's own service account. A mapped secret that cannot be read stops startup with a message naming the secret, never its value.
QR codes for barakoCMS delivery: renders one field of a public entry as a PNG or SVG QR code, only for the fields a deployment lists per content type, so a claim token or a link can be scanned from a page, an email or a printed document.
Booking for barakoCMS: resources with a time zone, weekly opening hours and exceptions, bookings as content entries that a lifecycle hook refuses when they overlap another active booking of the same resource, and a public availability route that returns free slots only.
Payments for barakoCMS: a content type declares what is payable, a public checkout returns the provider's hosted URL for the amount stored on the entry, and a signed, idempotent webhook runs the paid transition.
Tagging and taxonomy for barakoCMS: vocabularies, terms that can nest, and term assignments on any record by content type and record id, so a contact, a file and a content entry share one vocabulary. Query the records carrying a term across types, per tenant.
Loads barakoCMS configuration values, such as JWT:Key, Secrets:Key and module credentials, from AWS Secrets Manager at startup, authenticating as the instance's own role. A mapped secret that cannot be read stops startup with a message naming the secret, never its value.
Notifications for barakoCMS: any module raises a notification for a user, it lands in that user's in-app inbox (list, unread count, mark read) and is also handed to any delivery sink registered beside it, such as the built-in email sink. Tenant-scoped, and a user sees only their own.
Comments and notes for barakoCMS: a threaded comment on any record. A comment names its target by type and id, and it is only readable and postable by a caller who can read that record. Content entries work out of the box; any other module registers its own record type.
Scheduling module for barakoCMS: schedule a named action for a due time, and exactly one API instance hands it to the registered handler when the time comes. Never fires the same entry twice.
CDN purge module for barakoCMS: a CdnPurge workflow action that purges the cache tags of a published entry from Cloudflare, using the same tags the delivery API sends.
Document generation for barakoCMS: render an entry to a PDF from a narrow template language, drawn natively with SkiaSharp, and store it through the Files module. No browser, and a template cannot fetch anything.
Contacts for barakoCMS: one record for a person or an organization, with typed custom fields, person to organization links, email deduplication with a merge endpoint, tenant scoping and capability-gated access. Email, phone and address are Sensitive and never leave over anonymous delivery.
Reports for barakoCMS: save a report over a client's own content (a content type, filters, one group-by field and count, sum, avg, min or max measures), run it with a date range, and export it as CSV. Totals are computed in the database, bounded by a group limit, and follow the reader: row conditions apply and a field the role cannot read cannot be grouped or measured.
The question every contribution runs into
Module, or core?
It is a module if any of these is true
Two sensible projects would disagree about wanting it
Core is what nobody gets a choice about
It names a vendor, a product or a business domain
Core’s vocabulary is content, users, tenants and permissions
It brings a dependency core does not already carry
Core’s dependency list is a promise to everyone who installs it
Removing it still leaves a working CMS
If content, auth, tenancy and delivery survive, it was never core
It is core if any of these is true
Something else cannot work without it
Content, content types, auth, tenancy, permissions
Core would need to know it exists
The moment core needs an if for your feature, it is not a module
It changes the shape of content, auth, tenancy or delivery
Those are contracts other people’s modules depend on
When it is genuinely borderline, build it as a module. Moving one into core later is additive; pulling a feature out of core breaks everyone who installed it.
Where core stands against its own rules
The rules were applied to core itself. One feature failed them and is already gone: Features/Club/ was product vocabulary rather than CMS vocabulary, and the Membership model it operated on stayed, because a feature failing the rules does not mean the model under it is wrong. The two below look like they fail the rules and are correctly core.
Features/Workflows/Looks like a module, is correctly core: it runs as a Marten projection, and IModuleSchema exposes only For<T>(). A limit of the contract, written down rather than implied.
Features/Audit/Looks optional, is correctly core: one read endpoint, but fifteen core files write audit entries. A module here would leave core writing records nothing could read.
Build your own the same way
A module is one contract and the hooks it needs
Contribute DI services, your own Marten documents, FastEndpoints endpoints and seed data. Core knows none of them by name. Discovery finds the assembly, so installing yours is a package reference and a restart.
Turning a module off leaves its data alone
GET /api/modules lists every module with enabled.
A name that matches nothing refuses to start
And lists the names it does know, rather than booting without it.