344 lines
11 KiB
Markdown
344 lines
11 KiB
Markdown
# 🎨 Visual Builder Implementation Plan
|
|
## Craft.js + AstroWind + Direct DB Shim
|
|
|
|
**Objective:** Build a "Squarespace-style" visual editor that saves directly to PostgreSQL via the Shim, without CMS overhead.
|
|
|
|
---
|
|
|
|
## 🏗️ ARCHITECTURE
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ PUBLIC SITE (SSR - Lightning Fast) │
|
|
│ https://[site-domain]/[slug] │
|
|
│ - Reads sites.config JSONB │
|
|
│ - Renders AstroWind components │
|
|
│ - Zero editor overhead │
|
|
└─────────────────────────────────────────────────────────┘
|
|
▲
|
|
│ Reads config
|
|
│
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ POSTGRESQL (sites.config JSONB) │
|
|
│ { │
|
|
│ "template": "astrowind", │
|
|
│ "blocks": [ │
|
|
│ { "type": "Hero", "props": {...} }, │
|
|
│ { "type": "Features", "props": {...} } │
|
|
│ ] │
|
|
│ } │
|
|
└─────────────────────────────────────────────────────────┘
|
|
▲
|
|
│ Writes config via Shim
|
|
│
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ VISUAL EDITOR (React + Craft.js) │
|
|
│ https://[admin-domain]/admin/editor/[id] │
|
|
│ - Drag-and-drop blocks │
|
|
│ - Live preview │
|
|
│ - Saves to PostgreSQL via /api/shim/sites/save-config │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 IMPLEMENTATION TASKS
|
|
|
|
### Phase 1: Editor Infrastructure (60 min)
|
|
|
|
**Task 1.1: Create Craft.js User Components**
|
|
- [ ] `src/components/editor/blocks/HeroBlock.tsx` - Wraps AstroWind Hero
|
|
- [ ] `src/components/editor/blocks/FeaturesBlock.tsx` - Wraps Features
|
|
- [ ] `src/components/editor/blocks/ContentBlock.tsx` - Wraps Content
|
|
- [ ] `src/components/editor/blocks/CTABlock.tsx` - Wraps Call-to-Action
|
|
- [ ] `src/components/editor/blocks/index.ts` - Exports all blocks
|
|
|
|
**Task 1.2: Create Editor Canvas**
|
|
- [ ] `src/components/editor/EditorCanvas.tsx` - Main Craft.js editor
|
|
- [ ] `src/components/editor/ToolboxPanel.tsx` - Drag-and-drop panel
|
|
- [ ] `src/components/editor/SettingsPanel.tsx` - Block properties editor
|
|
- [ ] `src/components/editor/TopBar.tsx` - Save/Preview buttons
|
|
|
|
**Task 1.3: Create Editor Utilities**
|
|
- [ ] `src/lib/editor/serializer.ts` - Convert Craft.js → JSONB
|
|
- [ ] `src/lib/editor/deserializer.ts` - Convert JSONB → Craft.js
|
|
- [ ] `src/lib/editor/templates.ts` - Pre-built template configs
|
|
|
|
### Phase 2: Template Factory (45 min)
|
|
|
|
**Task 2.1: AstroWind Component Adapters**
|
|
- [ ] `src/components/templates/astrowind/Hero.astro` - Reads from JSONB
|
|
- [ ] `src/components/templates/astrowind/Features.astro` - Reads from JSONB
|
|
- [ ] `src/components/templates/astrowind/Content.astro` - Reads from JSONB
|
|
- [ ] `src/components/templates/astrowind/CTA.astro` - Reads from JSONB
|
|
|
|
**Task 2.2: Template Registry**
|
|
- [ ] `src/lib/templates/registry.ts` - Maps template names to components
|
|
- [ ] `src/lib/templates/schemas.ts` - Zod schemas for block configs
|
|
- [ ] `src/lib/templates/defaults.ts` - Default block configurations
|
|
|
|
### Phase 3: API Routes (30 min)
|
|
|
|
**Task 3.1: Editor API Routes**
|
|
- [ ] `POST /api/shim/sites/save-config` - Save JSONB to PostgreSQL
|
|
- [ ] `GET /api/shim/sites/[id]/config` - Load JSONB for editor
|
|
- [ ] `POST /api/shim/sites/[id]/preview` - Generate preview URL
|
|
|
|
**Task 3.2: Template API Routes**
|
|
- [ ] `GET /api/templates/list` - Available templates
|
|
- [ ] `POST /api/templates/apply` - Apply template to site
|
|
|
|
### Phase 4: Editor Pages (30 min)
|
|
|
|
**Task 4.1: Editor Route**
|
|
- [ ] `src/pages/admin/editor/[id].astro` - Main editor page
|
|
- [ ] Token validation wrapper
|
|
- [ ] Load site config from Shim
|
|
|
|
**Task 4.2: Template Selector**
|
|
- [ ] `src/pages/admin/templates.astro` - Template gallery
|
|
- [ ] Preview thumbnails
|
|
- [ ] One-click apply
|
|
|
|
### Phase 5: Public Rendering (30 min)
|
|
|
|
**Task 5.1: Dynamic Template Renderer**
|
|
- [ ] `src/pages/[...slug].astro` - Reads sites.config and renders blocks
|
|
- [ ] Block component resolver
|
|
- [ ] SEO metadata injection
|
|
|
|
**Task 5.2: Site Utilities**
|
|
- [ ] `src/lib/templates/renderer.ts` - Render blocks from JSONB
|
|
- [ ] `src/lib/templates/seo.ts` - Extract SEO from config
|
|
|
|
---
|
|
|
|
## 🔧 CORE COMPONENTS
|
|
|
|
### 1. Editor Canvas (`EditorCanvas.tsx`)
|
|
|
|
```typescript
|
|
import { Editor, Frame, Element } from '@craftjs/core';
|
|
import { HeroBlock, FeaturesBlock, ContentBlock } from './blocks';
|
|
|
|
export default function EditorCanvas({ initialState, siteId }) {
|
|
const handleSave = async (json) => {
|
|
await fetch(`/api/shim/sites/save-config`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({ siteId, config: json })
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Editor resolver={{ HeroBlock, FeaturesBlock, ContentBlock }}>
|
|
<div className="flex h-screen">
|
|
<ToolboxPanel />
|
|
<div className="flex-1">
|
|
<TopBar onSave={handleSave} />
|
|
<Frame json={initialState}>
|
|
<Element is="div" canvas>
|
|
{/* Editable canvas */}
|
|
</Element>
|
|
</Frame>
|
|
</div>
|
|
<SettingsPanel />
|
|
</div>
|
|
</Editor>
|
|
);
|
|
}
|
|
```
|
|
|
|
### 2. User Component Example (`HeroBlock.tsx`)
|
|
|
|
```typescript
|
|
import { useNode } from '@craftjs/core';
|
|
|
|
export const HeroBlock = ({ title, subtitle, image, ctaText }) => {
|
|
const { connectors: { connect, drag } } = useNode();
|
|
|
|
return (
|
|
<div ref={ref => connect(drag(ref))} className="hero">
|
|
<h1>{title}</h1>
|
|
<p>{subtitle}</p>
|
|
{image && <img src={image} alt={title} />}
|
|
<button>{ctaText}</button>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
HeroBlock.craft = {
|
|
props: {
|
|
title: 'Hero Title',
|
|
subtitle: 'Hero subtitle',
|
|
image: '/placeholder.jpg',
|
|
ctaText: 'Get Started'
|
|
},
|
|
rules: {
|
|
canDrag: true,
|
|
canDrop: false
|
|
},
|
|
related: {
|
|
settings: HeroSettings // Property panel component
|
|
}
|
|
};
|
|
```
|
|
|
|
### 3. Save Config API (`save-config.ts`)
|
|
|
|
```typescript
|
|
import type { APIRoute } from 'astro';
|
|
import { updateSite } from '@/lib/shim/sites';
|
|
|
|
export const POST: APIRoute = async ({ request }) => {
|
|
try {
|
|
const { siteId, config } = await request.json();
|
|
|
|
// Update site config via Shim
|
|
await updateSite(siteId, {
|
|
config: JSON.stringify(config)
|
|
});
|
|
|
|
return new Response(JSON.stringify({ success: true }), {
|
|
status: 200
|
|
});
|
|
} catch (error) {
|
|
return new Response(JSON.stringify({ error: error.message }), {
|
|
status: 500
|
|
});
|
|
}
|
|
};
|
|
```
|
|
|
|
### 4. Public Renderer (`[...slug].astro`)
|
|
|
|
```astro
|
|
---
|
|
import { getSiteByDomain } from '@/lib/shim/sites';
|
|
import { renderBlocks } from '@/lib/templates/renderer';
|
|
|
|
const site = await getSiteByDomain(Astro.url.hostname);
|
|
const config = site?.config || {};
|
|
const blocks = config.blocks || [];
|
|
---
|
|
|
|
<html>
|
|
<body>
|
|
{renderBlocks(blocks)}
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 TEMPLATE FACTORY STRUCTURE
|
|
|
|
### Default Templates
|
|
|
|
| Template | Blocks | Use Case |
|
|
|----------|--------|----------|
|
|
| **Corporate** | Hero + Features + Stats + Team + CTA | Business sites |
|
|
| **Landing** | Hero + Benefits + Testimonials + Pricing + CTA | SaaS landing pages |
|
|
| **Blog** | Header + Posts Grid + Sidebar + Footer | Content sites |
|
|
| **Portfolio** | Hero + Projects Grid + About + Contact | Personal branding |
|
|
|
|
### JSONB Structure
|
|
|
|
```json
|
|
{
|
|
"template": "astrowind",
|
|
"theme": {
|
|
"primaryColor": "#3B82F6",
|
|
"font": "Inter"
|
|
},
|
|
"blocks": [
|
|
{
|
|
"id": "hero-1",
|
|
"type": "Hero",
|
|
"props": {
|
|
"title": "Welcome to Our Site",
|
|
"subtitle": "Build amazing things",
|
|
"ctaText": "Get Started",
|
|
"ctaLink": "/signup"
|
|
}
|
|
},
|
|
{
|
|
"id": "features-1",
|
|
"type": "Features",
|
|
"props": {
|
|
"title": "Key Features",
|
|
"items": [
|
|
{ "icon": "⚡", "title": "Fast", "description": "Lightning quick" },
|
|
{ "icon": "🔒", "title": "Secure", "description": "Bank-level security" }
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔒 SECURITY MODEL
|
|
|
|
1. **Editor Access:**
|
|
- Only accessible at `/admin/editor/[id]`
|
|
- Requires `GOD_MODE_TOKEN` validation
|
|
- Token checked in Astro middleware
|
|
|
|
2. **Save Operations:**
|
|
- All saves go through Shim (`/api/shim/sites/save-config`)
|
|
- Zod validation on JSONB structure
|
|
- Sanitize user input before SQL
|
|
|
|
3. **Public Rendering:**
|
|
- No editor JavaScript loaded
|
|
- Pure SSR from JSONB config
|
|
- No exposure of admin endpoints
|
|
|
|
---
|
|
|
|
## 📊 PERFORMANCE COMPARISON
|
|
|
|
| Operation | Traditional CMS | God Mode Visual Builder |
|
|
|-----------|----------------|-------------------------|
|
|
| **Load Editor** | ~2000ms (API + DB + Render) | ~300ms (Direct DB) |
|
|
| **Save Changes** | ~1500ms (API → CMS → DB) | ~50ms (Shim → DB) |
|
|
| **Public Page Load** | ~800ms (CMS overhead) | ~10ms (Pure SSR) |
|
|
| **Scale** | 100s of sites | 10,000s of sites |
|
|
|
|
---
|
|
|
|
## 🎯 SUCCESS CRITERIA
|
|
|
|
1. ✅ Can drag-and-drop AstroWind blocks in `/admin/editor/[id]`
|
|
2. ✅ Changes save directly to `sites.config` JSONB
|
|
3. ✅ Public site re-renders instantly with new config
|
|
4. ✅ Zero performance impact on public-facing pages
|
|
5. ✅ Can manage 1000+ sites with different layouts
|
|
6. ✅ Full Zod validation on all block configs
|
|
7. ✅ SEO metadata auto-extracted from blocks
|
|
|
|
---
|
|
|
|
## 🚀 DEPLOYMENT CHECKLIST
|
|
|
|
- [ ] Install Craft.js dependencies (`npm install @craftjs/core @craftjs/utils`)
|
|
- [ ] Create all editor components
|
|
- [ ] Create template adapters
|
|
- [ ] Test save/load flow
|
|
- [ ] Verify public rendering
|
|
- [ ] Security audit (token validation)
|
|
- [ ] Performance test (1000+ blocks)
|
|
|
|
---
|
|
|
|
## 📈 ROADMAP EXTENSIONS
|
|
|
|
**Phase 6 (Future):**
|
|
- [ ] A/B Testing - Save multiple configs, split traffic
|
|
- [ ] Version History - Keep history of config changes
|
|
- [ ] Template Marketplace - Share templates between sites
|
|
- [ ] AI Block Generator - Generate blocks from text prompts
|
|
- [ ] Responsive Preview - Mobile/tablet/desktop view
|
|
- [ ] Component Library - Custom reusable blocks
|