Building Blocks Vision - Composable Architecture
Everything is a building block that composes into more complex building blocks
Building Blocks Vision - Composable Architecture
🎯 The Vision
Everything is a building block that helps build more complex building blocks.
The Composition Hierarchy
PROPERTIES
↓ compose into
WIDGETS
↓ compose into
COMPLEX WIDGETS (with children)
↓ embed into
MODULES
↓ compose into
COMPLEX MODULES (with children)
↓ compose into
PLATFORMS
🧱 Level 1: Properties (Atomic Building Blocks)
Storage Strategy
Global Property Templates:
Database: gograb-core
Collection: core_property_templates
Purpose: Reusable across ALL spaces
Examples:
- "sizing-dimensions" (width, height, min/max)
- "colors-basic" (backgroundColor, textColor, borderColor)
- "typography-text" (fontSize, fontFamily, fontWeight)
- "spacing-padding" (paddingTop, paddingRight, etc.)
Custom Properties (Per Space):
Database: space_{spaceId}
Collection: custom_properties
Purpose: Space-specific custom properties
Examples:
- Custom brand colors
- Custom spacing scales
- Space-specific behaviors
Property Template Structure
// In gograb-core.core_property_templates
{
_id: "template-sizing-dimensions",
id: "sizing-dimensions",
name: "Sizing & Dimensions",
description: "Control widget width and height",
category: "layout",
icon: "fa-arrows-alt",
scope: "global", // ✅ Global, shared by all spaces
properties: [
{
id: "prop-width",
key: "width",
label: "Width",
controlType: "number",
category: "layout",
defaultValue: 100,
validation: { min: 0 },
aiMetadata: {
importance: "essential",
useCases: ["Set widget width", "Control dimensions"],
sampleValues: ["100", "200", "50%"]
}
},
{
id: "prop-height",
key: "height",
label: "Height",
controlType: "number",
category: "layout",
defaultValue: 100,
validation: { min: 0 }
}
],
widgetTypes: ["button", "text", "image", "container"], // Applicable to these
usageCount: 1250, // Analytics
metadata: {
created: "2025-12-18T00:00:00Z",
modified: "2025-12-18T00:00:00Z",
author: "system",
version: "1.0.0"
}
}
🎨 Level 2: Widgets (Component Building Blocks)
Widget = UI Component + Adapter
// Pure UI Component (from ui-core)
@Component({
selector: 'ux-button',
template: '<button>{{ text }}</button>'
})
export class UxButtonComponent {
@Input() text = 'Click';
@Input() variant = 'primary';
@Output() clicked = new EventEmitter();
}
// Adapter (bridges to editor)
const BUTTON_ADAPTER: EditorWidgetAdapter = {
id: 'button',
name: 'Button',
component: UxButtonComponent,
// ✅ References GLOBAL property templates!
propertyTemplateIds: [
'content-text', // From gograb-core
'colors-button', // From gograb-core
'sizing-dimensions', // From gograb-core
],
capabilities: {
supportsChildren: false,
supportsResize: true,
supportsDrag: true,
},
defaultSize: { width: 120, height: 40 },
defaultProperties: { text: 'Click Me', variant: 'primary' },
};
Result: Button widget can be used in editor with:
- Drag/drop
- Resize
- Properties from backend templates
- Clean, reusable
📦 Level 3: Complex Widgets (Widgets with Children)
Container Widget
// Simple container component
@Component({
selector: 'ux-container',
template: `
<div class="container">
<ng-content></ng-content> <!-- Children go here -->
</div>
`
})
export class UxContainerComponent {
@Input() padding = 10;
@Input() gap = 10;
@Input() layout: 'free' | 'flex' | 'grid' = 'free';
}
// Container adapter
const CONTAINER_ADAPTER: EditorWidgetAdapter = {
id: 'container',
component: UxContainerComponent,
propertyTemplateIds: [
'sizing-dimensions',
'spacing-padding',
'spacing-gap',
'layout-container', // Layout type, alignment, distribution
],
capabilities: {
supportsChildren: true, // ✅ KEY!
},
childrenConfig: {
acceptedAdapters: undefined, // All widgets accepted
layoutTypes: ['free', 'flex', 'grid', 'masonry'],
defaultLayout: 'free',
defaultGap: 10,
defaultPadding: 10,
},
};
Usage:
// Create container with button inside
const container: EditorWidget = {
id: 'container-1',
adapterId: 'container',
properties: { layout: 'flex', padding: 20 },
childIds: ['button-1'], // ✅ Has children!
};
const button: EditorWidget = {
id: 'button-1',
adapterId: 'button',
properties: { text: 'Click' },
parentId: 'container-1', // ✅ Parent reference
};
// EditorWidgetWrapper automatically:
// - Renders container component
// - Renders button inside it
// - Handles drag/drop into container
// - Manages hierarchy
🔧 Level 4: Modules (Widget Collections)
Widgets embed into modules:
// Page Module
const pageModule: UniversalModule = {
id: 'page-home',
type: 'page-module',
content: {
widgets: [
container, // Container with children
button,
text,
],
},
};
// Module can reference other modules
const galaxyModule: UniversalModule = {
id: 'galaxy-main',
type: 'galaxy',
children: [
{ moduleId: 'page-home' },
{ moduleId: 'page-about' },
],
};
🏢 Level 5: Platforms (Module Hierarchies)
Platform Root
└─ Galaxy (Marketing)
├─ Page (Home)
│ └─ Widgets: [Hero, Features, CTA]
├─ Page (About)
│ └─ Widgets: [Team, Story]
└─ Page (Contact)
└─ Widgets: [Form, Map]
🎯 Property Management UI (NEW)
Location
Create new Nx library: libs/libs-ui/property-manager
Features
Property Templates Browser
- View all global templates (from gograb-core)
- Search, filter, category
- Preview properties in each template
- Usage analytics
Property Template Editor
- Create new global templates
- Edit existing templates
- Add/remove properties
- Set categories, icons, metadata
- Preview in widget context
Custom Properties Manager (Per Space)
- Create space-specific custom properties
- Attach to widgets
- Override global templates if needed
Property Analytics
- Most used templates
- Most used properties
- AI generation patterns
- Optimization suggestions
Routes
{
path: 'properties',
children: [
{ path: '', component: PropertiesDashboard },
{ path: 'templates', component: TemplatesBrowser },
{ path: 'templates/new', component: TemplateEditor },
{ path: 'templates/:id', component: TemplateEditor },
{ path: 'custom', component: CustomPropertiesManager },
{ path: 'analytics', component: PropertyAnalytics },
]
}
📊 Updated Storage Architecture
┌─────────────────────────────────────────────────────┐
│ MONGO STORAGE │
├─────────────────────────────────────────────────────┤
│ │
│ gograb-core Database (GLOBAL) │
│ ═══════════════════════════════════════════════ │
│ ├─ core_property_templates │
│ │ ├─ sizing-dimensions │
│ │ ├─ colors-basic │
│ │ ├─ typography-text │
│ │ ├─ spacing-padding │
│ │ └─ ... (50+ reusable templates) │
│ │ │
│ ├─ core_widget_adapters │
│ │ ├─ button-adapter │
│ │ ├─ text-adapter │
│ │ ├─ container-adapter │
│ │ └─ ... (core adapters) │
│ │ │
│ └─ core_modules (if global modules) │
│ │
├─────────────────────────────────────────────────────┤
│ │
│ space_{spaceId} Database (PER SPACE) │
│ ═══════════════════════════════════════════════ │
│ ├─ custom_properties │
│ │ └─ Space-specific custom properties │
│ │ │
│ ├─ custom_adapters │
│ │ └─ Custom widget adapters for this space │
│ │ │
│ ├─ space_pages │
│ │ └─ Pages with EditorWidgets (lightweight!) │
│ │ │
│ └─ space_modules │
│ └─ Space-specific modules │
│ │
└─────────────────────────────────────────────────────┘
🔄 The Composition Flow
Example: Creating a Login Form
1. PROPERTIES (from gograb-core.core_property_templates)
├─ "sizing-dimensions" template
├─ "colors-form" template
├─ "spacing-padding" template
└─ "form-validation" template
2. BASIC WIDGETS (using properties)
├─ Input widget (uses sizing + colors + validation)
├─ Button widget (uses sizing + colors)
└─ Text widget (uses typography + colors)
3. CONTAINER WIDGET (contains basic widgets)
├─ Form Container (uses layout + spacing)
│ ├─ Email Input (child widget)
│ ├─ Password Input (child widget)
│ └─ Submit Button (child widget)
4. MODULE (embeds container widget)
├─ Login Module
│ └─ content.widgets: [FormContainer]
5. PLATFORM (composes modules)
└─ Auth Platform
├─ Login Module
├─ Register Module
└─ Reset Password Module
The Beauty
- Change color in property template → ALL widgets get new color option
- Create new widget → Can immediately be used in containers
- Create container variant → Can be used in modules
- Create module → Can be composed into platforms
Everything flows up the composition chain!
🚀 Implementation Plan (Updated)
Phase 1: Property Templates System
Backend (gograb-core):
// apis/backend-api/src/app/core-properties/
├─ core-properties.module.ts
├─ core-properties.controller.ts
├─ core-properties.service.ts
└─ templates/
├─ sizing.templates.ts
├─ colors.templates.ts
├─ typography.templates.ts
└─ layout.templates.ts
API Endpoints:
GET /api/core/property-templates - List all global templates
GET /api/core/property-templates/:id - Get template
POST /api/core/property-templates/seed - Seed built-in templates
Phase 2: Property Manager UI
Create: libs/libs-ui/property-manager
// libs/libs-ui/property-manager/src/lib/
├─ components/
│ ├─ property-templates-browser/
│ ├─ property-template-editor/
│ ├─ custom-properties-manager/
│ └─ property-analytics/
├─ services/
│ ├─ core-templates-api.service.ts
│ └─ custom-properties-api.service.ts
└─ property-manager.routes.ts
Routes:
{
path: 'properties',
loadChildren: () => import('@libs-ui/property-manager').then(m => m.routes)
}
Phase 3: Widget Adapters V2
Create: libs/libs-widgets/editor-widgets-v2
// libs/libs-widgets/editor-widgets-v2/src/lib/
├─ core/
│ ├─ editor-widget-adapter.interface.ts
│ ├─ editor-widget.model.ts // Clean EditorWidget interface
│ └─ editor-widget-wrapper.component.ts // Universal wrapper!
├─ adapters/
│ ├─ button.adapter.ts
│ ├─ text.adapter.ts
│ ├─ image.adapter.ts
│ ├─ input.adapter.ts
│ └─ container.adapter.ts // ✅ With children support!
├─ services/
│ ├─ widget-adapters-registry.service.ts
│ ├─ property-template-loader.service.ts
│ └─ widget-hydration.service.ts
└─ components/
├─ editor-widget-chrome/ // Selection UI, handles
└─ children-container/ // Universal children renderer
Phase 4: Building Blocks UI (NEW)
Create: libs/libs-ui/building-blocks-manager
Purpose: Central hub to manage all building blocks
Dashboard:
├─ Properties
│ ├─ Global Templates (50 templates)
│ ├─ Custom Properties (5 custom)
│ └─ Analytics
│
├─ Widgets
│ ├─ Core Widgets (using global templates)
│ ├─ Custom Widgets (AI-generated)
│ └─ Complex Widgets (with children)
│
├─ Modules
│ ├─ Page Modules (embed widgets)
│ ├─ Feature Modules (dashboards, forms)
│ └─ Layout Modules (navigation, etc.)
│
└─ Platforms
└─ Complete applications
🎯 Revised Implementation Plan
Week 1: Foundation + Core
Day 1: Backend Property Templates
- Create core-properties module in backend-api
- Design core property templates (sizing, colors, typography, spacing, layout)
- Seed gograb-core.core_property_templates
- Create API endpoints
- Test loading templates
Day 2: Property Manager UI
- Create property-manager library
- Implement templates browser
- Implement template editor
- Implement custom properties manager
- Integrate with backend API
Day 3: Widget Adapters Foundation
- Create editor-widgets-v2 library
- Implement EditorWidgetAdapter interface
- Implement EditorWidget model (clean, sparse)
- Implement WidgetAdaptersRegistry
- Implement PropertyTemplateLoader service
Day 4: Universal Wrapper
- Implement EditorWidgetWrapperComponent
- Implement universal children rendering
- Implement editor chrome (selection, handles)
- Test with mock adapters
Day 5: Core Adapters
- Button adapter (wrap UxButtonComponent)
- Text adapter (create or wrap existing)
- Image adapter
- Input adapter
- Container adapter (WITH children support!)
Day 6: Integration
- Integrate with Widget Builder
- Integrate with Editor Canvas
- Test widget creation flow
- Test container + children nesting ⭐
- Test all adapters
Day 7: Testing & Polish
- Complete end-to-end testing
- Migration script for old widgets
- Documentation
- Code review
💎 The Beauty of This Architecture
1. Properties are Reusable
// Create "sizing-dimensions" once in gograb-core
// Used by:
✅ Button widget
✅ Text widget
✅ Image widget
✅ Container widget
✅ ALL future widgets
// Update "sizing-dimensions" template
// ALL widgets get the update automatically!
2. Widgets are Composable
// Button widget (no children)
{
adapterId: 'button',
properties: { text: 'Submit' }
}
// Container widget (HAS children)
{
adapterId: 'container',
properties: { layout: 'flex', gap: 10 },
childIds: ['button-1', 'input-1', 'input-2']
}
// ANY widget can become complex by:
// 1. Setting supportsChildren: true in adapter
// 2. Adding childrenConfig
// That's it! Universal wrapper handles the rest!
3. Modules Embed Widgets
// Page module references widgets
{
type: 'page-module',
content: {
widgetIds: ['container-1', 'hero-1', 'footer-1']
}
}
// Widgets can be reused across modules!
4. Everything is Expandable
Want a new property type?
- Add to core_property_templates
- ALL widgets can use it
- Property Manager UI updates automatically
Want a new widget?
- Create adapter (or use Widget Builder AI)
- References existing property templates
- Immediately usable in editor
- Can be made complex by enabling children
Want a new module type?
- Create module manifest
- Can embed any widgets
- Can have child modules
The system SCALES infinitely!
📋 First Steps (Starting Now!)
Step 1: Backend Core Properties
cd apis/backend-api/src/app
mkdir core-properties
Create:
core-properties.module.tscore-properties.controller.tscore-properties.service.ts- Seed templates
Step 2: Property Manager UI
npx nx g @nx/angular:library property-manager --directory=libs/libs-ui
Create browser + editor for property templates
Step 3: Editor Widgets V2
npx nx g @nx/angular:library editor-widgets-v2 --directory=libs/libs-widgets
Create clean architecture
✅ You're Absolutely Right
Your vision is PERFECT:
- ✅ Properties in gograb-core - Global, reusable
- ✅ Custom properties per space - When needed
- ✅ Property Manager UI - View/edit/create
- ✅ Everything composes - Properties → Widgets → Modules → Platforms
This is elegant, scalable, and maintainable!
Ready to start building? Say "GO" and I'll begin with the backend core properties! 🚀
Session: 11.9
Date: December 18, 2025
Status: Vision clarified, architecture refined, ready to implement