LightCMS Version History

LightCMS Version History

All notable changes to LightCMS, organized by version. Source: CHANGELOG.md


v3.3.0 — Bulk Operation Performance

Significantly improves performance of all bulk and batch operations, with particular gains at scale (hundreds of content items).

Performance Improvements

  • Scope filters pushed to MongoDBbulk_field_operation, scoped_search_replace_execute, and export_content now push template, category, folder, and content_ids filters down to MongoDB instead of loading all content and filtering in Go. For a 600-item site scoped to 100 pages, this eliminates ~500 unnecessary document transfers.
  • Goroutine worker pool (10 concurrent) — All four bulk/search-replace execute handlers now process items concurrently with a pool of 10 workers instead of sequentially. On a 100-item batch this yields up to 8–10× faster wall time.
  • Batch content fetch in bulk_update_content — Per-item GetContent calls replaced with a single $in query. 100-item bulk update: 100 DB round-trips → 1 for the initial fetch.
  • content_versions index on content_id — Previously missing; every UpdateContent call triggered a full collection scan on content_versions for the version count. Now O(log n) per item.
  • template_name index on content — Enables MongoDB-level template scope filters to use an index scan instead of a full collection scan.

New Service Methods

  • ListContentScoped — MongoDB-native scoped list with support for template_name, category, folder_path, and content_ids filters.
  • GetContentByIDs — Batch-fetch multiple content items in one $in query, returning a map keyed by ID.

MCP Tool Fixes

  • list_content include_data / include_fields — Fixed a bug where enriched field data was fetched correctly by the API but silently dropped before being returned to MCP callers.
  • auto_republish on search & replace execute — New boolean parameter on search_replace_execute and scoped_search_replace_execute. When true, pages that were published before the change are automatically re-published after replacement.
  • bulk_field_operation dry_run has_value — Dry-run results now report whether each matching page currently has a non-empty value for the target field.

v3.2.0 — Healthz Endpoint & DAU/MAU Analytics

Adds a structured health check endpoint following the VibeCtl Health Check Protocol, plus user activity tracking for DAU/MAU metrics surfaced in the health endpoint and admin dashboard.

/healthz Endpoint

  • GET /healthz — Unauthenticated structured JSON status: status, name, version, uptime, dependencies (live MongoDB ping), and kpis (DAU, MAU, pages created today)
  • HTTP 503 on unhealthy — Returns 503 when status is unhealthy; 200 otherwise
  • Existing /health unchanged — Plain-text OK endpoint for Fly.io TCP probes is preserved

Analytics & KPIs

  • AnalyticsService — New service backed by user_activity collection. Activity recorded on admin login and API key auth via fire-and-forget goroutine (no request latency impact)
  • Unique-per-day deduplication — In-process sync.Map dedup prevents repeat DB writes for the same user on the same calendar day. Storage: at most one document per user per day with 90-day TTL auto-expiry
  • DAU / MAU — Daily Active Users (distinct today) and Monthly Active Users (distinct last 30 days) via aggregation pipeline
  • Dashboard stat cards — Three new cards added: Daily Active Users, Monthly Active Users, Pages Created Today

v3.1.0 — Bulk Operations, Wiki-Like Markup & Security Hardening

First-class bulk content operations (eliminating N×1 API call patterns), a full wiki-like markup system for content authoring, configurable script policy, and comprehensive security fixes.

Bulk Content Operations

  • bulk_update_content — Update up to 100 content items in a single MCP/API call with merge semantics. Supports clear_fields, dry_run, and per-item success/error details
  • bulk_field_operation — Apply a single operation (clear, set, prepend, append, wrap) to a field across all matching pages. Scoped by template, folder, category, or IDs. Supports dry_run
  • export_content — Export content items with full field data as structured JSON. Designed for the export → transform → bulk_update pipeline
  • list_content with field data — New include_data and include_fields parameters return full template field values in list results, eliminating per-item get_content calls
  • clear_fields on update_content — Explicitly zero out fields, removing ambiguity about merge semantics
  • dry_run validation — Validate update payloads without committing changes on both update_content and bulk_update_content

Regex Search & Replace

  • All four search/replace tools now accept "regex": true for Go RE2 regular expression matching
  • Use $1, $2 for capture group references in replace strings
  • Input validation: 500-char pattern limit, max 20 capture groups, 10× expansion guard

