# 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**
```html
<!-- 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 `id` attributes 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)
```yaml
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)
```yaml
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**

1. **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
   ```

2. **Create Application:**
   ```
   Applications → Applications → Create
   - Name: "Insertr CMS"
   - Slug: insertr
   - Provider: (select the provider created above)
   ```

3. **Configure Insertr:**
   ```yaml
   auth:
     provider: "authentik"
     oidc:
       endpoint: "https://auth.example.com/application/o/insertr/"
       client_id: "insertr-client"
       client_secret: "your-generated-secret"
   ```

4. **Environment Variables (Recommended):**
   ```bash
   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)**
```bash
# 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**
```bash
# Alternative using npm
npm run install:all
npm run build
npm run dev
```

### **Available Commands**
```bash
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

```bash
🔍 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 injection
- `insertr serve` - Runtime API server  
- Single binary handles both development and production workflows

### **Smart Loading Strategy**
```html
<!-- 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**
```bash
# 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**
```bash
# 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**
```bash
# 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**
```yaml
# .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**
```html
<!-- 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**
```bash
# 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**
```bash
# 🔥 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 `id` attributes 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)**
```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**
1. **CLI flags** (highest priority) - `./insertr --db ./custom.db serve`
2. **Environment variables** - `INSERTR_DB_PATH=./custom.db`
3. **YAML config file** - `insertr.yaml` or `--config custom.yaml`
4. **Smart defaults** (lowest priority)

### **Environment Variables**
- `INSERTR_DB_PATH` - Database path
- `INSERTR_API_URL` - Remote API URL  
- `INSERTR_API_KEY` - API authentication key
- `INSERTR_SITE_ID` - Site identifier

## 📖 Documentation

- **[Command Reference](COMMANDS.md)** - Complete command and configuration guide
- **[Development Guide](DEVELOPMENT.md)** - Setup and contribution workflow
- **[Research Document](RESEARCH.md)** - Strategic analysis and market positioning
- **[Integration Summary](INTEGRATION-SUMMARY.md)** - 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 serve` for content management and authentication
- **Static Site Host**: Serves enhanced static files (CDN, GitHub Pages, Netlify, etc.)

### **Production Workflow**
```bash
# 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:

```yaml
# 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)**
```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 override
- `INSERTR_API_URL` - Remote API URL override  
- `INSERTR_API_KEY` - API authentication key
- `INSERTR_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**
1. **CLI flags** (highest priority)
2. **Environment variables**
3. **YAML config file**
4. **Smart defaults** (lowest priority)

### **Database Options**
```bash
# 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:

1. **Zero configuration** - Markup-driven approach
2. **Build-time optimization** - No runtime performance cost
3. **Framework agnostic** - Works with any tech stack  
4. **Developer friendly** - Minimal cognitive overhead

See [DEVELOPMENT.md](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**