mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-26 06:44:58 +00:00
504 lines
16 KiB
Markdown
504 lines
16 KiB
Markdown
# Generic Page System - Reducing Hardcoded TSX Dependency
|
|
|
|
## Overview
|
|
|
|
MetaBuilder now features a **Generic Page System** that allows Level 1-3 (Homepage, User Area, Admin Panel) to be defined declaratively using JSON configuration and Lua scripts, dramatically reducing dependence on hardcoded TSX files.
|
|
|
|
## Key Improvements
|
|
|
|
### Before (Iteration 1-23)
|
|
- ❌ Level1.tsx, Level2.tsx, Level3.tsx were **hardcoded TSX files**
|
|
- ❌ Each level had fixed UI structure
|
|
- ❌ Changes required code modification
|
|
- ❌ IRC was the only declarative component
|
|
|
|
### After (Iteration 24+)
|
|
- ✅ **PageDefinition** system allows declarative page configuration
|
|
- ✅ **GenericPage** component renders any page from JSON
|
|
- ✅ **PageRenderer** manages page loading, permissions, and Lua execution
|
|
- ✅ **PageDefinitionBuilder** provides default pages
|
|
- ✅ Levels 1-3 can be fully customized from Level 4/5 without code changes
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ PAGE DEFINITION (JSON) │
|
|
│ - Components tree │
|
|
│ - Layout configuration │
|
|
│ - Permission rules │
|
|
│ - Lua script hooks │
|
|
│ - Metadata (header, sidebar, footer) │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ PAGE RENDERER │
|
|
│ - Loads page from database │
|
|
│ - Checks permissions │
|
|
│ - Executes onLoad/onUnload Lua scripts │
|
|
│ - Provides context to components │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ GENERIC PAGE (React) │
|
|
│ - Renders layout (default, sidebar, dashboard, blank) │
|
|
│ - Renders header/footer based on metadata │
|
|
│ - Renders component tree using RenderComponent │
|
|
│ - Handles navigation and logout │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ RENDER COMPONENT │
|
|
│ - Recursively renders component tree │
|
|
│ - Supports shadcn components │
|
|
│ - Supports declarative components (IRC, Forum, etc.) │
|
|
│ - Executes Lua handlers for interactions │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Core Files
|
|
|
|
### 1. `/src/lib/page-renderer.ts`
|
|
**PageRenderer** class that manages pages:
|
|
- `registerPage(page)` - Register a page definition
|
|
- `loadPages()` - Load pages from database
|
|
- `getPage(id)` - Get page by ID
|
|
- `getPagesByLevel(level)` - Get all pages for a level
|
|
- `checkPermissions(page, user)` - Verify user can access page
|
|
- `executeLuaScript(scriptId, context)` - Run Lua script
|
|
- `onPageLoad(page, context)` - Lifecycle hook
|
|
- `onPageUnload(page, context)` - Lifecycle hook
|
|
|
|
### 2. `/src/lib/page-definition-builder.ts`
|
|
**PageDefinitionBuilder** creates default pages:
|
|
- `initializeDefaultPages()` - Creates Level 1-3 default pages
|
|
- `buildLevel1Homepage()` - Public homepage with hero + features
|
|
- `buildLevel2UserDashboard()` - User dashboard with profile + comments
|
|
- `buildLevel3AdminPanel()` - Admin panel with user/content management
|
|
- `getPages()` - Returns all built pages
|
|
|
|
### 3. `/src/components/GenericPage.tsx`
|
|
**GenericPage** React component that renders any page:
|
|
- Loads page definition from PageRenderer
|
|
- Checks permissions
|
|
- Renders appropriate layout
|
|
- Executes Lua lifecycle hooks
|
|
- Handles navigation and user actions
|
|
|
|
## PageDefinition Structure
|
|
|
|
```typescript
|
|
interface PageDefinition {
|
|
id: string // Unique page identifier
|
|
level: 1 | 2 | 3 | 4 | 5 // Application level
|
|
title: string // Page title
|
|
description?: string // Optional description
|
|
layout: 'default' | 'sidebar' | 'dashboard' | 'blank' // Layout type
|
|
components: ComponentInstance[] // Component tree
|
|
|
|
luaScripts?: {
|
|
onLoad?: string // Script ID to run on page load
|
|
onUnload?: string // Script ID to run on page unload
|
|
handlers?: Record<string, string> // Event handlers (Lua script IDs)
|
|
}
|
|
|
|
permissions?: {
|
|
requiresAuth: boolean // Requires authentication?
|
|
requiredRole?: string // Minimum role required
|
|
customCheck?: string // Custom Lua permission check
|
|
}
|
|
|
|
metadata?: {
|
|
showHeader?: boolean // Show header?
|
|
showFooter?: boolean // Show footer?
|
|
headerTitle?: string // Header title
|
|
headerActions?: ComponentInstance[] // Header buttons/actions
|
|
sidebarItems?: Array<{ // Sidebar navigation items
|
|
id: string
|
|
label: string
|
|
icon: string
|
|
action: 'navigate' | 'lua' | 'external'
|
|
target: string
|
|
}>
|
|
}
|
|
}
|
|
```
|
|
|
|
## Layout Types
|
|
|
|
### 1. Default Layout
|
|
Standard page with header, content area, and footer:
|
|
```
|
|
┌────────────────────────────────────┐
|
|
│ Header │
|
|
├────────────────────────────────────┤
|
|
│ │
|
|
│ Content │
|
|
│ │
|
|
├────────────────────────────────────┤
|
|
│ Footer │
|
|
└────────────────────────────────────┘
|
|
```
|
|
|
|
### 2. Sidebar Layout
|
|
Page with persistent sidebar navigation:
|
|
```
|
|
┌────────────────────────────────────┐
|
|
│ Header │
|
|
├────────┬───────────────────────────┤
|
|
│ │ │
|
|
│ Sidebar│ Content │
|
|
│ │ │
|
|
└────────┴───────────────────────────┘
|
|
```
|
|
|
|
### 3. Dashboard Layout
|
|
Full application dashboard with sidebar + header:
|
|
```
|
|
┌────────────────────────────────────┐
|
|
│ Header │
|
|
├────────┬───────────────────────────┤
|
|
│ │ │
|
|
│ Sidebar│ Dashboard Content │
|
|
│ │ (usually cards/widgets) │
|
|
└────────┴───────────────────────────┘
|
|
```
|
|
|
|
### 4. Blank Layout
|
|
No header/footer, just content (for custom layouts):
|
|
```
|
|
┌────────────────────────────────────┐
|
|
│ │
|
|
│ Full Content │
|
|
│ │
|
|
└────────────────────────────────────┘
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### Example 1: Create a Custom Homepage
|
|
|
|
```typescript
|
|
import { getPageRenderer } from '@/lib/page-renderer'
|
|
|
|
const customHomepage: PageDefinition = {
|
|
id: 'page_custom_home',
|
|
level: 1,
|
|
title: 'My Custom Homepage',
|
|
layout: 'default',
|
|
components: [
|
|
{
|
|
id: 'hero',
|
|
type: 'Container',
|
|
props: {
|
|
className: 'py-20 text-center bg-gradient-to-br from-blue-500 to-purple-600'
|
|
},
|
|
children: [
|
|
{
|
|
id: 'hero_title',
|
|
type: 'Heading',
|
|
props: {
|
|
level: 1,
|
|
children: 'Welcome to Our Platform',
|
|
className: 'text-5xl font-bold text-white mb-4'
|
|
},
|
|
children: []
|
|
},
|
|
{
|
|
id: 'hero_cta',
|
|
type: 'Button',
|
|
props: {
|
|
children: 'Get Started',
|
|
variant: 'default',
|
|
size: 'lg'
|
|
},
|
|
children: []
|
|
}
|
|
]
|
|
}
|
|
],
|
|
permissions: {
|
|
requiresAuth: false
|
|
},
|
|
metadata: {
|
|
showHeader: true,
|
|
showFooter: true
|
|
}
|
|
}
|
|
|
|
const renderer = getPageRenderer()
|
|
await renderer.registerPage(customHomepage)
|
|
```
|
|
|
|
### Example 2: User Dashboard with Sidebar
|
|
|
|
```typescript
|
|
const userDashboard: PageDefinition = {
|
|
id: 'page_user_dash',
|
|
level: 2,
|
|
title: 'Dashboard',
|
|
layout: 'dashboard',
|
|
components: [
|
|
{
|
|
id: 'stats_card',
|
|
type: 'Card',
|
|
props: { className: 'p-6' },
|
|
children: [
|
|
{
|
|
id: 'stats_title',
|
|
type: 'Heading',
|
|
props: { level: 2, children: 'Your Stats' },
|
|
children: []
|
|
}
|
|
]
|
|
}
|
|
],
|
|
permissions: {
|
|
requiresAuth: true,
|
|
requiredRole: 'user'
|
|
},
|
|
metadata: {
|
|
showHeader: true,
|
|
headerTitle: 'Dashboard',
|
|
sidebarItems: [
|
|
{ id: 'nav_home', label: 'Home', icon: '🏠', action: 'navigate', target: '1' },
|
|
{ id: 'nav_profile', label: 'Profile', icon: '👤', action: 'navigate', target: '2' }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example 3: Page with Lua Lifecycle Hooks
|
|
|
|
```typescript
|
|
// First, create Lua scripts in database
|
|
const onLoadScript: LuaScript = {
|
|
id: 'lua_page_analytics',
|
|
name: 'Track Page View',
|
|
code: `
|
|
function trackPageView(userId, pageId)
|
|
log("User " .. userId .. " viewed page " .. pageId)
|
|
-- Could save to database, call API, etc.
|
|
return true
|
|
end
|
|
return trackPageView
|
|
`,
|
|
parameters: [
|
|
{ name: 'userId', type: 'string' },
|
|
{ name: 'pageId', type: 'string' }
|
|
],
|
|
returnType: 'boolean'
|
|
}
|
|
|
|
await Database.addLuaScript(onLoadScript)
|
|
|
|
// Then reference it in page definition
|
|
const trackedPage: PageDefinition = {
|
|
id: 'page_tracked',
|
|
level: 2,
|
|
title: 'Tracked Page',
|
|
layout: 'default',
|
|
components: [],
|
|
luaScripts: {
|
|
onLoad: 'lua_page_analytics', // Runs when page loads
|
|
onUnload: 'lua_page_cleanup' // Runs when page unloads
|
|
},
|
|
permissions: {
|
|
requiresAuth: true
|
|
}
|
|
}
|
|
```
|
|
|
|
## Rendering a Generic Page
|
|
|
|
In `App.tsx` or any level component:
|
|
|
|
```typescript
|
|
import { GenericPage } from '@/components/GenericPage'
|
|
|
|
// Instead of:
|
|
// <Level1 onNavigate={handleNavigate} />
|
|
|
|
// Use:
|
|
<GenericPage
|
|
pageId="page_level1_home"
|
|
user={currentUser}
|
|
level={1}
|
|
onNavigate={handleNavigate}
|
|
onLogout={handleLogout}
|
|
/>
|
|
```
|
|
|
|
## Extending the System
|
|
|
|
### Add Custom Component Types
|
|
|
|
Register new component types in `component-catalog.ts`:
|
|
|
|
```typescript
|
|
{
|
|
type: 'VideoPlayer',
|
|
label: 'Video Player',
|
|
icon: 'Play',
|
|
category: 'Media',
|
|
allowsChildren: false,
|
|
defaultProps: {
|
|
src: '',
|
|
controls: true
|
|
},
|
|
propSchema: [
|
|
{ name: 'src', label: 'Video URL', type: 'string' },
|
|
{ name: 'controls', label: 'Show Controls', type: 'boolean' }
|
|
]
|
|
}
|
|
```
|
|
|
|
Then add rendering logic in `RenderComponent.tsx`:
|
|
|
|
```typescript
|
|
case 'VideoPlayer':
|
|
return (
|
|
<video
|
|
src={props.src}
|
|
controls={props.controls}
|
|
className={props.className}
|
|
/>
|
|
)
|
|
```
|
|
|
|
### Create Package-Based Pages
|
|
|
|
Create a complete application package with pages:
|
|
|
|
```typescript
|
|
const forumPackage = {
|
|
manifest: {
|
|
id: 'forum-app',
|
|
name: 'Forum Application',
|
|
version: '1.0.0'
|
|
},
|
|
content: {
|
|
pages: [
|
|
{
|
|
id: 'page_forum_home',
|
|
level: 2,
|
|
title: 'Forum Home',
|
|
layout: 'sidebar',
|
|
components: [...],
|
|
permissions: { requiresAuth: true, requiredRole: 'user' }
|
|
},
|
|
{
|
|
id: 'page_forum_thread',
|
|
level: 2,
|
|
title: 'Thread View',
|
|
layout: 'default',
|
|
components: [...],
|
|
permissions: { requiresAuth: true, requiredRole: 'user' }
|
|
}
|
|
],
|
|
luaScripts: [
|
|
// Forum-specific scripts
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Benefits
|
|
|
|
### 🚀 Flexibility
|
|
- Pages can be modified from Level 4/5 GUI
|
|
- No code deployment needed
|
|
- Real-time preview of changes
|
|
|
|
### 🔒 Security
|
|
- Permission checks at page level
|
|
- Role-based access control
|
|
- Custom Lua permission logic
|
|
|
|
### 📦 Packages
|
|
- Distribute complete applications as packages
|
|
- Forum, blog, e-commerce as installable packages
|
|
- Community-shareable templates
|
|
|
|
### ⚡ Performance
|
|
- Pages loaded on-demand
|
|
- Lua scripts cached
|
|
- Component tree optimized
|
|
|
|
### 🛠️ Developer Experience
|
|
- Clear separation of concerns
|
|
- Type-safe definitions
|
|
- Easy to test and debug
|
|
|
|
## Migration Path
|
|
|
|
### Phase 1: ✅ COMPLETE (Iteration 24)
|
|
- ✅ Created `PageRenderer` system
|
|
- ✅ Created `GenericPage` component
|
|
- ✅ Created `PageDefinitionBuilder`
|
|
- ✅ Created default Level 1-3 pages
|
|
|
|
### Phase 2: 🚧 IN PROGRESS
|
|
- [ ] Update `App.tsx` to use `GenericPage` instead of Level1/2/3
|
|
- [ ] Add page management UI in Level 4/5
|
|
- [ ] Allow god users to edit page definitions
|
|
- [ ] Add visual page builder drag-and-drop
|
|
|
|
### Phase 3: 📋 PLANNED
|
|
- [ ] Remove `Level1.tsx`, `Level2.tsx`, `Level3.tsx` files
|
|
- [ ] Create more default page templates
|
|
- [ ] Build page marketplace/library
|
|
- [ ] Add page versioning and rollback
|
|
|
|
## Comparison: Before vs After
|
|
|
|
### Level 1 Homepage - Before
|
|
```tsx
|
|
// Level1.tsx - 300+ lines of hardcoded TSX
|
|
export function Level1({ onNavigate }: Level1Props) {
|
|
return (
|
|
<div className="min-h-screen">
|
|
<header>...</header>
|
|
<section className="hero">
|
|
<h1>Welcome to MetaBuilder</h1>
|
|
{/* Hardcoded content */}
|
|
</section>
|
|
<footer>...</footer>
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
### Level 1 Homepage - After
|
|
```tsx
|
|
// App.tsx - Generic, data-driven
|
|
<GenericPage
|
|
pageId="page_level1_home"
|
|
user={null}
|
|
level={1}
|
|
onNavigate={handleNavigate}
|
|
/>
|
|
|
|
// Page definition stored in database, fully customizable
|
|
```
|
|
|
|
## Next Steps
|
|
|
|
To complete the migration:
|
|
|
|
1. **Update App.tsx** to use `GenericPage` for levels 1-3
|
|
2. **Add Page Builder UI** in Level 4/5 panels
|
|
3. **Create Page Templates** for common layouts
|
|
4. **Build Page Editor** with drag-and-drop
|
|
5. **Test Thoroughly** before removing old TSX files
|
|
|
|
## Conclusion
|
|
|
|
The Generic Page System represents a major architectural improvement:
|
|
- **Less hardcoded TSX** = more flexibility
|
|
- **Declarative pages** = easier to maintain
|
|
- **Database-driven** = dynamic without deployment
|
|
- **Package system** = shareable applications
|
|
|
|
This moves MetaBuilder closer to being a true "no-code" platform where the builder UI (Levels 4-5) is the only hardcoded TSX, and everything else is procedurally generated from data.
|