Wiki-Like Markup System

  • WikilinksPage Title, display, /path syntax in any content field. Resolves to <a> at page generation time; broken links render as broken-link spans
  • Snippet includesinclude:snippet-name embeds a named snippet inline in any content field. Depth limit 3, cycle detection
  • Table of contents — Add {{.lc_toc}} in a template layout to auto-generate a <nav class="lc-toc"> from page headings
  • Heading IDs — All h1–h6 tags automatically get id= attributes for deep-linking
  • Markdown field type — Set a template field type to markdown for GFM rendering (tables, strikethrough, task lists, autolinks)
  • Inline #tag detection — Mentioning #tagname in any content field automatically tags the page for lc:query index pages
  • get_backlinks MCP tool — Returns all published pages that wikilink or link to a given path. Useful before renaming or deleting pages
  • Version history attribution — "By" column in version history shows the email of the editor who made each change

Configurable Script Policy

  • New site config markdown_script_policy controls who may use raw <script> tags in content
  • "all" (default) — all users may use scripts; fully backward-compatible
  • "admin_only" — editor-authored content sanitized via bluemonday; admin content passes through unchanged
  • "none" — all content sanitized regardless of author role
  • Configurable via admin Settings page or update_site_config MCP tool

Security Fixes

  • Export authorization: export_content now requires authentication
  • Regex DoS protection: pattern length cap (500 chars), capture group limit (20), expansion guard
  • Snippet recursion guard: depth limit 3 with cycle detection
  • Version history permissions: get_content_versions and get_content_version now enforce PermContentView
  • Folder path scope bug: scoped search/replace with /blog no longer matches /blog-old
  • Bulk field op limit: 500-page cap prevents unbounded database writes per request
  • Wikilink href safety: resolved links not starting with / render as broken-link spans
  • TOC HTML escaping: heading IDs in TOC anchors are properly HTML-escaped
  • Rate limiter cleanup: background goroutine prunes stale entries every 10 minutes

v3.0.0 — Dynamic Index Pages: Tags, Snippets & lc:query

The most significant content modelling capability added since v1.0 — a first-class system for building dynamic, automatically-updated index pages.

Content Tagging

  • Tags field on all content items — Any content item can carry zero or more freeform string labels, set in the admin editor or via {"tags": [...]} in the REST API
  • Full API supportGET /api/v1/content?tag=TAGNAME filters by tag; PUT /api/v1/content/{id} accepts a tags array
  • Tags are exact-match strings with preserved capitalization, indexed in MongoDB for efficient filtering

Snippets

  • New snippets collection — Named HTML template fragments with Go template variable support
  • Admin UI at /cm/snippets — Create, edit, and delete snippets with a live editor
  • REST API — Full CRUD at /api/v1/snippets
  • Available variables{{.Title}}, {{.FullPath}}, {{.Slug}}, {{.MetaDescription}}, {{.PublishedAt}}
  • Rendered through Go’s html/template — safe from XSS by default

lc:query Directives

  • Embed live content queries in template layouts — Using HTML comment syntax: <!-- lc:query filter="tag:X" snippet="name" -->
  • Processed at page generation time, replaced with rendered output of all matching published content items
  • Filter optionstag, category, template, folder
  • Sort optionstitle:asc, title:desc, created_at:asc, created_at:desc
  • Multiple directives per template — each is an independent query

Automatic Cascade Regeneration

  • Auto-regeneration — When tagged content is published or updated, all index pages whose templates contain lc:query directives are automatically regenerated
  • Also triggers when a template layout or snippet is updated

New MCP Tools (5 added, 54 → 59 total)

  • list_snippets — list all snippets
  • get_snippet — retrieve a snippet by ID or name
  • create_snippet — create a new named HTML snippet
  • update_snippet — update a snippet’s name or HTML
  • delete_snippet — delete a snippet

Security Fix

  • XSS in lc:query default fallback — When no snippet attribute was specified, title and path were concatenated without escaping. Fixed to use template.HTMLEscapeString()

v2.6.0 — MCP Tool Improvements

Bug Fixes

  • get_theme returned empty stringsThemeSettings struct was missing json struct tags; all theme fields now serialize correctly via the REST API and MCP
  • search_replace_execute response missing search/replace fields — Both search_replace_execute and scoped_search_replace_execute now echo back the search and replace strings used

New MCP Feature: Rendered HTML in get_content

  • get_content now accepts an include_rendered boolean parameter
  • When true, the response includes a rendered_html field containing the fully rendered page HTML (template + theme header/footer applied)
  • Works for both published and draft content — lets agents inspect exactly what visitors see without publishing

