7.4 KiB
7.4 KiB
Landing Pages (Page Builder)
The Landing Pages feature provides a complete page building system with WYSIWYG editing, custom blocks, MkDocs export, and public rendering. Build custom landing pages without code.
Overview
The Landing Pages system consists of four integrated components:
- Page Builder - Page CRUD and management
- GrapesJS Editor - WYSIWYG editor
- Block Library - Reusable content blocks
- MkDocs Export - Export to Jinja2 templates
Features
WYSIWYG Editor
- GrapesJS integration
- Drag-and-drop interface
- Visual editing
- Component customization
- CSS styling
- Responsive preview
- Desktop-only (mobile warning)
Block Library
Pre-built components:
- Hero sections - Large header with CTA
- Feature grids - Multi-column features
- Call-to-action - Button sections
- Text blocks - Rich text content
- Image galleries - Photo grids
- Forms - Contact forms (future)
- Custom HTML - Raw HTML blocks
Page Management
- Create/edit/delete pages
- Slug management (URL-friendly)
- Meta tags (title, description)
- Published/draft status
- Page settings (layout, scripts)
- Search and filtering
MkDocs Export
- Export to Jinja2 Material theme templates
- Custom overrides directory
- Static page generation
- SEO optimization
- Template inheritance
User Flow
Admin Experience
-
Create Page (
/app/pages)- Click "New Page"
- Enter title and slug
- Set meta description
- Save draft
-
Edit Page (
/app/pages/:id/edit)- Full-screen GrapesJS editor
- Drag blocks from sidebar
- Customize components
- Ctrl+S to save
- Preview changes
-
Publish Page
- Set status to "Published"
- Page appears at
/p/:slug - Listed in page table
-
Export to MkDocs (
/app/services/docs)- Select pages to export
- Click "Export"
- Pages saved to MkDocs overrides
- Rebuild MkDocs site
Public Experience
- View Landing Page (
/p/:slug)- Rendered HTML/CSS
- Custom styling
- Responsive design
- SEO metadata
Architecture
Backend Components
Module:
api/src/modules/pages/pages-admin.routes.ts- Admin CRUDapi/src/modules/pages/pages-public.routes.ts- Public rendererapi/src/modules/pages/blocks.routes.ts- Block library APIapi/src/modules/pages/pages.service.ts- Business logicapi/src/modules/pages/pages.schemas.ts- Zod validation
Database Models:
Page- Page definitions (title, slug, html, css, settings)PageBlock- Reusable block library
Frontend Components
Admin Pages:
admin/src/pages/LandingPagesPage.tsx- Page management tableadmin/src/pages/PageEditorPage.tsx- Full-screen editor
Public Pages:
admin/src/pages/public/LandingPage.tsx- Page renderer
Editor Component:
admin/src/components/GrapesJSEditor.tsx- GrapesJS wrapper
Configuration
Environment Variables
# MkDocs export directory (inside Docker)
MKDOCS_EXPORT_DIR=/mkdocs/docs/overrides
Page Settings
Each page can configure:
- Meta title - Browser title tag
- Meta description - SEO description
- Custom CSS - Page-specific styles
- Custom JS - Page-specific scripts
- Layout - Template wrapper (future)
GrapesJS Integration
Editor Setup
import grapesjs from 'grapesjs';
const editor = grapesjs.init({
container: '#gjs',
fromElement: true,
height: '100vh',
storageManager: false, // Save via API
canvas: {
styles: [...], // Custom styles
scripts: [...], // Custom scripts
},
blockManager: {
blocks: customBlocks, // Block library
},
});
Custom Blocks
Blocks defined in GrapesJSEditor.tsx:
const customBlocks = [
{
id: 'hero-section',
label: 'Hero Section',
content: '<div class="hero">...</div>',
category: 'Basic',
},
{
id: 'feature-grid',
label: 'Feature Grid',
content: '<div class="features">...</div>',
category: 'Content',
},
// ... more blocks
];
Save Handler
Ctrl+S keyboard shortcut:
editor.on('run:core:save', () => {
const html = editor.getHtml();
const css = editor.getCss();
onSave({ html, css });
});
MkDocs Export
Export Process
- Select Pages - Admin selects pages to export
- Generate Jinja2 - Wrap HTML in Material theme template
- Save to Overrides - Write to
mkdocs/docs/overrides/ - Configure Front Matter - Set template, title, description
- Rebuild Site - MkDocs regenerates static site
Jinja2 Template Wrapper
{% extends "main.html" %}
{% block content %}
<style>
{{ page_css }}
</style>
{{ page_html }}
{% endblock %}
Front Matter
---
template: custom-page.html
title: Page Title
description: Page description for SEO
---
Database Schema
Page Model
model Page {
id Int @id @default(autoincrement())
title String
slug String @unique
html String @db.Text
css String? @db.Text
settings Json?
published Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
PageBlock Model
model PageBlock {
id Int @id @default(autoincrement())
name String
category String
html String @db.Text
css String? @db.Text
thumbnail String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
API Endpoints
Admin Endpoints
GET /api/pages # List pages
POST /api/pages # Create page
GET /api/pages/:id # Get page
PATCH /api/pages/:id # Update page
DELETE /api/pages/:id # Delete page
POST /api/pages/export-mkdocs # Export to MkDocs
GET /api/pages/blocks # Get block library
POST /api/pages/blocks # Create block
Public Endpoints
GET /api/pages/public/:slug # Get published page by slug
Desktop-Only Editor
GrapesJS editor requires desktop browser:
const screens = Grid.useBreakpoint();
const isMobile = !screens.md;
if (isMobile) {
return (
<Alert
message="Desktop Required"
description="Page editor requires desktop browser"
type="warning"
/>
);
}
Best Practices
Slug Management
- Auto-generate from title
- URL-friendly (lowercase, hyphens)
- Unique constraint
- Update URL on slug change
SEO Optimization
- Meta title (50-60 chars)
- Meta description (150-160 chars)
- Semantic HTML structure
- Alt text for images
- Heading hierarchy
Performance
- Minify CSS
- Lazy load images
- Async scripts
- Cache rendered pages
Responsive Design
- Mobile-first CSS
- Flexible grids
- Responsive images
- Touch-friendly buttons