gleamcms

A fact-oriented, sovereign content management system built on the AaronDB temporal datalog engine for the Erlang/BEAM virtual machine.

gleamcms is an independent, sovereign project. It depends on aarondb purely as an embedded Datalog engine and owns its complete web, projection, and media layers (wisp / mist / lustre / simplifile).


The Core Philosophy: Content as Immutable Values

Traditional content management systems (WordPress, Strapi, Ghost, Payload) are place-oriented: they model content as mutable database rows or documents. Updating an article overwrites the values at that disk location (UPDATE posts SET ...), destroying historical provenance unless secondary audit tables are bolted on.

gleamcms adopts Rich Hickey's Epochal Time Model and the Value of Values:


Layout

src/
gleamcms.gleam # Application bootstrapper and listener
gleamcms/
config.gleam # Typed, fail-closed runtime configuration
theme.gleam # Renderer interface definition
ai/
designer.gleam # Bounded AI theme designer (30s timeout, CSS whitelisting)
builder/
generator.gleam # Atomic static site generator (isolated staging + swap)
importer.gleam # Legacy JSON data migration tooling
media.gleam # CAS media abstraction interface
storage.gleam # Pluggable storage adapter (LocalStorage & S3Storage)
theme.gleam # Theme resolution and provider
content/
ast.gleam # Typed AST representations (Inline, Block, Document)
markdown.gleam # Pure functional Markdown parser & safe HTML renderer
db/
post.gleam # Post model, validation, and Datalog persistence
schema.gleam # AaronDB attribute schema declarations
editor/
app.gleam # Lustre SSR admin editor shell
events/
webhook.gleam # Signed HMAC-SHA256 webhook event dispatcher
runtime/
ffi.gleam # Quarantined Erlang host FFI bindings
server/
api.gleam # JSON decoders, CRUD, sync, generation & design endpoints
auth.gleam # Stateless HMAC sessions, cookies & POST-only login guard
router.gleam # High-level HTTP request dispatcher (<70 LOC)
static.gleam # Static asset & generated output serving + security headers
themes/
catalog_a.gleam # Curated theme definitions 1 to 25
catalog_b.gleam # Curated theme definitions 26 to 51
configurable.gleam # Config-driven dynamic HTML/CSS renderer
default.gleam # Built-in sovereign dark/light theme
library.gleam # Unified theme catalog aggregator
gleamcms_httpc_ffi.erl # Erlang FFI (bounded port execution, crypto HMAC, inets)

Gap Analysis: GleamCMS vs. External CMS Alternatives

DimensionGleamCMS (AaronDB)Payload CMS v3Strapi v5Ghost v5Sanity Content Lake
Data ModelEAV Datalog Facts (Immutable Datoms)Relational SQL / DocumentRelational SQL (MySQL/PG)Relational SQL (MySQL/SQLite)JSON-LD Structured Documents
Mutation ModelAtomic Fact AssertionsIn-place row overwriteIn-place row overwriteIn-place row overwriteDocument CRDT mutation
Temporal HistoryNative Fact RetentionCustom version tablesDraft/Publish duplicatesSingle updated_atDocument history API
Query EngineDeclarative Datalog PatternsTypeScript ORM builderREST filters / GraphQLKnex ORM queriesGROQ (Graph Queries)
SSG ProjectionsAtomic Staging & Rename SwapNext.js Server ComponentsHeadless API onlyDynamic SSR onlyHeadless API only
Content SafetyAST Markdown Parsing & EscapingDOMPurify / Slate ASTSanitized Rich TextLexical AST RendererPortable Text Serializer
Webhooks & EventsSigned HMAC-SHA256 PayloadsCustom lifecycle hooksCustom webhook UIWebhook integrationsManaged GROQ webhooks
Auth BoundaryPOST-Only Form + HMAC CookiesScoped JWTs & CookiesRole JWTs & PermissionsPassword + 2FA / SessionOAuth / SAML SSO
Runtime Footprint~30 MB (Single BEAM node)~250 MB (Node + SQL DB)~350 MB (Node + SQL DB)~200 MB (Node + MySQL)Cloud SaaS (Proprietary)
File SizingStrictly < 500 LOC per fileLarge multi-kLOC filesLarge controllersLarge monolithsModular React components

Configure (Fail-Closed)

gleamcms refuses to start unless all required secrets are non-blank. Configuration is loaded once during boot and threaded explicitly:

Env varRequiredDefaultPurpose / Validation
GLEAMCMS_SECRETyesnoneNon-blank signing secret for stateless admin HMAC session cookies. Never logged.
GLEAMCMS_ADMIN_TOKENyesnoneNon-blank bearer password accepted by POST /admin/login. Never logged.
GLEAMCMS_OUTPUT_DIRnogleamcms_outputDirectory for generated atomic site projections.
GLEAMCMS_DATA_DIRnoMnesia.nonode@nohostPersistent AaronDB/Mnesia storage directory.
GLEAMCMS_PORTno4000Port integer from 1 through 65535.
GLEAMCMS_COOKIE_MAX_AGEno86400Session cookie lifetime in seconds (60 to 2592000).
GLEAMCMS_IMPORT_LEGACYnofalseExplicit one-time legacy JSON import flag.

Quick Start

# 1. Set environment secrets
export GLEAMCMS_SECRET=$(openssl rand -hex 32)
export GLEAMCMS_ADMIN_TOKEN=$(openssl rand -hex 16)
export GLEAMCMS_PORT=4000
# 2. Run test suite
gleam test
# 3. Start sovereign server
gleam run

Access the admin editor at http://localhost:4000/admin and log in with your configured GLEAMCMS_ADMIN_TOKEN.


Invariants & Certification