v2.5.0 — Security Hardening

  • SSRF preventionupload_asset_from_url blocks all private/reserved IP ranges (loopback, RFC1918, link-local, CGNAT, IPv6 ULA) before making any network request
  • ReDoS prevention — Full-text search runs under a 5-second context deadline, preventing pathological queries from pinning CPU
  • Permission checks — Search-replace preview and reindex-embeddings endpoints now require admin-only permissions
  • API rate limiting — Per-bearer-token sliding-window limiter: 300 requests per token per minute across the entire /api/v1/ subrouter
  • Asset serve_path whitelist — Upload paths restricted to /assets/, /images/, /docs/, /media/, or /files/
  • Trusted proxy IP extraction — Rate limiter uses configured trusted proxy settings, preventing IP spoofing via forged headers
  • Database indexes — Compound index on the content collection for improved query performance under load
  • Session secret validation — Server warns if secret is too short, fails hard in production if under 16 characters

v2.1.0 — Agentic API Improvements

Theme Reliability

  • Theme CSS on startupstatic/css/theme-vars.css is now regenerated from the database every time the server starts, preventing blank styles after a deploy or container restart

New Content Endpoints

  • Update by path — Update content by URL path instead of MongoDB ID, useful when you know the page URL but not its ID
  • Batch publish — Publish multiple content items in one call; pass an ID list or publish_all_drafts: true
  • Content preview — Render a content item’s HTML without publishing; accepts optional title/data overrides to preview unsaved edits; returns rendered_html and warnings (missing required fields, unclosed tags, unresolved placeholders)
  • Rendered HTML in get_contentinclude_rendered=true returns the fully rendered page HTML alongside regular content data

New Asset Endpoints

  • Upload from URL — Fetch a remote URL and store it as a LightCMS asset (HTTP/HTTPS only, 50 MB cap, MIME validation)

Theme Version Pinning

  • Pin/unpin theme versions — Lock a theme version to protect it from auto-pruning; pinned versions are marked with locked: true in version history

Scoped Search & Replace

  • Targeted replacements — Run search-and-replace filtered by content_ids, folder_path, template_name, and/or category — safer than a full site-wide replacement

New MCP Tools (13 added, 41 → 54 total)

  • update_content_by_path — update by URL path; merges data fields
  • publish_multiple — batch publish by ID list or all drafts at once
  • preview_content — render HTML without saving; supports field overrides
  • scoped_search_replace_preview / scoped_search_replace_execute — folder/template/category-scoped search & replace
  • upload_asset_from_url — fetch remote file and store as asset
  • pin_theme_version / unpin_theme_version — protect important theme milestones
  • Improved descriptions on existing tools with workflow guidance and examples

v2.0.1 — Configurable Search Ranking

  • Database-stored ranking config — All search ranking parameters now stored in the database and editable from the admin panel at Tools → End User Search → Search Ranking
  • Configurable fields — Title match boost, nav page boost, boosted template name substrings, template boost score, demoted path prefixes, demotion penalty score
  • Safety clamping — Values clamped to −1.0…1.0 to prevent accidental misconfiguration
  • Instant effect — Changes take effect immediately; in-memory cache invalidated on save
  • Search API documentation — Expanded typeahead suggest API docs, full parameter tables, response schemas, and JavaScript examples in the admin Integration Guide and README

Multi-User Access Control

  • Role-Based Access Control (RBAC) — Three roles (admin, editor, viewer) with granular permissions enforced on every admin UI page and REST API endpoint
  • User Management — Admin-only panel at /cm/users for creating users, assigning roles, disabling accounts, and resetting passwords
  • Email-based login — Authentication migrated from a single shared password to per-user email + password credentials
  • Force password change — Temporary passwords prompt a mandatory change on first login
  • Automatic migration — On first startup with an empty users collection, the existing admin password hash is carried over into a new admin user account

Audit Logging

  • Persistent audit trail — All mutations logged with acting user, action, resource, and timestamp
  • 365-day retention — Audit logs auto-expire via MongoDB TTL index
  • Filterable UI at /cm/audit — Filter by action type, resource, and date range
  • Async logging — LogAsync fire-and-forget pattern to avoid blocking request handlers

User-Scoped API Keys

  • API keys now belong to a specific user and inherit that user’s permissions
  • Admins can view and manage all keys; non-admins can only manage their own
  • Keys created before v2.0 remain functional as system-level keys with full access

