Visual drag-and-drop website builder using GrapesJS with: - Multi-page editor with live preview - File-based asset storage via PHP API (no localStorage base64) - Template library, Docker support, and Playwright test suite Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14 KiB
Site Builder - Project Documentation
Overview
A visual drag-and-drop website builder using GrapesJS. Users can create multi-page websites without writing code, with server-side file storage for assets and localStorage persistence for editor state.
File Structure
site-builder/
├── router.php # PHP built-in server router (dev server)
├── .htaccess # Apache rewrite rules for /api/* routing
├── .user.ini # PHP upload/memory limits for Apache
├── index.html # Main editor page
├── preview.html # Preview page (renders saved content with page navigation)
├── CLAUDE.md # This documentation file
├── api/
│ ├── index.php # API handler (assets, projects, health endpoints)
│ └── image-resize.php # Image resize/crop endpoint
├── css/
│ └── editor.css # Custom editor styles (dark theme, ~1300 lines)
├── js/
│ ├── editor.js # Editor initialization and all functionality (~1900 lines)
│ ├── assets.js # Asset management (upload, browse, deploy)
│ └── whp-integration.js # WHP control panel integration
├── storage/
│ ├── assets/ # Uploaded asset files (images, videos, etc.)
│ ├── projects/ # Saved project data (JSON files)
│ └── tmp/ # Temporary files
└── docs/
└── plans/
└── 2026-01-26-site-builder-design.md # Design document
Dependencies (CDN)
All dependencies are loaded from CDN in index.html:
- GrapesJS Core (
unpkg.com/grapesjs) - Main editor engine - grapesjs-blocks-basic - Basic building blocks
- grapesjs-preset-webpage - Webpage blocks (hero, features, etc.)
- grapesjs-plugin-forms - Form elements
- grapesjs-style-gradient - Gradient background support
- Font Awesome 5 - Block icons
- Google Fonts - Inter, Roboto, Open Sans, Poppins, Montserrat, Playfair Display, Merriweather, Source Code Pro
Running the Project
The project uses PHP for its API backend. Assets are stored as files on disk (not base64 in localStorage), which avoids browser storage quota issues.
Production (Apache)
The .htaccess file routes /api/* requests to api/index.php. The .user.ini sets PHP upload limits. Just deploy to any Apache + PHP host.
Local Development (PHP built-in server)
php -d upload_max_filesize=500M -d post_max_size=512M -S localhost:8081 router.php
Then open http://localhost:8081
Server API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/health |
Server health check |
| POST | /api/assets/upload |
Upload file (multipart/form-data) |
| GET | /api/assets |
List all stored assets |
| DELETE | /api/assets/<filename> |
Delete an asset |
| POST | /api/projects/save |
Save project data (JSON body) |
| GET | /api/projects/list |
List all saved projects |
| GET | /api/projects/<id> |
Load a specific project |
| DELETE | /api/projects/<id> |
Delete a project |
Editor Interface
Top Navigation Bar
- Logo/branding
- Device switcher (Desktop/Tablet/Mobile)
- Undo/Redo buttons
- Clear canvas button
- Export button (download site as ZIP with options)
- Preview button (opens preview.html in new tab)
Left Panel (3 tabs)
- Blocks - Draggable components organized by category
- Pages - Multi-page management (add/edit/delete pages)
- Layers - Component hierarchy tree view
Center Canvas
- Live preview of the website
- Click to select, drag to reposition
- Right-click for context menu
- Resize handles on selected components
Right Panel (2 tabs)
- Styles - Two modes:
- Guided Mode: Context-aware presets based on selected element type
- Advanced Mode: Full GrapesJS style manager with all CSS properties
- Settings - Component-specific traits/attributes (like Video URL)
Block Categories
Layout
| Block | Description |
|---|---|
| Section | Basic content section with centered container |
| Section (Background) | Section with image background and overlay |
| Section (Video BG) | Section with video background (YouTube/Vimeo/MP4) and overlay |
| Logo | Styled logo with icon and text |
| Navigation | Dynamic nav bar with page sync |
| Footer | Footer with links and copyright |
| 1-4 Columns | Flexible column layouts |
| 2 Columns 3/7 | Asymmetric column layout |
Basic
| Block | Description |
|---|---|
| Text | Paragraph text |
| Heading | H2 heading |
| Button | Styled link button |
| Divider | Horizontal rule (color/thickness editable) |
| Spacer | Vertical spacing element |
| Text Box | Styled container for overlaying on backgrounds |
Media
| Block | Description |
|---|---|
| Image | Responsive image |
| Video | Universal video (YouTube, Vimeo, or direct file) |
Sections
| Block | Description |
|---|---|
| Hero (Image) | Hero with image background and overlay |
| Hero (Video) | Hero with video background and overlay |
| Hero (Simple) | Hero with gradient background |
| Features Grid | 3-column feature cards |
| Testimonials | Customer testimonials with star ratings |
| Pricing Table | 3-tier pricing comparison with featured tier |
| Contact Section | Contact info with form |
| Call to Action | CTA banner with gradient background |
Forms
Form, Input, Textarea, Select, Button, Label, Checkbox, Radio
Context-Aware Styling (Guided Mode)
The guided panel shows different controls based on selected element:
Text Elements (p, h1-h6, span, label)
- Text Color (8 presets)
- Font Family (8 Google Fonts)
- Text Size (XS, S, M, L, XL, 2XL)
- Font Weight (Light, Normal, Medium, Semi, Bold)
Links/Buttons (a)
- Link URL input with "Open in new tab" option
- Button Color (8 presets, auto-adjusts text for contrast)
- Text styling options
- Border Radius and Padding
Containers (div, section, etc.)
- Background Color (8 presets)
- Background Gradient (12 presets)
- Background Image (URL with size/position controls)
- Padding and Border Radius
Overlays (.bg-overlay)
- Overlay Color (6 presets)
- Opacity Slider (0-100%)
Navigation (nav)
- "Sync with Pages" button (auto-generates links from page list)
- "Add Link" button
- Link list with delete buttons
Dividers (hr)
- Divider Color (8 presets)
- Line Thickness (1-6px)
Video System
Supported Formats
The Video block and Section Video BG support:
- YouTube:
youtube.com/watch?v=ID,youtu.be/ID - Vimeo:
vimeo.com/ID - Direct files:
.mp4,.webm,.ogg,.mov
How Videos Work
- URLs are auto-detected and converted to proper embed format
- YouTube/Vimeo use iframe embeds
- Direct files use HTML5 video element
- Background videos auto-play muted and loop
Editing Video URL
- Select the video container (use Layers panel if needed)
- Go to Settings tab
- Paste URL in "Video URL" field
- Video loads automatically
Multi-Page System
Storage
- Pages stored in localStorage key:
sitebuilder-pages - Each page has: id, name, slug, html, css
Page Management
- Add Page: Click "Add Page" in Pages tab
- Edit Page: Click edit icon on page item
- Delete Page: Click delete icon (cannot delete last page)
- Switch Pages: Click on page item (auto-saves current page)
Navigation Sync
- Add Navigation block to page
- Select the nav element
- In Settings, click "Sync with Pages"
- Links auto-generate from page list
- CTA button (with
.nav-ctaclass) is preserved
Context Menu (Right-Click)
| Action | Shortcut | Description |
|---|---|---|
| Edit Content | - | Enable inline text editing |
| Duplicate | Ctrl+D | Copy element in place |
| Copy | Ctrl+C | Copy to clipboard |
| Paste | Ctrl+V | Paste from clipboard |
| Move Up | - | Move element up in parent |
| Move Down | - | Move element down in parent |
| Select Parent | - | Select parent container |
| Wrap in Container | - | Wrap in new div |
| Delete | Del | Remove element |
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| Ctrl/Cmd + Z | Undo |
| Ctrl/Cmd + Shift + Z | Redo |
| Ctrl/Cmd + Y | Redo (alternative) |
| Ctrl/Cmd + C | Copy |
| Ctrl/Cmd + V | Paste |
| Ctrl/Cmd + D | Duplicate |
| Delete / Backspace | Remove selected |
| Escape | Deselect / Close modals |
Storage Architecture
Server-Side Storage (primary, when server.py is running)
| Location | Purpose |
|---|---|
storage/assets/ |
Uploaded files (images, videos, etc.) stored on disk |
storage/projects/ |
Project data as JSON files |
storage/tmp/ |
Temporary files |
Assets are uploaded via POST /api/assets/upload and stored as actual files on disk. They are referenced in the editor by URL (e.g., /storage/assets/1234567_abc123_photo.jpg), avoiding localStorage quota limits.
localStorage Keys (lightweight metadata and editor state)
| Key | Purpose |
|---|---|
sitebuilder-project |
GrapesJS auto-save (components, styles) |
sitebuilder-pages |
Multi-page data (array of page objects) |
sitebuilder-assets |
Asset metadata index (URLs and names only, no file contents) |
sitebuilder-project-preview |
Preview data (all pages for preview.html) |
Important: Asset file contents (images, videos) are NOT stored in localStorage. Only metadata (filename, URL, type) is cached there. This prevents the QuotaExceededError that occurred with base64-encoded large files.
Export Feature
How to Export
- Click the Export button in the top navigation bar
- Choose export options:
- Minify CSS: Reduces file size by removing whitespace/comments
- Include Google Fonts: Adds font preload links (recommended)
- Click Download ZIP
- All pages are exported as standalone HTML files
Exported File Structure
site-export.zip
├── index.html # Home page
├── about.html # About page (based on page slug)
├── contact.html # etc.
Technical Details
- Uses JSZip library (loaded dynamically on first export)
- Each HTML file includes embedded CSS styles
- Responsive CSS reset included in each file
- Mobile column stacking rules included
Preview System
preview.html loads saved content from localStorage and renders it:
- Supports multi-page with page selector buttons
- Backwards compatible with legacy single-page format
- Includes Google Fonts and responsive styles
- "Back to Editor" button
CSS Architecture (editor.css)
Main Sections
- Base Layout (~lines 1-100) - Editor container, panels
- Top Navigation (~lines 100-200) - Nav bar, device buttons
- Left Panel (~lines 200-400) - Blocks, pages, layers
- Right Panel (~lines 400-600) - Styles, traits
- Guided Styles (~lines 600-800) - Color presets, font presets
- Context Menu (~lines 800-900) - Right-click menu
- Pages Panel (~lines 900-1000) - Page list, page items
- Modals (~lines 1000-1100) - Page settings modal
- New Controls (~lines 1100-1300) - Background, overlay, nav controls
Theme
- Dark theme with
#16161abase - Accent color:
#3b82f6(blue) - Text:
#e4e4e7(light gray) - Borders:
#3f3f46(dark gray)
JavaScript Architecture (editor.js)
Structure (approximate line numbers)
- GrapesJS Init (1-200) - Editor configuration, plugins
- Custom Blocks (200-820) - All block definitions including new sections
- Component Types (900-1040) - Video wrapper types with traits
- Device Switching (1040-1080)
- Undo/Redo/Clear (1080-1120)
- Preview (1120-1140)
- Panel Tabs (1140-1200)
- Style Mode Toggle (1200-1220)
- Context-Aware UI (1220-1400) - Element type detection, section visibility
- Color/Style Presets (1400-1600) - Click handlers for all presets
- Background/Overlay Controls (1600-1700)
- Navigation Controls (1700-1800) - Sync with pages, add/remove links
- Link Editing (1800-1850)
- Save Status (1850-1900)
- Keyboard Shortcuts (1900-1950)
- Selection Handling (1950-2050) - Update UI on selection change
- Context Menu (2050-2200) - Right-click functionality
- Page Management (2200-2600) - Pages CRUD, switching, modals
- Export Functionality (2630-2810) - ZIP export with JSZip
Key Functions
convertToEmbedUrl(url)- Converts YouTube/Vimeo URLs to embed formatapplyVideoUrl(component, url)- Applies video to wrapper componentgetElementType(tagName)- Returns element category for context-aware UIshowSectionsForElement(component)- Shows relevant guided panel sectionsloadPages()/savePages()- Page persistenceswitchToPage(pageId)- Page switching with auto-saveloadNavLinks(component)- Populate nav links list in guided panelgeneratePageHtml(page, includeFonts, minifyCss)- Generate standalone HTML for exportcreateAndDownloadZip(includeFonts, minifyCss)- Create ZIP and trigger download
Development Notes
Adding New Blocks
- Add to
blockManager.add()section - Choose appropriate category
- Use inline styles for immediate visibility
- Add
data-*attributes for custom component types if needed
Adding New Guided Controls
- Add HTML section in
index.htmlinside#guided-styles - Add section reference in
sectionsobject - Update
showSectionsForElement()to show for relevant element types - Add click handlers for presets
- Add CSS in
editor.css
Custom Component Types
Use editor.DomComponents.addType() for:
- Custom traits in Settings panel
- Special behavior on attribute changes
- Detection via
isComponentfunction
Testing Video Embeds
YouTube/Vimeo embeds may not work in GrapesJS canvas (nested iframe issue) but work correctly in Preview mode and published sites.
Future Enhancements (from design doc)
Phase 2: Backend Integration
- PHP backend for user authentication
- Database storage for projects
- Multiple project support
Phase 3: Publishing
- Save/publish sites to server
- Subdomain or custom domain support
- Template library
Phase 4: Enhancements
- More block types
- Custom CSS injection
- Asset manager for images
- SEO settings per page