{"id":42473239,"url":"https://github.com/tsawler/dragon-cms","last_synced_at":"2026-01-28T10:10:41.718Z","repository":{"id":314162348,"uuid":"1038549667","full_name":"tsawler/dragon-cms","owner":"tsawler","description":"A simple, pure JavaScript drag-and-drop website builder with zero dependencies.","archived":false,"fork":false,"pushed_at":"2025-09-18T12:10:00.000Z","size":619,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-18T14:39:26.225Z","etag":null,"topics":["cms","drag-and-drop","website-builder"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tsawler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-15T12:10:10.000Z","updated_at":"2025-09-18T12:10:04.000Z","dependencies_parsed_at":"2025-09-11T00:30:21.244Z","dependency_job_id":null,"html_url":"https://github.com/tsawler/dragon-cms","commit_stats":null,"previous_names":["tsawler/dragon-cms"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/tsawler/dragon-cms","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsawler%2Fdragon-cms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsawler%2Fdragon-cms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsawler%2Fdragon-cms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsawler%2Fdragon-cms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tsawler","download_url":"https://codeload.github.com/tsawler/dragon-cms/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsawler%2Fdragon-cms/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28844011,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T07:39:25.367Z","status":"ssl_error","status_checked_at":"2026-01-28T07:39:24.487Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cms","drag-and-drop","website-builder"],"created_at":"2026-01-28T10:10:40.625Z","updated_at":"2026-01-28T10:10:41.702Z","avatar_url":"https://github.com/tsawler.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![DragonCMS](https://img.shields.io/badge/version-1.0.0-blue.svg)\n![Pure JavaScript](https://img.shields.io/badge/pure-javascript-yellow.svg)\n![No Dependencies](https://img.shields.io/badge/dependencies-none-green.svg)\n![License](https://img.shields.io/badge/license-MIT-purple.svg)\n\n# DragonCMS - Drag \u0026 Drop Website Builder\n\nA simple, pure JavaScript drag-and-drop website builder with zero dependencies. Create responsive websites visually by dragging sections, blocks, and snippets onto a canvas, with real-time editing, custom styling, and HTML code access. Features an organized tabbed sidebar for easy component access.\n\n**🚀 [Try the Live Demo](https://tsawler.github.io/dragon-cms/)**\n\nThis project is **still in development**, and has not yet reached a stable release. Most features seem to work, and all tests pass, but there are undoubtedly still some rough edges.\n\n## Table of Contents\n\n- [Features](#features)\n- [Quick Start](#quick-start)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Advanced Examples](#advanced-examples)\n- [API Reference](#api-reference)\n- [Customization](#customization)\n- [Section System](#section-system)\n- [Components](#components)\n- [Browser Support](#browser-support)\n- [Troubleshooting](#troubleshooting)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n\n### Core Capabilities\n- **Pure JavaScript** - No frameworks, no dependencies, just vanilla JavaScript\n- **Drag \u0026 Drop Interface** - Intuitive visual building with organized tabbed sidebar for sections, blocks, and snippets\n- **Responsive Design** - Built-in viewport preview modes (Desktop, Tablet, Mobile)\n- **Real-time Editing** - In-place text editing with rich formatting toolbar\n- **Custom Styling** - Visual style editor for every element\n- **HTML Access** - Direct HTML code editing for advanced users\n- **Undo/Redo** - Complete state history management\n- **Import/Export** - Save and load designs as JSON or HTML\n\n### Advanced Features\n- **Section System** - Full-width page sections with background control and content centering\n- **Block System** - Container-based layout with column management\n- **Rich Text Editing** - Full formatting toolbar with fonts, colors, alignment\n- **Image Management** - Upload, resize, and position images with visual handles\n- **Video Embedding** - YouTube and video file support\n- **Button Customization** - Style, URL, and target configuration\n- **Page Settings** - Custom CSS and JavaScript injection\n- **Background Images** - Upload and position background images for sections and blocks\n- **Column Resizing** - Visual column width adjustment\n- **Organized Interface** - Tabbed left sidebar with search/filtering for components\n\n### Developer Features\n- **Programmatic API** - Full control via JavaScript\n- **Custom Snippets** - Create your own components\n- **Event System** - Listen to editor mode changes and content modifications\n- **Callback System** - onChange and onRender callbacks for content tracking\n- **Font Customization** - Easy Google Fonts integration with copy-paste embed links\n- **Flexible Configuration** - Customize paths, assets, and behavior\n- **Save/Load Integration** - Connect to your backend API\n\n## Quick Start\n\n### Minimal Example\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n    \u003ctitle\u003eDragonCMS Example\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv id=\"editor\"\u003e\u003c/div\u003e\n\n    \u003c!-- Note that fonts.js, custom-blocks.js, and custom-snippets.js are all OPTIONAL. See the customization section, below. --\u003e\n    \u003cscript src=\"fonts.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"custom-blocks.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"custom-snippets.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"snippets.js\"\u003e\u003c/script\u003e\n    \u003cscript type=\"module\"\u003e\n        import dragon from './js/dragon.js';\n        \n        const editor = dragon.New({\n            containerId: 'editor',\n            cssPath: 'editor.css',\n            showCodeIcon: true\n        });\n    \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Installation\n\n### Option 1: Use Built Files (Recommended for Production)\n\n1. Download or clone the repository:\n```bash\ngit clone https://github.com/tsawler/dragon-cms.git\ncd dragon-cms\n```\n\n2. Install dependencies and build:\n```bash\nnpm install\nnpm run build\n```\n\n3. Use the built files from the `dist/` folder in your project:\n```html\n\u003c!-- For production (minified) --\u003e\n\u003c!-- Note that fonts.js, custom-blocks.js, and custom-snippets.js are all OPTIONAL. See the customization section, below. --\u003e\n\u003clink rel=\"stylesheet\" href=\"path/to/dist/editor.min.css\"\u003e\n\u003cscript src=\"path/to/dist/fonts.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/dist/custom-blocks.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/dist/custom-snippets.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/dist/snippets.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/dist/dragon.min.js\"\u003e\u003c/script\u003e\n\n\u003c!-- For development (unminified) --\u003e\n\u003clink rel=\"stylesheet\" href=\"path/to/dist/editor.css\"\u003e\n\u003cscript src=\"path/to/dist/fonts.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/dist/custom-blocks.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/dist/custom-snippets.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/dist/snippets.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/dist/dragon.js\"\u003e\u003c/script\u003e\n```\n\n### Option 2: Use Source Files (Development)\n\n1. Clone the repository:\n```bash\ngit clone https://github.com/tsawler/dragon-cms.git\ncd dragon-cms\n```\n\n2. Use the source files directly:\n```html\n\u003clink rel=\"stylesheet\" href=\"path/to/editor.css\"\u003e\n\u003c!-- Note that fonts.js, custom-blocks.js, and custom-snippets.js are all OPTIONAL. See the customization section, below. --\u003e\n\u003cscript src=\"path/to/fonts.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/custom-blocks.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/custom-snippets.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"path/to/snippets.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"module\" src=\"path/to/js/dragon.js\"\u003e\u003c/script\u003e\n```\n\n### File Structure\n\n```\ndragoncms/\n├── index.html              # Example implementation\n├── editor.css              # Editor styles\n├── snippets.js             # Block and snippet definitions\n├── fonts.js                # Google Fonts configuration\n├── custom-blocks.js        # Custom blocks configuration\n├── custom-snippets.js      # Custom snippets configuration\n├── assets/                 # Images and resources\n│   └── images/\n└── js/                     # Core JavaScript modules\n    ├── dragon.js           # Main entry point\n    ├── editor-core.js      # Core editor class\n    ├── modals.js           # Modal components\n    ├── formatting-toolbar.js\n    ├── snippet-panel.js\n    ├── state-history.js\n    ├── image-uploader.js\n    ├── column-resizer.js\n    └── [other modules]\n```\n\n## Development\n\n### Build System\n\nDragonCMS uses Rollup and Babel for building and bundling. The build system creates both development and production versions.\n\n#### Available Scripts\n\n```bash\n# Install dependencies\nnpm install\n\n# Build for production (creates dist/ folder)\nnpm run build\n\n# Serve built files on localhost:8000\nnpm run serve\n\n# Serve development files on localhost:8000  \nnpm run serve:dev\n\n# Run tests\nnpm test\n\n# Run tests in watch mode\nnpm run test:watch\n\n# Generate test coverage report\nnpm run test:coverage\n```\n\n#### Development Workflows\n\n**Fast Development (Recommended):**\n```bash\nnpm run serve:dev  # Serves source files directly with ES modules\n# Edit source files, refresh browser to see changes immediately\n```\n\n**Production Testing:**\n```bash\nnpm run build  # Build once\nnpm run serve  # Serve built files\n# Test the production build\n```\n\n**Testing:**\n```bash\nnpm test                # Run all tests once\nnpm run test:watch      # Run tests in watch mode (auto-rerun on file changes)\nnpm run test:coverage   # Generate test coverage report\n```\n\nDragonCMS includes a comprehensive test suite covering:\n- Core editor functionality\n- Font system and Google Fonts integration\n- Custom blocks system and configuration\n- Custom snippets system and configuration\n- State management and history\n- Modal components and UI interactions\n- Callback system\n- Error handling and edge cases\n\n#### Build Output\n\nThe build process creates:\n\n- `dist/dragon.js` - Development bundle (unminified)\n- `dist/dragon.min.js` - Production bundle (minified, console logs removed)\n- `dist/editor.css` - Editor styles (unminified)\n- `dist/editor.min.css` - Editor styles (minified)\n- `dist/snippets.js` - Components (unminified)\n- `dist/snippets.min.js` - Components (minified)\n- `dist/fonts.js` - Google Fonts configuration (copied from source)\n- `dist/custom-blocks.js` - Custom blocks configuration (copied from source)\n- `dist/custom-snippets.js` - Custom snippets configuration (copied from source)\n- `dist/index.html` - Example page (copied from source)\n- `dist/assets/` - Static assets (copied from source)\n\n#### Using Built Files\n\nFor production, use the minified bundles:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003ctitle\u003eMy Website Builder\u003c/title\u003e\n    \u003clink rel=\"stylesheet\" href=\"dist/editor.min.css\"\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv id=\"editor\"\u003e\u003c/div\u003e\n    \n    \u003cscript src=\"dist/snippets.min.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"dist/dragon.min.js\"\u003e\u003c/script\u003e\n    \u003cscript\u003e\n        // Note: Built version creates global 'dragon' object\n        const editor = dragon.New({\n            containerId: 'editor'\n        });\n    \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### Build Configuration\n\nThe build is configured through:\n\n- `rollup.config.js` - Rollup bundling configuration for JavaScript\n- `postcss.config.js` - PostCSS configuration for CSS minification\n- `.babelrc` - Babel transpilation settings (ES6+ to ES5)\n- `package.json` - Build scripts and dependencies\n\nTarget browsers: `\u003e 1%`, `last 2 versions`, `not dead`, `IE 11`\n\n**Minification:**\n- JavaScript: Terser (removes console logs in production)\n- CSS: cssnano (optimizes and minifies styles)\n\n## Basic Usage\n\n### Simple Implementation\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n    \u003ctitle\u003eMy Website Builder\u003c/title\u003e\n    \u003cstyle\u003e\n        body { margin: 0; padding: 0; }\n        #my-editor { width: 100vw; height: 100vh; }\n    \u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv id=\"my-editor\"\u003e\u003c/div\u003e\n    \n    \u003cscript src=\"fonts.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"custom-blocks.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"custom-snippets.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"snippets.js\"\u003e\u003c/script\u003e\n    \u003cscript type=\"module\" src=\"js/dragon.js\"\u003e\u003c/script\u003e\n    \n    \u003cscript\u003e\n        window.addEventListener('load', function() {\n            const editor = dragon.New({\n                containerId: 'my-editor',\n                cssPath: 'editor.css',\n                showCodeIcon: true,\n                snippetsPath: 'snippets.js',\n                assetsPath: 'assets/'\n            });\n        });\n    \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### With Existing Content\n\n```javascript\nconst editor = dragon.New({\n    containerId: 'my-editor',\n    cssPath: 'editor.css',\n    initialContent: `\n        \u003csection class=\"editor-section hero-section\"\u003e\n            \u003cdiv class=\"section-content\"\u003e\n                \u003cdiv class=\"editor-block\"\u003e\n                    \u003ch1\u003eWelcome to My Site\u003c/h1\u003e\n                    \u003cp\u003eThis content was loaded from HTML\u003c/p\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/section\u003e\n    `\n});\n```\n\n### Display Mode with Edit Button\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003ctitle\u003eWebsite with Edit Mode\u003c/title\u003e\n    \u003cstyle\u003e\n        #edit-btn {\n            position: fixed;\n            top: 20px;\n            right: 20px;\n            z-index: 10000;\n            background: #007bff;\n            color: white;\n            border: none;\n            border-radius: 50%;\n            width: 50px;\n            height: 50px;\n            font-size: 24px;\n            cursor: pointer;\n            box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n        }\n        #edit-btn.editing { display: none; }\n    \u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv id=\"content\"\u003e\u003c/div\u003e\n    \u003cbutton id=\"edit-btn\" title=\"Edit Page\"\u003e✏️\u003c/button\u003e\n    \n    \u003cscript src=\"fonts.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"custom-blocks.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"custom-snippets.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"snippets.js\"\u003e\u003c/script\u003e\n    \u003cscript type=\"module\" src=\"js/dragon.js\"\u003e\u003c/script\u003e\n    \n    \u003cscript\u003e\n        window.addEventListener('load', function() {\n            const editor = dragon.New({\n                containerId: 'content',\n                cssPath: 'editor.css'\n            });\n            \n            // Start in display mode\n            editor.setMode('display');\n            \n            // Edit button functionality\n            document.getElementById('edit-btn').addEventListener('click', function() {\n                editor.setMode('edit');\n                this.classList.add('editing');\n            });\n            \n            // Listen for mode changes\n            window.addEventListener('dragonModeChanged', function(e) {\n                document.getElementById('edit-btn').classList.toggle('editing', \n                    e.detail.mode === 'edit');\n            });\n        });\n    \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Advanced Examples\n\n### Save to Backend API\n\n```javascript\nconst editor = dragon.New({\n    containerId: 'editor',\n    cssPath: 'editor.css',\n    publishUrl: 'https://api.example.com/pages/save',\n    loadUrl: 'https://api.example.com/pages/load'\n});\n\n// Save button is automatically connected to publishUrl\n// Load button is automatically connected to loadUrl\n\n// Manual save\ndocument.getElementById('custom-save').addEventListener('click', async () =\u003e {\n    const content = editor.exportHTML();\n    \n    const response = await fetch('/api/save', {\n        method: 'POST',\n        headers: {'Content-Type': 'application/json'},\n        body: JSON.stringify({\n            html: content,\n            timestamp: new Date().toISOString()\n        })\n    });\n    \n    if (response.ok) {\n        alert('Saved successfully!');\n    }\n});\n```\n\n### Custom Snippet Creation\n\nAdd custom components to `snippets.js`:\n\n```javascript\n// In snippets.js\nwindow.getSnippets = function() {\n    return [\n        // Custom hero section\n        {\n            id: 'custom-hero',\n            name: 'Hero Section',\n            type: 'block',\n            preview: 'text',\n            html: `\n                \u003cdiv style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); \n                            padding: 80px 40px; text-align: center; color: white;\"\u003e\n                    \u003ch1 style=\"font-size: 48px; margin: 0;\"\u003eAmazing Hero Title\u003c/h1\u003e\n                    \u003cp style=\"font-size: 20px; margin: 20px 0;\"\u003eYour compelling subtitle here\u003c/p\u003e\n                    \u003cbutton style=\"background: white; color: #667eea; border: none; \n                                   padding: 15px 40px; font-size: 18px; \n                                   border-radius: 30px; cursor: pointer;\"\u003e\n                        Get Started\n                    \u003c/button\u003e\n                \u003c/div\u003e\n            `\n        },\n        \n        // Custom testimonial card\n        {\n            id: 'testimonial',\n            name: 'Testimonial',\n            type: 'snippet',\n            preview: 'text',\n            html: `\n                \u003cdiv style=\"background: white; padding: 30px; border-radius: 10px; \n                            box-shadow: 0 4px 6px rgba(0,0,0,0.1); margin: 20px 0;\"\u003e\n                    \u003cdiv style=\"display: flex; align-items: center; margin-bottom: 20px;\"\u003e\n                        \u003cimg src=\"https://via.placeholder.com/60\" \n                             style=\"border-radius: 50%; margin-right: 15px;\"\u003e\n                        \u003cdiv\u003e\n                            \u003ch4 style=\"margin: 0;\"\u003eCustomer Name\u003c/h4\u003e\n                            \u003cp style=\"margin: 0; color: #666;\"\u003eCEO, Company\u003c/p\u003e\n                        \u003c/div\u003e\n                    \u003c/div\u003e\n                    \u003cp style=\"font-style: italic; color: #333; line-height: 1.6;\"\u003e\n                        \"This is an amazing product that has transformed our business...\"\n                    \u003c/p\u003e\n                \u003c/div\u003e\n            `\n        },\n        \n        // Existing snippets...\n        ...window.getDefaultSnippets()\n    ];\n};\n```\n\n### Using Callbacks for Custom Behavior\n\n```javascript\nconst editor = dragon.New({\n    containerId: 'editor',\n    cssPath: 'editor.css',\n    onChange: (event) =\u003e {\n        // Auto-save on changes\n        if (event.type.includes('added') || event.type.includes('deleted')) {\n            autoSave(event.html);\n        }\n        \n        // Track analytics\n        analytics.track('editor_change', {\n            action: event.type,\n            timestamp: event.timestamp\n        });\n    },\n    onRender: (event) =\u003e {\n        // Apply custom enhancements to rendered elements\n        if (event.type === 'block') {\n            // Add animation classes\n            event.element.classList.add('fade-in');\n        }\n        \n        // Initialize third-party libraries\n        if (event.element.querySelector('.chart-container')) {\n            initializeCharts(event.element);\n        }\n    }\n});\n```\n\n### Programmatic Content Manipulation\n\n```javascript\nconst editor = dragon.New({\n    containerId: 'editor',\n    cssPath: 'editor.css'\n});\n\n// Switch modes programmatically\neditor.setMode('edit');  // or 'display'\n\n// Get current mode\nconst currentMode = editor.getMode();\n\n// Export HTML\nconst htmlContent = editor.exportHTML();\n\n// Load content dynamically\nasync function loadTemplate(templateId) {\n    const response = await fetch(`/templates/${templateId}.html`);\n    const html = await response.text();\n    \n    // Clear current content and load new\n    document.getElementById('editable-area').innerHTML = html;\n    \n    // Re-initialize editable elements\n    editor.makeExistingBlocksEditable();\n}\n\n// Listen for mode changes\nwindow.addEventListener('dragonModeChanged', (e) =\u003e {\n    console.log('Mode changed to:', e.detail.mode);\n    \n    if (e.detail.mode === 'display') {\n        // Auto-save when switching to display mode\n        autoSave();\n    }\n});\n```\n\n## API Reference\n\n### dragon.New(options)\n\nCreates a new DragonCMS editor instance.\n\n#### Parameters\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `containerId` | string | `'dragon-editor'` | ID of the container element |\n| `cssPath` | string | `'editor.css'` | Path to the editor CSS file |\n| `showCodeIcon` | boolean | `true` | Show HTML editor icon |\n| `snippetsPath` | string | `'snippets.js'` | Path to snippets definition file |\n| `assetsPath` | string | `'assets/'` | Path to assets folder |\n| `initialContent` | string | `null` | Initial HTML content to load |\n| `publishUrl` | string | `null` | API endpoint for saving |\n| `loadUrl` | string | `null` | API endpoint for loading |\n| `onChange` | function | `null` | Callback when content changes (add/delete/move) |\n| `onRender` | function | `null` | Callback when element is rendered |\n\n#### Returns\nAn `Editor` instance with the following methods:\n\n### Editor Methods\n\n#### editor.setMode(mode)\nSets the editor mode.\n\n```javascript\neditor.setMode('edit');   // Enable editing mode\neditor.setMode('display'); // Enable display mode\n```\n\n#### editor.getMode()\nReturns the current mode ('edit' or 'display').\n\n```javascript\nconst mode = editor.getMode();\nconsole.log(mode); // 'edit' or 'display'\n```\n\n#### editor.exportHTML()\nExports the current content as HTML.\n\n```javascript\nconst html = editor.exportHTML();\n// Returns complete HTML with styles\n```\n\n#### editor.exportData()\nExports the current state as JSON.\n\n```javascript\nconst data = editor.exportData();\n// Returns: { html: '...', pageSettings: {...} }\n```\n\n#### editor.makeExistingBlocksEditable()\nRe-initializes editing capabilities for dynamically loaded content.\n\n```javascript\n// After loading new HTML content\ndocument.getElementById('editable-area').innerHTML = newContent;\neditor.makeExistingBlocksEditable();\n```\n\n### Events\n\n#### dragonModeChanged\nFired when the editor mode changes.\n\n```javascript\nwindow.addEventListener('dragonModeChanged', (e) =\u003e {\n    console.log('New mode:', e.detail.mode);\n    // e.detail.mode is 'edit' or 'display'\n});\n```\n\n### Callbacks\n\n#### onChange Callback\nTriggered when content changes (sections/blocks/snippets added, deleted, or moved).\n\n```javascript\nconst editor = dragon.New({\n    containerId: 'editor',\n    onChange: (event) =\u003e {\n        console.log('Content changed:', event);\n        // event.type: 'section-added', 'section-deleted', 'section-moved',\n        //             'block-added', 'block-deleted', 'block-moved',\n        //             'snippet-added', 'snippet-deleted', 'snippet-moved'\n        // event.element: The affected element (null for deletions)\n        // event.html: Current HTML content of the editor\n        // event.timestamp: ISO timestamp of the change\n    }\n});\n```\n\n#### onRender Callback\nTriggered when a new section, block, or snippet is rendered.\n\n```javascript\nconst editor = dragon.New({\n    containerId: 'editor',\n    onRender: (event) =\u003e {\n        console.log('Element rendered:', event);\n        // event.type: 'section', 'block', or 'snippet'\n        // event.element: The rendered DOM element\n        // event.timestamp: ISO timestamp of the render\n        \n        // Example: Add custom initialization\n        if (event.type === 'section') {\n            // Initialize any custom JavaScript for the section\n            initializeCustomSection(event.element);\n        }\n    }\n});\n```\n\n## Customization\n\n### Font Customization\n\nDragonCMS supports easy Google Fonts integration through the `fonts.js` configuration file. Users can simply copy and paste Google Fonts embed links to add custom typography to the formatting toolbar.\n\n#### Adding Google Fonts\n\n1. Visit [fonts.google.com](https://fonts.google.com) and select your desired fonts\n2. Copy the `\u003clink\u003e` embed code provided by Google Fonts\n3. Add it to the `googleFontLinks` array in `fonts.js`\n\n```javascript\n// In fonts.js\nwindow.DragonFonts = {\n    // Default system fonts (always available)\n    systemFonts: [\n        { name: \"Arial\", family: \"Arial, sans-serif\" },\n        { name: \"Georgia\", family: \"Georgia, serif\" },\n        // ... other system fonts\n    ],\n\n    // Google Fonts - just paste embed links here\n    googleFontLinks: [\n        '\u003clink href=\"https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700\u0026display=swap\" rel=\"stylesheet\"\u003e',\n        '\u003clink href=\"https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700\u0026display=swap\" rel=\"stylesheet\"\u003e',\n        '\u003clink href=\"https://fonts.googleapis.com/css2?family=Fira+Code:wght@400\u0026display=swap\" rel=\"stylesheet\"\u003e',\n        // Add your fonts here\n    ]\n};\n```\n\n#### Supported Font Formats\n\nThe font parser automatically handles various Google Fonts URL formats:\n\n```javascript\n// Simple single font\n'\u003clink href=\"https://fonts.googleapis.com/css2?family=Open+Sans:wght@400\u0026display=swap\" rel=\"stylesheet\"\u003e'\n\n// Multiple weights\n'\u003clink href=\"https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700\u0026display=swap\" rel=\"stylesheet\"\u003e'\n\n// Multiple fonts in one URL\n'\u003clink href=\"https://fonts.googleapis.com/css2?family=Roboto:wght@400\u0026family=Open+Sans:wght@300;400\u0026display=swap\" rel=\"stylesheet\"\u003e'\n\n// Complex variations with italics\n'\u003clink href=\"https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400;1,400\u0026display=swap\" rel=\"stylesheet\"\u003e'\n```\n\n#### Font Fallback Assignment\n\nThe system automatically assigns appropriate fallbacks:\n\n- **Serif fonts** (Playfair Display, Merriweather, etc.) → `serif`\n- **Monospace fonts** (Fira Code, Source Code Pro, etc.) → `monospace` \n- **All other fonts** → `sans-serif`\n\n#### Custom Font Integration\n\nFor production builds, ensure `fonts.js` is loaded before the Dragon library:\n\n```html\n\u003c!-- Development --\u003e\n\u003cscript src=\"fonts.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"snippets.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"module\" src=\"js/dragon.js\"\u003e\u003c/script\u003e\n\n\u003c!-- Production --\u003e\n\u003cscript src=\"fonts.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"snippets.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"dragon.min.js\"\u003e\u003c/script\u003e\n```\n\n#### Font Loading\n\nGoogle Fonts are automatically loaded when the editor initializes. The system:\n\n1. Parses font names from embed links\n2. Injects `\u003clink\u003e` tags into the document head\n3. Adds fonts to the formatting toolbar dropdown\n4. Prevents duplicate font loading\n\n#### Example: Adding Popular Fonts\n\n```javascript\n// Popular Google Fonts examples\ngoogleFontLinks: [\n    // Sans-serif fonts\n    '\u003clink href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700\u0026display=swap\" rel=\"stylesheet\"\u003e',\n    '\u003clink href=\"https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700\u0026display=swap\" rel=\"stylesheet\"\u003e',\n    '\u003clink href=\"https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700\u0026display=swap\" rel=\"stylesheet\"\u003e',\n    \n    // Serif fonts\n    '\u003clink href=\"https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700\u0026display=swap\" rel=\"stylesheet\"\u003e',\n    '\u003clink href=\"https://fonts.googleapis.com/css2?family=Merriweather:wght@300;400;700\u0026display=swap\" rel=\"stylesheet\"\u003e',\n    \n    // Monospace fonts\n    '\u003clink href=\"https://fonts.googleapis.com/css2?family=Fira+Code:wght@400\u0026display=swap\" rel=\"stylesheet\"\u003e',\n    '\u003clink href=\"https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400\u0026display=swap\" rel=\"stylesheet\"\u003e'\n]\n```\n\n### Custom Blocks\n\nDragonCMS supports user-defined custom blocks through the `custom-blocks.js` configuration file. Custom blocks are container elements that can hold other content and appear in the editor's block panel alongside default blocks.\n\n#### Adding Custom Blocks\n\nCustom blocks are defined in the `custom-blocks.js` file. **Simply add your blocks to the `customBlocks` array - that's all you need to do!**\n\n```javascript\n// In custom-blocks.js - This is ALL you need to edit:\nwindow.DragonBlocks = {\n    customBlocks: [\n        // Just add your blocks here:\n        {\n            id: 'custom-card-block',\n            name: 'Card Block',\n            type: 'block',\n            preview: 'text',\n            description: 'A card-style container with shadow and padding',\n            category: 'layout',\n            html: `\n                \u003cdiv class=\"editor-block card-block\" style=\"\n                    background: white;\n                    border-radius: 12px;\n                    padding: 30px;\n                    margin: 20px 0;\n                    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n                    border: 1px solid #e5e7eb;\n                \"\u003e\n                    \u003cdiv class=\"card-content\"\u003e\n                        \u003ch3\u003eCard Title\u003c/h3\u003e\n                        \u003cp\u003eThis is a custom card block. Add your content here.\u003c/p\u003e\n                    \u003c/div\u003e\n                \u003c/div\u003e\n            `\n        },\n        // Add more blocks here...\n    ]\n    \n    // Note: Management methods are automatically provided by DragonCMS\n    // You don't need to implement these - they're built-in!\n};\n```\n\n**That's it!** Include the script tag and your blocks automatically appear:\n\n```html\n\u003cscript src=\"custom-blocks.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"custom-snippets.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"snippets.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"module\" src=\"js/dragon.js\"\u003e\u003c/script\u003e\n```\n\n#### Block Configuration Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `id` | string | ✓ | Unique identifier for the block |\n| `name` | string | ✓ | Display name in the editor panel |\n| `type` | string | ✓ | Must be 'block' for container elements |\n| `html` | string | ✓ | The HTML structure of the block |\n| `preview` | string | ✓ | 'text' or 'image' - how to display in panel |\n| `description` | string | ✗ | Tooltip description |\n| `category` | string | ✗ | Category for organization (e.g., 'layout', 'marketing') |\n| `previewImage` | string | ✗ | **Required if preview='image'** - See preview options below |\n\n#### Preview Options\n\n**Text Preview (`preview: 'text'`):**\n- Shows the block name as text in the editor panel\n- Simple and straightforward - no additional configuration needed\n- Best for most use cases\n\n**Image Preview (`preview: 'image'`):**\n- Shows a custom icon/image in the editor panel instead of text\n- Requires `previewImage` property with one of these formats:\n\n**Supported Image Formats:**\n- **File path**: `'./assets/my-preview.png'` (PNG, JPG, WebP, GIF, SVG files)\n- **Absolute URL**: `'https://example.com/preview.jpg'`\n- **Data URL**: `'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...'`\n- **SVG data URL**: `svgToDataUrl('\u003csvg\u003e...\u003c/svg\u003e')` (for inline SVG)\n\n**Example with Image Preview:**\n```javascript\n{\n    id: 'hero-block',\n    name: 'Hero Section',\n    type: 'block',\n    preview: 'image',\n    previewImage: './assets/hero-icon.png',  // Simple file path\n    html: '\u003cdiv class=\"editor-block hero\"\u003eHero content\u003c/div\u003e'\n}\n```\n\n**Example with Text Preview:**\n```javascript\n{\n    id: 'card-block',\n    name: 'Card Block',\n    type: 'block',\n    preview: 'text',  // No previewImage needed\n    html: '\u003cdiv class=\"editor-block card\"\u003eCard content\u003c/div\u003e'\n}\n```\n\n#### Built-in Custom Blocks\n\nDragonCMS includes several pre-configured custom blocks:\n\n**Layout Blocks:**\n- **Card Block** - Card-style container with shadow and padding\n- **Feature Grid** - Multi-column grid layout for features\n\n**Marketing Blocks:**\n- **CTA Section** - Call-to-action container with centered content\n- **Testimonial Block** - Customer testimonial with avatar layout\n- **Pricing Table** - Multi-tier pricing comparison\n\n**Content Blocks:**\n- Various content-focused containers with predefined styling\n\n#### Creating Custom Blocks\n\n1. **Basic Block Structure:**\n   ```javascript\n   {\n       id: 'my-custom-block',\n       name: 'My Custom Block',\n       type: 'block',\n       preview: 'text',\n       category: 'layout',\n       html: `\n           \u003cdiv class=\"editor-block my-custom-block\"\u003e\n               \u003ch2\u003eCustom Block Title\u003c/h2\u003e\n               \u003cp\u003eAdd your content here\u003c/p\u003e\n           \u003c/div\u003e\n       `\n   }\n   ```\n\n2. **Advanced Block with Styling:**\n   ```javascript\n   {\n       id: 'hero-section-block',\n       name: 'Hero Section',\n       type: 'block',\n       preview: 'text',\n       description: 'Full-width hero section with gradient background',\n       category: 'marketing',\n       html: `\n           \u003cdiv class=\"editor-block hero-section\" style=\"\n               background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n               color: white;\n               text-align: center;\n               padding: 80px 20px;\n               min-height: 400px;\n               display: flex;\n               align-items: center;\n               justify-content: center;\n           \"\u003e\n               \u003cdiv\u003e\n                   \u003ch1 style=\"font-size: 48px; margin-bottom: 20px;\"\u003eHero Title\u003c/h1\u003e\n                   \u003cp style=\"font-size: 20px; margin-bottom: 30px;\"\u003eYour compelling message here\u003c/p\u003e\n                   \u003cbutton style=\"\n                       background: white;\n                       color: #667eea;\n                       border: none;\n                       padding: 15px 40px;\n                       font-size: 18px;\n                       border-radius: 30px;\n                       cursor: pointer;\n                   \"\u003eGet Started\u003c/button\u003e\n               \u003c/div\u003e\n           \u003c/div\u003e\n       `\n   }\n   ```\n\n#### Block Categories\n\nOrganize blocks using categories:\n\n- **layout** - Structural containers and layout blocks\n- **marketing** - CTA, testimonial, pricing blocks\n- **content** - Content-focused containers\n- **media** - Image galleries, video containers\n- **custom** - User-specific blocks\n\n#### Integration with Editor\n\nCustom blocks automatically integrate with the editor:\n\n- **Block Panel** - Appear in blocks tab (🧱) with filtering support\n- **Drag \u0026 Drop** - Full drag and drop functionality\n- **Block Settings** - Access to gear icon settings (layout, columns, background)\n- **Content Editing** - All text elements are editable\n- **Column Management** - Support for adding/removing columns\n- **Responsive Design** - Blocks adapt to tablet/mobile preview modes\n\n#### Block Loading\n\nFor production builds, ensure both custom files are loaded before the Dragon library:\n\n```html\n\u003c!-- Development --\u003e\n\u003cscript src=\"fonts.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"custom-blocks.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"custom-snippets.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"snippets.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"module\" src=\"js/dragon.js\"\u003e\u003c/script\u003e\n\n\u003c!-- Production --\u003e\n\u003cscript src=\"fonts.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"custom-blocks.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"custom-snippets.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"snippets.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"dragon.min.js\"\u003e\u003c/script\u003e\n```\n\n#### Dynamic Block Management (Advanced)\n\n**Note: These methods are automatically provided by DragonCMS - you don't need to implement them!** They're available for advanced runtime management:\n\n```javascript\n// Built-in methods available on window.DragonBlocks:\n\n// Get all custom blocks\nconst blocks = window.DragonBlocks.getAllCustomBlocks();\n\n// Get blocks by category\nconst layoutBlocks = window.DragonBlocks.getBlocksByCategory('layout');\n\n// Get specific block\nconst cardBlock = window.DragonBlocks.getBlockById('custom-card-block');\n\n// Get all available categories\nconst categories = window.DragonBlocks.getCategories();\n\n// Add new block dynamically (advanced usage)\nconst success = window.DragonBlocks.addCustomBlock({\n    id: 'new-block',\n    name: 'New Block',\n    type: 'block',\n    html: '\u003cdiv class=\"editor-block\"\u003eNew content\u003c/div\u003e'\n});\n```\n\n**For most users: Just edit the `customBlocks` array in custom-blocks.js - these methods are only needed for advanced programmatic manipulation.**\n\n#### Best Practices\n\n1. **Use semantic HTML structure** with proper accessibility\n2. **Include responsive design patterns** (flexbox, grid, percentages)\n3. **Provide meaningful descriptions** for better user experience\n4. **Use consistent naming conventions** for IDs and classes\n5. **Test blocks across devices** using preview modes\n6. **Avoid inline scripts** for security (use external initialization if needed)\n7. **Use appropriate categories** for better organization\n\n### Custom Snippets\n\nDragonCMS supports user-defined custom snippets through the `custom-snippets.js` configuration file. Custom snippets are content elements like text, images, buttons, or custom HTML components that can be dragged into blocks.\n\n#### Adding Custom Snippets\n\nCustom snippets are defined in the `custom-snippets.js` file. **Simply add your snippets to the `customSnippets` array - that's all you need to do!**\n\n```javascript\n// In custom-snippets.js - This is ALL you need to edit:\nwindow.DragonSnippets = {\n    customSnippets: [\n        // Just add your snippets here:\n        {\n            id: 'custom-alert-box',\n            name: 'Alert Box',\n            type: 'snippet',\n            snippetType: 'content',\n            preview: 'text',\n            description: 'A styled alert box with icon and message',\n            category: 'content',\n            html: `\n                \u003cdiv class=\"alert-box\" style=\"\n                    background: #dbeafe;\n                    border: 1px solid #3b82f6;\n                    border-radius: 8px;\n                    padding: 16px;\n                    margin: 16px 0;\n                \"\u003e\n                    \u003cp\u003eThis is an important message for your visitors.\u003c/p\u003e\n                \u003c/div\u003e\n            `\n        },\n        // Add more snippets here...\n    ]\n    \n    // Note: Management methods are automatically provided by DragonCMS\n    // You don't need to implement these - they're built-in!\n};\n```\n\n**That's it!** Include the script tag and your snippets automatically appear in the \"Custom Snippets\" section:\n\n```html\n\u003cscript src=\"custom-blocks.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"custom-snippets.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"snippets.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"module\" src=\"js/dragon.js\"\u003e\u003c/script\u003e\n```\n\n#### Snippet Configuration Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `id` | string | ✓ | Unique identifier for the snippet |\n| `name` | string | ✓ | Display name in the editor panel |\n| `type` | string | ✓ | Must be 'snippet' for content elements |\n| `html` | string | ✓ | The HTML structure of the snippet |\n| `preview` | string | ✓ | 'text' or 'image' - how to display in panel |\n| `description` | string | ✗ | Tooltip description |\n| `category` | string | ✗ | Category for organization (e.g., 'content', 'marketing') |\n| `snippetType` | string | ✗ | Sub-type (e.g., 'text', 'media', 'button') |\n| `previewImage` | string | ✗ | **Required if preview='image'** - See preview options below |\n\n#### Preview Options\n\n**Text Preview (`preview: 'text'`):**\n- Shows the snippet name as text in the editor panel\n- Simple and straightforward - no additional configuration needed\n- Best for most use cases\n\n**Image Preview (`preview: 'image'`):**\n- Shows a custom icon/image in the editor panel instead of text\n- Requires `previewImage` property with one of these formats:\n\n**Supported Image Formats:**\n- **File path**: `'./assets/my-preview.png'` (PNG, JPG, WebP, GIF, SVG files)\n- **Absolute URL**: `'https://example.com/preview.jpg'`\n- **Data URL**: `'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...'`\n- **SVG data URL**: `svgToDataUrl('\u003csvg\u003e...\u003c/svg\u003e')` (for inline SVG)\n\n**Example with Image Preview:**\n```javascript\n{\n    id: 'testimonial-card',\n    name: 'Testimonial Card',\n    type: 'snippet',\n    preview: 'image',\n    previewImage: './assets/testimonial-icon.svg',  // Simple file path\n    html: '\u003cdiv class=\"testimonial\"\u003eCustomer testimonial content\u003c/div\u003e'\n}\n```\n\n**Example with Text Preview:**\n```javascript\n{\n    id: 'alert-box',\n    name: 'Alert Box',\n    type: 'snippet',\n    preview: 'text',  // No previewImage needed\n    html: '\u003cdiv class=\"alert\"\u003eAlert message content\u003c/div\u003e'\n}\n```\n\n#### Built-in Custom Snippets\n\nDragonCMS includes several pre-configured custom snippets:\n\n**Content Snippets:**\n- **Alert Box** - Styled notification box with icon and message\n- **Feature Highlight** - Feature showcase with icon and description\n- **Code Block** - Syntax-highlighted code display with terminal styling\n\n**Marketing Snippets:**\n- **Testimonial Card** - Customer testimonial with avatar and star rating\n- **Stat Counter** - Statistics display with large number and description\n\n#### Creating Custom Snippets\n\n1. **Basic Snippet Structure:**\n   ```javascript\n   {\n       id: 'my-custom-snippet',\n       name: 'My Custom Snippet',\n       type: 'snippet',\n       preview: 'text',\n       category: 'content',\n       html: `\n           \u003cdiv class=\"my-custom-snippet\"\u003e\n               \u003ch3\u003eCustom Content\u003c/h3\u003e\n               \u003cp\u003eAdd your content here\u003c/p\u003e\n           \u003c/div\u003e\n       `\n   }\n   ```\n\n2. **Advanced Snippet with Rich Styling:**\n   ```javascript\n   {\n       id: 'pricing-card',\n       name: 'Pricing Card',\n       type: 'snippet',\n       snippetType: 'marketing',\n       preview: 'text',\n       description: 'A pricing card with features and call-to-action',\n       category: 'marketing',\n       html: `\n           \u003cdiv class=\"pricing-card\" style=\"\n               background: white;\n               border: 2px solid #e5e7eb;\n               border-radius: 12px;\n               padding: 32px;\n               text-align: center;\n               max-width: 300px;\n               margin: 20px auto;\n               box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n           \"\u003e\n               \u003ch3 style=\"color: #1f2937; margin: 0 0 16px 0;\"\u003ePro Plan\u003c/h3\u003e\n               \u003cdiv style=\"font-size: 48px; font-weight: 700; color: #3b82f6; margin-bottom: 16px;\"\u003e\n                   $29\u003cspan style=\"font-size: 18px; color: #6b7280;\"\u003e/month\u003c/span\u003e\n               \u003c/div\u003e\n               \u003cul style=\"list-style: none; padding: 0; margin: 0 0 24px 0; text-align: left;\"\u003e\n                   \u003cli style=\"padding: 8px 0; color: #374151;\"\u003e✓ All features included\u003c/li\u003e\n                   \u003cli style=\"padding: 8px 0; color: #374151;\"\u003e✓ Priority support\u003c/li\u003e\n                   \u003cli style=\"padding: 8px 0; color: #374151;\"\u003e✓ Advanced analytics\u003c/li\u003e\n               \u003c/ul\u003e\n               \u003cbutton style=\"\n                   background: #3b82f6;\n                   color: white;\n                   border: none;\n                   border-radius: 8px;\n                   padding: 12px 32px;\n                   font-size: 16px;\n                   font-weight: 600;\n                   cursor: pointer;\n                   width: 100%;\n               \"\u003e\n                   Get Started\n               \u003c/button\u003e\n           \u003c/div\u003e\n       `\n   }\n   ```\n\n#### Snippet Categories\n\nOrganize snippets using categories:\n\n- **content** - Text elements, alerts, highlights\n- **marketing** - Testimonials, pricing cards, CTAs\n- **media** - Image galleries, video players\n- **navigation** - Breadcrumbs, pagination, menus\n- **social** - Social media widgets, share buttons\n\n#### Integration with Editor\n\nCustom snippets automatically integrate with the editor:\n\n- **Snippet Panel** - Appear in snippets tab (⚡) with filtering support\n- **Drag \u0026 Drop** - Full drag and drop functionality into blocks\n- **Text Editing** - All text elements become editable when dropped\n- **Formatting Toolbar** - Rich text formatting available for text content\n- **Content Flexibility** - Can be placed in any block or column\n\n#### Dynamic Snippet Management (Advanced)\n\n**Note: These methods are automatically provided by DragonCMS - you don't need to implement them!** They're available for advanced runtime management:\n\n```javascript\n// Built-in methods available on window.DragonSnippets:\n\n// Get all custom snippets\nconst snippets = window.DragonSnippets.getAllCustomSnippets();\n\n// Get snippets by category\nconst contentSnippets = window.DragonSnippets.getSnippetsByCategory('content');\n\n// Get specific snippet\nconst alertBox = window.DragonSnippets.getSnippetById('custom-alert-box');\n\n// Get all available categories\nconst categories = window.DragonSnippets.getCategories();\n\n// Add new snippet dynamically (advanced usage)\nconst success = window.DragonSnippets.addCustomSnippet({\n    id: 'new-snippet',\n    name: 'New Snippet',\n    type: 'snippet',\n    html: '\u003cdiv class=\"new-snippet\"\u003eNew content\u003c/div\u003e'\n});\n```\n\n**For most users: Just edit the `customSnippets` array in custom-snippets.js - these methods are only needed for advanced programmatic manipulation.**\n\n#### Best Practices\n\n1. **Keep snippets focused** on single components or content types\n2. **Use inline styles** for better portability and self-containment\n3. **Provide clear descriptions** to help users understand the purpose\n4. **Test across devices** to ensure responsive behavior\n5. **Use semantic HTML** with proper accessibility attributes\n6. **Avoid complex JavaScript** - keep snippets simple and reliable\n7. **Category organization** helps users find snippets quickly\n\n### Custom Styles\n\nOverride default styles by adding CSS after the editor.css:\n\n```css\n/* Custom theme */\n.dragon-editor .editor-header {\n    background: linear-gradient(90deg, #4a90e2, #7b68ee);\n}\n\n.dragon-editor .btn-primary {\n    background: #7b68ee;\n    border-color: #7b68ee;\n}\n\n.dragon-editor .editor-block {\n    border-color: #e0e0e0;\n}\n\n/* Custom snippet styles */\n.dragon-editor .custom-snippet {\n    background: #f8f9fa;\n    padding: 20px;\n    border-left: 4px solid #7b68ee;\n}\n```\n\n### Custom Snippets\n\nCreate rich, interactive snippets:\n\n```javascript\n// Advanced snippet with JavaScript\n{\n    id: 'countdown-timer',\n    name: 'Countdown Timer',\n    type: 'snippet',\n    preview: 'text',\n    html: `\n        \u003cdiv class=\"countdown-widget\" data-target=\"2024-12-31T23:59:59\"\u003e\n            \u003cdiv style=\"text-align: center; padding: 40px; background: #f0f0f0; border-radius: 10px;\"\u003e\n                \u003ch2\u003eCountdown to New Year\u003c/h2\u003e\n                \u003cdiv class=\"countdown-display\" style=\"font-size: 36px; font-weight: bold;\"\u003e\n                    \u003cspan class=\"days\"\u003e00\u003c/span\u003e days\n                    \u003cspan class=\"hours\"\u003e00\u003c/span\u003e hours\n                    \u003cspan class=\"minutes\"\u003e00\u003c/span\u003e minutes\n                    \u003cspan class=\"seconds\"\u003e00\u003c/span\u003e seconds\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    `,\n    script: `\n        document.querySelectorAll('.countdown-widget').forEach(widget =\u003e {\n            const target = new Date(widget.dataset.target);\n            \n            setInterval(() =\u003e {\n                const now = new Date();\n                const diff = target - now;\n                \n                const days = Math.floor(diff / (1000 * 60 * 60 * 24));\n                const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));\n                const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));\n                const seconds = Math.floor((diff % (1000 * 60)) / 1000);\n                \n                widget.querySelector('.days').textContent = days;\n                widget.querySelector('.hours').textContent = hours;\n                widget.querySelector('.minutes').textContent = minutes;\n                widget.querySelector('.seconds').textContent = seconds;\n            }, 1000);\n        });\n    `\n}\n```\n\n### Custom Block Templates\n\n```javascript\n// Multi-column responsive block\n{\n    id: 'three-column-block',\n    name: 'Three Column Layout',\n    type: 'block',\n    preview: 'text',\n    html: `\n        \u003cdiv class=\"editor-block three-columns\" style=\"display: flex; gap: 20px; padding: 40px;\"\u003e\n            \u003cdiv class=\"column\" style=\"flex: 1; background: #f9f9f9; padding: 20px; border-radius: 8px;\"\u003e\n                \u003ch3\u003eColumn 1\u003c/h3\u003e\n                \u003cp\u003eContent for the first column\u003c/p\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"column\" style=\"flex: 1; background: #f9f9f9; padding: 20px; border-radius: 8px;\"\u003e\n                \u003ch3\u003eColumn 2\u003c/h3\u003e\n                \u003cp\u003eContent for the second column\u003c/p\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"column\" style=\"flex: 1; background: #f9f9f9; padding: 20px; border-radius: 8px;\"\u003e\n                \u003ch3\u003eColumn 3\u003c/h3\u003e\n                \u003cp\u003eContent for the third column\u003c/p\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    `\n}\n```\n\n## Section System\n\nDragonCMS uses a hierarchical 3-level content structure: **Sections \u003e Blocks \u003e Snippets**. This provides better organization and enables modern full-width designs.\n\n### Content Hierarchy\n\n```\nSection (Full-width page regions)\n├── Block (Content containers with columns)\n│   ├── Snippet (Text, images, buttons)\n│   ├── Snippet\n│   └── ...\n├── Block\n└── ...\n```\n\n### Sections\n\nSections are full-width page regions that span the entire viewport. They're perfect for creating modern website layouts with distinct page areas.\n\n**Key Features:**\n- **Full viewport width** - True edge-to-edge spanning\n- **Background control** - Colors, gradients, and images\n- **Content centering** - Inner content stays centered with configurable max-width\n- **Semantic structure** - Proper HTML5 `\u003csection\u003e` elements\n\n**Section Settings (⚙️ icon):**\n- **Layout Tab:**\n  - Section width (usually 100% for full-width)\n  - Content max-width (centers content within section)\n  - Padding (vertical and horizontal spacing)\n  - Minimum height (for consistent sizing)\n\n- **Background Tab:**\n  - Background color with color picker\n  - Background image upload with browse button\n  - Background size (cover, contain, auto, stretch)\n  - Background position (center, top, bottom, etc.)\n\n### Blocks within Sections\n\nBlocks live inside sections and provide structured content areas:\n\n- **Drag blocks into section content areas** to organize content\n- **Column management** - Add/remove columns within blocks\n- **Responsive behavior** - Columns stack on tablet/mobile\n- **Block settings** available via gear icon\n\n### Working with Sections\n\n**Creating Sections:**\n1. Click the sections icon (📋) in the left sidebar to open the sections panel\n2. Drag a section from the panel to the main editor area\n3. Choose from: Hero, Content, Features, CTA, Footer, or Empty sections\n\n**Adding Content to Sections:**\n1. Click the blocks icon (🧱) in the left sidebar to access blocks\n2. Drag blocks into the section's content area\n3. Click the snippets icon (⚡) for content elements\n4. Drag snippets into blocks within sections\n5. Use the hierarchical structure to organize content logically\n\n**Section vs Block Backgrounds:**\n- **Section backgrounds** span the full viewport width\n- **Block backgrounds** only cover the block content area\n- Use sections for page-wide visual themes\n\n### Example Section Structure\n\n```html\n\u003c!-- Hero Section (full-width) --\u003e\n\u003csection class=\"editor-section hero-section\"\u003e\n  \u003cdiv class=\"section-content\"\u003e \u003c!-- Centered container --\u003e\n    \u003cdiv class=\"editor-block\"\u003e   \u003c!-- Content block --\u003e\n      \u003ch1\u003eHero Title\u003c/h1\u003e        \u003c!-- Snippet --\u003e\n      \u003cp\u003eHero description\u003c/p\u003e    \u003c!-- Snippet --\u003e\n      \u003cbutton\u003eCTA Button\u003c/button\u003e \u003c!-- Snippet --\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/section\u003e\n\n\u003c!-- Content Section --\u003e\n\u003csection class=\"editor-section content-section\"\u003e\n  \u003cdiv class=\"section-content\"\u003e\n    \u003cdiv class=\"editor-block two-column\"\u003e\n      \u003cdiv class=\"column\"\u003e\n        \u003ch2\u003eColumn 1 Title\u003c/h2\u003e\n        \u003cp\u003eColumn 1 content\u003c/p\u003e\n      \u003c/div\u003e\n      \u003cdiv class=\"column\"\u003e\n        \u003ch2\u003eColumn 2 Title\u003c/h2\u003e\n        \u003cp\u003eColumn 2 content\u003c/p\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/section\u003e\n```\n\n### Benefits of the Section System\n\n**Better Organization:**\n- Clear visual separation between page regions\n- Semantic HTML structure improves SEO and accessibility\n- Logical content hierarchy\n\n**Design Flexibility:**\n- True full-width backgrounds without CSS hacks\n- Independent styling for each page section\n- Consistent content centering\n\n**Responsive Design:**\n- Sections adapt to all viewport sizes\n- Content remains centered and readable\n- Background images scale appropriately\n\n**Modern Web Standards:**\n- Follows industry-standard page building patterns\n- Compatible with CSS Grid and Flexbox\n- Future-ready architecture\n\n## Components\n\n### Available Sections\n\n1. **Hero Section** - Full-width hero with gradient background\n2. **Content Section** - Standard content area with centered container\n3. **Features Section** - Feature showcase section with light background\n4. **Call to Action Section** - CTA section with dark background\n5. **Footer Section** - Page footer with dark styling\n\n### Available Blocks\n\n1. **Container Block** - Basic container with columns\n2. **Two Column Block** - Side-by-side layout\n3. **Three Column Block** - Three equal columns\n4. **Hero Block** - Hero content container\n\n### Available Snippets\n\n1. **Text Elements**\n   - Heading (H1-H6)\n   - Paragraph\n   - Blockquote\n   - Lists (ordered/unordered)\n\n2. **Media Elements**\n   - Image\n   - Video (YouTube/file)\n   - Image Gallery\n\n3. **Interactive Elements**\n   - Button\n   - Link\n   - Form elements\n\n4. **Layout Elements**\n   - Divider\n   - Spacer\n   - Custom HTML\n\n## Browser Support\n\nDragonCMS supports all modern browsers:\n\n- Chrome 90+\n- Firefox 88+\n- Safari 14+\n- Edge 90+\n\n### Known Browser Issues\n\n#### Firefox\n- Cursor positioning in contentEditable elements requires special handling (implemented)\n- Drag handle conflicts with contentEditable (resolved with workarounds)\n\n#### Safari\n- Some drag-and-drop behaviors may differ slightly\n- Touch events on iOS require additional handling\n\n## Troubleshooting\n\n### Common Issues\n\n#### Accessing Components\n**Problem:** Cannot find sections, blocks, or snippets to drag\n**Solution:** Use the tabbed left sidebar:\n- Click the sections icon (📋) to access page sections\n- Click the blocks icon (🧱) to access layout containers  \n- Click the snippets icon (⚡) to access content elements\n- Click the same icon again to close the panel\n\n#### Blocks not dragging\n**Problem:** Blocks can only be dragged by the handle (⋮⋮)\n**Solution:** Click and drag the dotted handle on the left side of each block\n\n#### Text not editable\n**Problem:** After using HTML editor, text becomes uneditable\n**Solution:** The editor automatically re-initializes contentEditable. If issues persist, call:\n```javascript\neditor.makeExistingBlocksEditable();\n```\n\n#### Styles not applying\n**Problem:** Custom styles not showing\n**Solution:** Ensure CSS specificity is high enough:\n```css\n.dragon-editor .editor-block.custom-class {\n    /* Your styles */\n}\n```\n\n#### Save/Load not working\n**Problem:** Save/Load buttons not functioning\n**Solution:** Set the `publishUrl` and `loadUrl` options:\n```javascript\nconst editor = dragon.New({\n    publishUrl: '/api/save',\n    loadUrl: '/api/load'\n});\n```\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.\n\n### Development Setup\n\n1. Clone the repository\n2. Install dependencies: `npm install`\n3. Run tests: `npm test`\n4. Open `index.html` in a browser or use `npm run serve:dev`\n5. Make changes to the JavaScript modules\n6. Run tests again to ensure no regressions\n7. Test across different browsers\n8. Submit a pull request\n\n### Testing\n\nDragonCMS uses Jest for unit and integration testing. Tests are located in the `tests/` directory.\n\n**Running Tests:**\n```bash\n# Run all tests\nnpm test\n\n# Run specific test file\nnpm test -- tests/fonts.test.js\n\n# Run tests in watch mode (recommended for development)\nnpm run test:watch\n\n# Generate coverage report\nnpm run test:coverage\n```\n\n**Test Structure:**\n- `tests/fonts.test.js` - Google Fonts system tests\n- `tests/blocks.test.js` - Custom blocks system tests\n- `tests/custom-snippets.test.js` - Custom snippets system tests\n- `tests/callbacks.test.js` - onChange/onRender callback tests  \n- `tests/editor-core.test.js` - Core editor functionality tests\n- `tests/modals.test.js` - Modal component tests\n- `tests/[component].test.js` - Individual component tests\n\n**Writing Tests:**\nFollow the existing test patterns. All tests should:\n- Use descriptive test names\n- Test both success and error scenarios\n- Mock external dependencies appropriately\n- Maintain good coverage of critical functionality\n\n### Testing Checklist\n\n- [ ] Run `npm test` and ensure all tests pass\n- [ ] Test drag and drop in Chrome, Firefox, Safari\n- [ ] Verify responsive preview modes\n- [ ] Test HTML editor functionality\n- [ ] Check undo/redo behavior\n- [ ] Test font customization with Google Fonts\n- [ ] Test custom blocks functionality and integration\n- [ ] Test custom snippets functionality and integration\n- [ ] Verify save/load if configured\n- [ ] Test custom snippets\n- [ ] Test callback functionality (onChange/onRender)\n- [ ] Validate mobile touch events\n\n## License\n\nMIT License - see [LICENSE.md](LICENSE.md) file for details.\n\n## Support\n\nFor issues, questions, or suggestions:\n- Open an issue on [GitHub](https://github.com/tsawler/dragon-cms)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftsawler%2Fdragon-cms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftsawler%2Fdragon-cms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftsawler%2Fdragon-cms/lists"}