Smart Search Ranking

  • Structural boost — Nav-linked pages (parsed from header HTML, cached 5 min) surface above other results
  • Template-based ranking — Concept pages rank above generic body-only content
  • Video deprioritisation — Pages under /videos/ rank below all other content types
  • Typeahead suggestions — Same structural ranking applied to prefix-match suggestions
  • Ranking priority: title+nav > title-only > nav-linked > concept pages > body-only > video transcripts

Bug Fixes

  • Fixed /cm/audit page crash caused by subtract/add template functions receiving mismatched integer types
  • Made arithmetic template functions type-flexible via interface{} dispatch

v1.4.0 — End-User Search API

  • Full-text search (/api/search?q=...) — Regex-based exact matching across all published content
  • Semantic vector search — Voyage AI embeddings stored in MongoDB Atlas; $vectorSearch pipeline for similarity queries
  • Hybrid mode — Reciprocal rank fusion (RRF, k=60) merges full-text and semantic results into a single ranked list
  • Title boosting — Results where the query appears in the page title float above body-only matches
  • Graceful degradation — Works without a Voyage API key (full-text only); automatically enables semantic search when configured
  • Rate limiting — Per-IP (10 req/min) and global (100 req/min) limits with DDoS protection
  • Embedding pipeline — Background batch generation with progress tracking in the admin panel
  • Typeahead suggestions/api/search/suggest endpoint for prefix-matching page titles and extracted keywords
  • WARP proxy for Voyage API calls on Fly.io to avoid IP-based rate limiting
  • Upgraded embedding model from voyage-3-lite to voyage-4-lite
  • Fixed SVG assets not displaying when uploaded with /assets path prefix
  • Expanded upload allowlist to include CSS, JS, JSON, and other text-based web assets

v1.2.0 — OAuth 2.1 & HTTP MCP Transport

  • OAuth 2.1 authorization server — Full authorization code flow with PKCE (S256), dynamic client registration (RFC 7591), token rotation, and revocation (RFC 7009)
  • Remote MCP clients — HTTP streamable MCP endpoint at /mcp — connects Cowork, Claude Desktop, and any MCP-compatible app without embedding credentials
  • Discovery endpoints/.well-known/oauth-authorization-server (RFC 8414) and /.well-known/oauth-protected-resource (RFC 9728) for automatic client setup
  • Dynamic MCP server card/.well-known/mcp/server-card.json with full tool schemas, served live from the running server
  • Smithery registry support — smithery.yaml and packaging config for registry publication
  • Test suite: 82% → 86% coverage with CI via GitHub Actions and Codecov integration
  • Loading state feedback on OAuth authorize buttons

v1.1.0 — REST API, CLI Tool & API Keys

  • REST API at /api/v1/ — Full JSON API for all content management operations (content, templates, assets, theme, config, redirects, folders, collections)
  • API key authenticationlc_-prefixed keys stored as SHA-256 hashes; created and managed in the admin panel
  • CLI tool (cmd/cli) — Command-line interface wrapping the REST API for scripting and CI/CD workflows
  • MCP refactor — MCP tools now use the REST API client rather than direct DB access
  • Partial update support on all PUT endpoints (send only changed fields)

v1.0.0 — Initial Release

  • Content management — Create, edit, publish, and delete content using customizable templates
  • Template system — Define reusable page structures with typed fields; HTML layout with {{.field_name}} placeholders
  • Static page generation — Published content rendered to content/generated/ for fast, zero-runtime serving
  • Content versioning — Automatic version snapshots on every update; revert to any prior version
  • Soft delete — Deleted content recoverable from the admin panel
  • Content collections — Auto-generated paginated listing pages filtered by category
  • MCP server (stdio) — 43 tools for managing the entire site through AI agents
  • Theme customization — Colors, fonts, border radius, custom CSS; header/footer HTML injection with versioning
  • Asset management — Upload, organize, and serve images, documents, and other files
  • URL redirects — 301/302 rules managed from the admin panel
  • Rich text editor — TinyMCE integration for visual editing
  • Search & replace — Site-wide text replacement with preview before execution
  • Security — CSRF protection, bcrypt passwords (cost 12), session cookies (SameSite=Strict), file upload validation, login rate limiting
  • Fly.io deployment — fly.toml and Dockerfile for one-command production deploy

MIT License · Copyright 2026 Metavert LLC