Restore missing content hydration logic in reconstructCollectionItems method that was accidentally removed during the engine file split (b46f643). Collection items were appearing empty instead of displaying original developer content. This fix restores the database-first behavior where content is properly extracted, stored, and injected back into .insertr elements within collection items.
Insertr
The Tailwind of CMS - Zero-configuration content editing for any static site
Insertr adds editing capabilities to any HTML website by simply adding class="insertr" to elements. No complex setup, no architectural changes, no framework dependencies. Just mark what should be editable and get a production-ready CMS.
✨ Zero Configuration Philosophy
Just Add a Class
<!-- Individual elements -->
<h1 class="insertr">Main Title</h1>
<p class="insertr">Description text</p>
<a href="/contact" class="insertr">Contact Us</a>
<!-- Container expansion -->
<section class="insertr">
<h1>Hero Title</h1>
<p>Hero description</p>
<button>Call to Action</button>
</section>
That's it! No manual IDs, no configuration files, no schema definitions.
Container Expansion
Containers with class="insertr" automatically make their viable children editable:
- Viable children: Elements containing only text (h1-h6, p, span, a, button)
- Automatic detection: Skip complex nested elements
- Semantic convenience: One class enables section-wide editing
🎯 Three User Experiences
1. Regular Visitors (99% of traffic)
- Pure static HTML performance
- Zero editor assets loaded
- No runtime overhead
2. Content Editors (Authenticated users)
- Style-aware editing interface loads on demand
- Click-to-edit any marked element
- Rich text editor with style preservation and formatting toolbar
- Link editor with popup configuration for complex elements
- Changes saved to database with version history
3. Developers (You)
- Add
class="insertr"to any element - Use HTML
idattributes for complex cases - Never see or manage generated content IDs
- Works with any static site generator
🔐 Authentication & Security
Insertr provides enterprise-grade authentication with multiple provider support for secure content editing.
Authentication Providers
Mock Authentication (Development)
auth:
provider: "mock"
- Zero setup - Works immediately for development
- Automatic login - No credentials needed
- Perfect for testing - Focus on content editing workflow
Authentik OIDC (Production)
auth:
provider: "authentik"
oidc:
endpoint: "https://auth.example.com/application/o/insertr/"
client_id: "insertr-client"
client_secret: "your-secret" # or use AUTHENTIK_CLIENT_SECRET env var
Enterprise-grade security features:
- ✅ OIDC Discovery - Automatic endpoint configuration
- ✅ PKCE Flow - Proof Key for Code Exchange security
- ✅ JWT Verification - RSA/ECDSA signature validation via JWKS
- ✅ Secure Sessions - HTTP-only cookies with CSRF protection
- ✅ Multi-tenant - Per-site authentication configuration
Authentication Flow
1. Editor clicks gate → Popup opens to Authentik
2. User authenticates → Authentik returns authorization code
3. Backend exchanges code for JWT → Validates with OIDC provider
4. Editor UI loads → Full editing capabilities enabled
Authentik Setup Guide
-
Create OIDC Provider in Authentik:
Applications → Providers → Create → OAuth2/OIDC Provider - Name: "Insertr CMS" - Authorization flow: default-authorization-flow - Client type: Confidential - Client ID: insertr-client - Redirect URIs: https://your-domain.com/auth/callback -
Create Application:
Applications → Applications → Create - Name: "Insertr CMS" - Slug: insertr - Provider: (select the provider created above) -
Configure Insertr:
auth: provider: "authentik" oidc: endpoint: "https://auth.example.com/application/o/insertr/" client_id: "insertr-client" client_secret: "your-generated-secret" -
Environment Variables (Recommended):
export AUTHENTIK_CLIENT_SECRET="your-secret" export AUTHENTIK_ENDPOINT="https://auth.example.com/application/o/insertr/"
Security Best Practices
- Environment Variables: Store secrets in env vars, not config files
- HTTPS Only: Always use HTTPS in production for OAuth flows
- Restricted Access: Use Authentik groups/policies to limit editor access
- Token Validation: All JWTs verified against provider's public keys
- Session Security: Secure cookie settings prevent XSS/CSRF attacks
🚀 Current Status
✅ Complete Full-Stack CMS
- Style-Aware Editor: Rich text editor with automatic style detection and formatting toolbar
- HTML Preservation: Perfect fidelity editing that maintains all element attributes and styling
- Enterprise Authentication: Production-ready OIDC integration with Authentik, PKCE security
- Content Persistence: SQLite/PostgreSQL database with REST API, complete version control
- Version History: Complete edit history with user attribution and one-click rollback
- Build Enhancement: Parse HTML, inject database content, build-time optimization
- Smart Detection: Auto-detects content types and generates style-based formatting options
- Link Management: Popup-based link configuration for complex multi-property elements
- Full Integration: Seamless development workflow with hot reload
🚀 Production Ready
- ✅ Full HTTP API server with authentication and version control
- ✅ Build-time enhancement for static site generators
- ✅ PostgreSQL and SQLite database support
- ✅ Authentik OIDC integration for enterprise authentication
- Deploy enhanced static files to any CDN or host
- Run content API server on separate infrastructure
🛠️ Quick Start
Quick Start (Recommended)
# Clone and setup
git clone <repository-url>
cd insertr
# Install dependencies and build everything
just install build
# Start full-stack development
just dev
This starts:
- Demo sites: http://localhost:8080/sites/demo/ (auto-enhanced for testing)
- API server: http://localhost:8080/api/* (with content persistence and version control)
Using NPM
# Alternative using npm
npm run install:all
npm run build
npm run dev
Available Commands
just --list # Show all available commands
# Development (Full-Stack by Default)
just dev # Start full-stack development (recommended)
just demo [site] # Start specific demo site (default, dan-eden)
just list-demos # Show all available demo sites
just demo-only # Demo site only (no content persistence)
just serve # API server only (localhost:8080)
# Building
just build # Build library + unified binary (complete stack)
just build-lib # Build JavaScript library only
# Utilities
just check # Validate project setup
just status # Show project status
just clean # Clean build artifacts
🎯 Complete Development Experience
Running just dev gives you the complete Insertr CMS:
- ✅ Style-Aware Editor - Rich text editing with automatic style detection and formatting
- ✅ HTML Preservation - Perfect fidelity editing that maintains all styling and attributes
- ✅ Real-Time Persistence - SQLite database with REST API and authentication
- ✅ Version Control - Complete edit history with user attribution and rollback
- ✅ Content Management - Create, read, update content via browser with popup-based link editing
- ✅ Build Integration - Binary enhances HTML with database content
- ✅ Hot Reload - Changes reflected immediately
📚 Version Control Features
Complete Edit History
Every content change is automatically tracked with:
- User Attribution - Who made each change
- Timestamps - When changes were made
- Content Snapshots - Full content preserved for each version
Easy Rollback
- View History button in any content editor
- One-Click Restore to any previous version
- Version Comparison - See what changed between versions
- Safe Rollback - Current content is preserved before restoration
Example Workflow
1. Editor clicks on any element with class="insertr"
2. Professional editing modal opens
3. Click "View History" to see all previous versions
4. Each version shows: timestamp, author, content preview
5. Click "Restore" on any version to rollback instantly
6. All changes are tracked automatically
📊 Parser Output Example
🔍 Parsing HTML files in: ../demo-site/
📊 Parse Results:
Files processed: 2
Elements found: 40
Container expansions: 3
Generated IDs: 34
📝 Content Types:
text: 19 # Headlines, short content
markdown: 19 # Rich content, paragraphs
link: 2 # Buttons, navigation
🎯 Container Expansions:
hero-section → 3 children (h1, p, button)
services-grid → 6 children (3×h3, 3×p)
🏗️ Architecture: Unified Binary
Enhancement Pipeline
Static Site Build → insertr enhance → Enhanced Deployment
↓ ↓ ↓
Pure HTML Parse + Inject Smart Loading
Database Content (Auth-dependent)
↓
Runtime Content API ← insertr serve ← Database (SQLite/PostgreSQL)
Unified Commands:
insertr enhance- Build-time content injectioninsertr serve- Runtime API server- Single binary handles both development and production workflows
Smart Loading Strategy
<!-- Regular visitors: zero overhead -->
<h1 class="insertr">Welcome to Our Site</h1>
<!-- Authenticated editors: rich editing -->
<h1 class="insertr" data-content-id="hero-title-abc123"
data-editor-loaded="true">Latest Content From Database</h1>
Benefits:
- Performance: Zero runtime cost for regular visitors
- Framework agnostic: Works with Hugo, Next.js, Jekyll, etc.
- Zero configuration: No schema files or content mappings
- Developer friendly: Stay in HTML markup, no context switching
🔧 Unified Binary Commands
Build-Time Enhancement
# Production build with remote API
./insertr enhance src/ --output ./dist --api https://cms.example.com --api-key xyz
# Development build with local database
./insertr enhance demo-site/ --output ./dist --db ./content.db
# Development build with mock data
./insertr enhance demo-site/ --output ./dist --mock
# Use justfile shortcuts
just enhance # Default: demo-site/ → dist/ with mock data
just enhance input="src" output="public" # Custom paths
Runtime API Server
# Development server with automatic site enhancement
./insertr serve --dev-mode --port 8080
# Production server with PostgreSQL
./insertr serve --db "postgresql://user:pass@host:5432/dbname" --config production.yaml
# Production server with custom config and Authentik
./insertr --config ./production.yaml serve
# Use justfile shortcuts
just serve # Development server on :8080 with auto-enhanced demo sites
just dev # Full development stack (recommended)
Configuration Options
# YAML configuration file
./insertr --config ./custom.yaml [command]
# Environment variables
export INSERTR_DB_PATH="./content.db"
export INSERTR_API_URL="https://api.example.com"
export INSERTR_API_KEY="your-api-key"
export INSERTR_SITE_ID="production"
# Command-line flags (highest priority)
./insertr --db ./custom.db --site-id staging serve --port 3000
# Show all options
./insertr --help
./insertr enhance --help
./insertr serve --help
📚 Integration Examples
GitHub Actions Workflow
# .github/workflows/deploy.yml
- name: Build static site
run: hugo --minify
- name: Enhance with Insertr
run: insertr enhance ./public --output ./dist
- name: Deploy enhanced site
uses: peaceiris/actions-gh-pages@v3
with:
publish_dir: ./dist
Container vs Individual Elements
<!-- Semantic convenience: entire section editable -->
<section id="hero" class="insertr">
<h1>Dynamic Title</h1> <!-- → text input -->
<p>Dynamic description</p> <!-- → textarea -->
<button>Dynamic CTA</button> <!-- → link editor -->
</section>
<!-- Granular control: specific elements -->
<nav>
<h1 class="insertr">Site Name</h1>
<ul>
<li><a href="/" class="insertr">Home</a></li>
<li><a href="/about" class="insertr">About</a></li>
</ul>
</nav>
Content Type Detection
- Headlines (
h1-h6) → Rich text editor with style-aware formatting - Paragraphs (
p) → Rich text editor with detected style options from CSS - Links/Buttons (
a,button) → Popup-based link editor with text + URL configuration - Containers (
div,section) → Expand to viable children with automatic style detection
🔌 API Reference
Simple Content Management
# Create or update content (single endpoint for both)
curl -X POST http://localhost:8080/api/content?site_id=demo \
-H "Content-Type: application/json" \
-d '{"value": "New content", "type": "text"}'
# Get all content for a site
curl http://localhost:8080/api/content?site_id=demo
# Get specific content by ID
curl http://localhost:8080/api/content/content-id?site_id=demo
# View edit history
curl http://localhost:8080/api/content/content-id/versions?site_id=demo
# Rollback to previous version
curl -X POST http://localhost:8080/api/content/content-id/rollback \
-d '{"version_id": 123}'
Key Features:
- Single POST endpoint handles both create and update (upsert)
- Automatic ID generation from element context if no ID provided
- Version control preserves all changes with user attribution
- Auto-enhancement updates static files when content changes
🔧 Development Workflow
Live Development with Hot Reload
# 🔥 Hot Reload: watches BOTH library AND unified binary
just air
# Alternative: Watch library only
just watch
# or: cd lib && npm run dev
# Library changes: lib/src/**/*.js → Auto rebuild library + binary
# Binary changes: cmd/**/*.go, internal/**/*.go → Auto rebuild binary
# Both trigger server restart with latest embedded assets
# Visit localhost:3000 → Refresh to see changes
What Gets Hot Reloaded:
- JavaScript library changes (
lib/src/) - Go unified binary changes (
cmd/,internal/) - Enhanced HTML output (real-time content injection)
Content ID Management
Development Phase:
- Generated IDs are disposable and change freely
- Focus on markup, ignore content persistence
- Use HTML
idattributes for complex cases
Production Phase:
- Preserve existing content mappings for stability
- Binary warns about orphaned content
- Simple migration tools for structural changes
⚙️ Configuration
YAML Configuration (insertr.yaml)
# Database configuration
database:
path: "./insertr.db" # SQLite file or PostgreSQL connection string
# API configuration (for remote content API)
api:
url: "" # Content API URL (leave empty to use local database)
key: "" # API authentication key
# Server configuration
server:
port: 8080 # HTTP server port
dev_mode: false # Enable development mode features
# Build configuration
build:
input: "./src" # Default input directory
output: "./dist" # Default output directory
# Global settings
site_id: "demo" # Site ID for content lookup
mock_content: false # Use mock content instead of real data
Configuration Precedence
- CLI flags (highest priority) -
./insertr --db ./custom.db serve - Environment variables -
INSERTR_DB_PATH=./custom.db - YAML config file -
insertr.yamlor--config custom.yaml - Smart defaults (lowest priority)
Environment Variables
INSERTR_DB_PATH- Database pathINSERTR_API_URL- Remote API URLINSERTR_API_KEY- API authentication keyINSERTR_SITE_ID- Site identifier
📖 Documentation
- Command Reference - Complete command and configuration guide
- Development Guide - Setup and contribution workflow
- Research Document - Strategic analysis and market positioning
- Integration Summary - Complete architecture overview
🎯 Market Position: "The Tailwind of CMS"
Tailwind CSS Approach:
- Utility-first classes:
class="text-lg font-bold" - Zero configuration, build-time optimization
- Framework agnostic, developer workflow integration
Insertr CMS Approach:
- Content-first classes:
class="insertr" - Zero configuration, build-time enhancement
- Framework agnostic, developer workflow integration
Shared Principles:
- Stay in markup, don't context switch
- Build-time optimization, zero runtime overhead
- Works with any framework or generator
- Developer experience focused
🚀 Production Deployment Workflow
Build-time enhancement + Runtime API for content management.
Production Architecture
The production workflow separates content management from site hosting:
1. Static Site Build → `insertr enhance` → Enhanced Static Files → Deploy to CDN/Host
2. Content Editing → `insertr serve` API → Database → Triggers rebuild
Two-Server Architecture
- Content API Server: Runs
insertr servefor content management and authentication - Static Site Host: Serves enhanced static files (CDN, GitHub Pages, Netlify, etc.)
Production Workflow
# 1. Build-time enhancement
./insertr enhance ./src --output ./dist --api https://cms.example.com
# 2. Deploy enhanced static files
rsync ./dist/ user@cdn:/var/www/site/
# 3. Run content API server (separate infrastructure)
./insertr serve --config production.yaml --db "postgresql://..."
Benefits
- ✅ Performance: Static files served from CDN with zero CMS overhead
- ✅ Scalability: Content API and static hosting scale independently
- ✅ Reliability: Static site works even if CMS server is down
- ✅ Security: Content editing isolated from public site hosting
- ✅ Framework Agnostic: Works with any static site generator or CDN
Development Server (Current Multi-Site Feature)
For development convenience, insertr serve --dev-mode can host multiple demo sites:
# insertr.yaml (development only)
server:
sites:
- site_id: "demo"
path: "./demos/demo_enhanced"
source_path: "./demos/demo"
auto_enhance: true
This serves sites at http://localhost:8080/sites/demo/ for testing the editor interface.
⚙️ Configuration
YAML Configuration (insertr.yaml)
# Global settings
dev_mode: false # Development mode features
# Database configuration
database:
path: "./insertr.db" # SQLite file or PostgreSQL connection string
# Server configuration (multi-site hosting)
server:
port: 8080 # HTTP server port
sites: # Server-hosted static sites
- site_id: "mysite"
path: "/var/www/mysite_enhanced" # Enhanced site output directory
source_path: "/var/www/mysite" # Original static site files
auto_enhance: true # Auto-enhance on startup and content changes
discovery:
enabled: false # Use explicit class="insertr" markings (true = auto-discover)
aggressive: false # Aggressive element discovery
# CLI enhancement configuration
cli:
site_id: "default" # Default site ID for CLI operations
output: "./dist" # Default output directory for enhanced files
inject_demo_gate: true # Inject demo editing gate if none exist
# API configuration (for CLI remote mode)
api:
url: "" # Content API URL (empty = use local database)
key: "" # API authentication key
# Authentication configuration
auth:
provider: "mock" # "mock" for development, "authentik" for production
jwt_secret: "" # JWT signing secret (auto-generated in dev mode)
# Authentik OIDC configuration (production)
oidc:
endpoint: "" # https://auth.example.com/application/o/insertr/
client_id: "" # insertr-client (OAuth2 client ID)
client_secret: "" # OAuth2 client secret (or use AUTHENTIK_CLIENT_SECRET env var)
Environment Variables
Core Configuration
INSERTR_DB_PATH- Database path overrideINSERTR_API_URL- Remote API URL overrideINSERTR_API_KEY- API authentication keyINSERTR_SITE_ID- Site identifier override
Authentication (Recommended for Production)
AUTHENTIK_CLIENT_SECRET- OIDC client secret (overrides config file)AUTHENTIK_ENDPOINT- OIDC endpoint URL (overrides config file)
Configuration Precedence
- CLI flags (highest priority)
- Environment variables
- YAML config file
- Smart defaults (lowest priority)
Database Options
# SQLite (development)
./insertr serve --db "./content.db"
# PostgreSQL (production)
./insertr serve --db "postgresql://user:pass@host:5432/insertr"
# Environment-based
export INSERTR_DB_PATH="postgresql://prod-host/insertr"
./insertr serve
🤝 Contributing
This project follows the "Tailwind philosophy" of developer-first design:
- Zero configuration - Markup-driven approach
- Build-time optimization - No runtime performance cost
- Framework agnostic - Works with any tech stack
- Developer friendly - Minimal cognitive overhead
See DEVELOPMENT.md for technical setup and contribution guidelines.
📄 License
MIT License - see LICENSE file for details.
Built with ❤️ for developers who want powerful editing without the complexity