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
1. URLs are auto-detected and converted to proper embed format
2. YouTube/Vimeo use iframe embeds
3. Direct files use HTML5 video element
4. Background videos auto-play muted and loop
### Editing Video URL
1. Select the video container (use Layers panel if needed)
2. Go to **Settings** tab
3. Paste URL in "Video URL" field
4. 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
1. Add Navigation block to page
2. Select the nav element
3. In Settings, click "Sync with Pages"
4. Links auto-generate from page list
5. CTA button (with `.nav-cta` class) 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)
| `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
1. Click the **Export** button in the top navigation bar
2. Choose export options:
- **Minify CSS**: Reduces file size by removing whitespace/comments
- **Include Google Fonts**: Adds font preload links (recommended)
3. Click **Download ZIP**
4. 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