- Remove complex style preservation system from editor - Simplify markdown conversion back to straightforward approach - Remove StyleContext class and style-aware conversion methods - Switch content type from 'html' back to 'markdown' for consistency - Clean up editor workflow to focus on core markdown editing - Remove ~500 lines of unnecessary style complexity This completes the UI unification cleanup by removing the overly complex style preservation system that was making the editor harder to maintain.
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)
- Rich editing interface loads on demand
- Click-to-edit any marked element
- Smart input types: text, textarea, link editor, markdown
- Changes saved to database
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
- Professional Editor: Modal forms, markdown support, authentication system
- Enterprise Authentication: Production-ready OIDC integration with Authentik, PKCE security
- Content Persistence: SQLite database with REST API, 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 (text/markdown/link)
- Deterministic IDs: Content-based ID generation for consistent developer experience
- Full Integration: Seamless development workflow with hot reload
🚀 Production Ready
- Deploy to cloud infrastructure
- Configure CDN for library assets
- Scale with PostgreSQL database
🛠️ 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 site: http://localhost:3000 (with live reload)
- API server: http://localhost:8080 (with content persistence)
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:
- ✅ Professional Editor - Modal forms, markdown support, authentication
- ✅ Real-Time Persistence - SQLite database with REST API
- ✅ Version Control - Complete edit history with user attribution and rollback
- ✅ Content Management - Create, read, update content via browser
- ✅ 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
# Production server with PostgreSQL
./insertr serve --db "postgresql://user:pass@host:5432/dbname"
# Development server with SQLite
./insertr serve --dev-mode --port 8080 --db ./dev.db
# Production server with custom config
./insertr --config ./production.yaml serve
# Use justfile shortcuts
just serve # Development server on :8080
just serve-prod port="443" # Production server
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) → Text input with character limits - Paragraphs (
p) → Markdown textarea for rich content - Links/Buttons (
a,button) → Text + URL fields - Containers (
div,section) → Expand to viable children
🔌 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
🏗️ Server-Hosted Static Sites (NEW)
Real-time content updates for server-hosted static sites with immediate deployment.
Overview
Insertr now supports hosting and enhancing static sites directly on the server. When content changes through the editor, static files are automatically updated in-place without requiring rebuilds or redeployment.
Key Benefits
- ✅ Immediate Updates: Content changes are live instantly
- ✅ Database Source of Truth: Content stored in database, not files
- ✅ No Rebuilds Required: Only content updates, templates stay the same
- ✅ Multi-Site Support: Host multiple enhanced sites on one server
- ✅ Automatic Backups: Original files backed up before enhancement
Workflow
1. Developer deploys static site → Server directory (e.g., /var/www/mysite)
2. Insertr enhances files → Adds editing capabilities + injects content
3. Editor makes changes → API updates database + triggers file enhancement
4. Changes immediately live → Visitors see updated content instantly
Configuration Example
# insertr.yaml
server:
port: 8080
sites:
- site_id: "mysite"
path: "/var/www/mysite"
domain: "mysite.example.com"
auto_enhance: true
- site_id: "blog"
path: "/var/www/blog"
domain: "blog.example.com"
auto_enhance: true
Quick Start
# 1. Configure sites in insertr.yaml
# 2. Start the server
./insertr serve --dev-mode
# 3. Your sites are automatically registered and enhanced
# 4. Content changes via editor immediately update static files
⚙️ Configuration
YAML Configuration (insertr.yaml)
# Database configuration
database:
path: "./insertr.db" # SQLite file path or PostgreSQL connection string
# Server configuration (with site hosting)
server:
port: 8080 # HTTP server port
sites: # Server-hosted static sites
- site_id: "demo"
path: "./demo-site"
domain: "localhost:3000"
auto_enhance: true
# API configuration (for remote content API)
api:
url: "" # Content API URL (leave empty to use local database)
key: "" # API authentication key
# Build configuration (for CLI enhancement)
build:
input: "./src" # Default input directory for enhancement
output: "./dist" # Default output directory for enhanced files
# 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/" # OIDC provider endpoint
client_id: "insertr-client" # OAuth2 client ID
client_secret: "your-secret" # Use AUTHENTIK_CLIENT_SECRET env var
# Global settings
site_id: "demo" # Default site ID for content lookup
mock_content: false # Use mock content instead of real data
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