ilusm.dev

cms

Content Management System - define content types with typed fields, create and publish pages, manage media, build taxonomy trees, compile templates, create menus and themes, run a publishing workflow with scheduled publish/unpublish, search content, generate sitemaps, produce RSS feeds, localise content, and emit a full static site.

Load with: use cms

What this module does

cms is a headless CMS in a single module. You define a CMS instance, register content types (blog post, product, page, etc.) with typed fields, create content records, set their fields, publish immediately or schedule for later, and unpublish. Taxonomy lets you organise content into hierarchical or flat categories.

Templates are compiled via tpl and rendered with content data. A publishing workflow engine lets you define state-machine transitions with conditions. Search filters published content by title and body text. Sitemap and RSS generation, a simple in-memory cache, user/permission definitions, and static site export round out the module.

Quick example

use cms

# Create a CMS
site = cmsne("My Blog")

# Define a content type
post_type = cmsct("post", "Blog Post", [
    cmsfl("body", "rich-text", {req: tru}),
    cmsfl("excerpt", "text", {})
])

# Create and publish a post
post = cmsc3("post", "Hello World", "alice@example.com")
post = cmsc1(post, "body", "This is my first post.")
post = cmsc0(post, nil)  # publish now

# Render with a template
# tmpl = cmst0("page", "

{{ct.ttl}}

{{ct.ct.body}}") # cmstm(tmpl) # compile # html = cmsrn(post, tmpl, nil) # Search published content results = cmssr(site, "hello") # Increment content version post = cmsc2(post)

Functions

CMS instance

cmsne(name)

Creates a new CMS with a name and empty collections for content types, media, menus, users, taxonomy, publishing queue, templates, and state cache.

cmsud()

Generates a unique CMS ID in the form "cms-{ms}-{rand}".

Content types

cmsct(id, label, fields)

Defines a content type with an ID, display label, and a list of field definitions. arc: tru marks it as archivable.

cmsfl(name, type, opts)

Defines a field: type is a string like "text", "rich-text", "number", "boolean". Options: lbl (label), req (required, default fls), dflt (default value), val (validator).

Content records

cmsc3(content_type, title, author)

Creates a new content record. Status starts as "draft". Auto-generates a slug from the title and a unique ID. Sets cr and mod to now.

cmsc1(content, field, value)

Sets a field value on a content record. Updates mod to now.

cmsc0(content, scheduled_ts)

Publishes content. If scheduled_ts is nil, sets status to "pub" and publish time to now. Otherwise sets status to "sched" with the given timestamp.

cmscn(content)

Unpublishes content - sets status back to "draft" and records the unpublish time.

cmsc2(content)

Increments the version counter on a content record.

Media

cmsmd(filename, mime_type)

Creates a media record with a unique ID, filename, MIME type, size (0 until updated), alt text, caption, and creation timestamp.

Taxonomy

cmstx(id, label, hierarchical)

Creates a taxonomy (e.g. "category", "tag"). Set hierarchical: tru for tree-structured categories.

cmstr(taxonomy_id, name, parent)

Creates a term within a taxonomy. Generates a slug from the name. parent is the parent term ID or nil for a root term.

Templates

cmst0(name, source)

Creates a template record from a source string. The compiled form is nil until cmstm is called.

cmstm(template)

Compiles a template via tpl.tplco. Returns the updated template with comp set.

cmsrn(content, template, theme)

Renders a compiled template with content data {ct, meta} via tpl.tplre. Returns the rendered string.

Menus and themes

cmsm0(id, name)

Creates a named navigation menu with an empty items list.

cmsmn(label, url, parent)

Creates a menu item with a label, URL, optional parent ID, and ordering index (default 0).

cmsth(name)

Creates a named theme with empty template map, CSS, and JS.

URLs

cmsrl(content)

Returns the canonical URL for a content record: "/{content_type}/{slug}".

cmssl(text)

Converts arbitrary text to a URL slug - lowercase, non-alphanumeric characters replaced with hyphens, consecutive hyphens collapsed.

Search, sitemap, and feeds

cmssr(cms, query)

Case-insensitive full-text search across published content titles and body fields. Returns up to 20 matches.

cmsst(cms)

Generates a sitemap as a list of {url, mod, pri} objects for all published content.

cmsrs(cms, content_type)

Generates a minimal RSS XML string for the 10 most recently published items of a given content type.

Workflow

cmsw1(name, steps)

Creates a named publishing workflow with a list of state names and an empty transition map.

cmswf(from, to, condition)

Defines a transition from one state to another, guarded by a condition function.

cmsw0(workflow, content, action)

Applies a workflow transition. Finds the first matching transition from the current state and updates content.st.

Cache and export

cmscp(cms, key, value, ttl)

Stores a value in the CMS state cache with an expiry timestamp.

cmsgt(cms, key)

Retrieves a cached value if not expired.

cms2j(cms) / cmsfr(json)

Export the entire CMS to JSON and import it back.

cmsgn(cms, output_dir)

Static site generator - renders all published content with the "page" template and writes .html files to output_dir at their canonical URL paths.

Notes

  • All content IDs are generated with cmsud() - millisecond timestamp plus a random 4-digit suffix.
  • Requires trl, txt, jsn, tim, and tpl.