Widgets Backend Analysis
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
Backend API Widget Architecture - Complete Analysis
Date: December 9, 2025
Session: 9
Status: ✅ Analysis Complete
🎯 Executive Summary
The backend has a three-tier widget architecture that was not fully documented:
- Global Widgets - Platform-wide widgets (gograb-api database)
- Space Widgets - Per-space custom widgets (space-specific databases)
- Widget Modules - Modular wrappers around widgets (space-specific databases)
📊 Backend Storage Architecture
Database Structure
┌─────────────────────────────────────────────────────────────────────────────┐
│ DATABASE: gograb-api (Platform Database) │
├─────────────────────────────────────────────────────────────────────────────┤
│ Collection: widgets (Global Widgets) │
│ Schema: GlobalWidget │
│ Purpose: Platform-wide reusable widgets │
│ Examples: Button, Input, Card, etc. │
│ │
│ Fields: │
│ - _id (string, unique) │
│ - name, version, type, description, icon, category │
│ - defaultConfig (Record<string, unknown>) │
│ - propertyConfig (WidgetPropertyConfig) │
│ - variants (WidgetVariant[]) │
│ - defaultVariant (string) │
│ - ai (ResourceAIMetadata) │
│ - isCore, isPremium, isPublic, isActive │
│ - author, tags │
│ - createdAt, updatedAt │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ DATABASE: space_{spaceId}_{shortId} (Per-Space Database) │
├─────────────────────────────────────────────────────────────────────────────┤
│ Collection: space_widgets (Space Widgets) │
│ Purpose: Custom widgets created by space users │
│ API Endpoints: /api/spaces/:spaceId/widgets │
│ │
│ Fields: │
│ - id (string) - widget_{timestamp}_{random} │
│ - name, type, category, description, icon │
│ - spaceId (string) │
│ - scope ('private' | 'public') │
│ - variants (array of variant objects) │
│ - defaultVariant (string) │
│ - defaultConfig (Record<string, unknown>) │
│ - propertyConfig (object) │
│ - groups (PropertyGroup[]) │
│ - values (Record<string, unknown>) │
│ - usage (object) │
│ - usedInUniverses (string[]) │
│ - usedInPages (string[]) │
│ - instanceCount (number) │
│ - metadata (object) │
│ - created, modified, author, version, tags │
│ │
│ Collection: widget_modules (Widget Modules) │
│ Purpose: Modular wrappers around widgets with embeddable components │
│ API Endpoints: /api/spaces/:spaceId/widget-modules │
│ │
│ Fields: │
│ - id (string) - wm_{timestamp}_{random} │
│ - name, description, version, type, icon, category, tags │
│ - spaceId (string) │
│ - scope ('private' | 'public') │
│ - sourceWidgetId (string) - references space_widgets │
│ - sourceWidgetType (string) │
│ - embeddableComponents (array) │
│ - inputs (array) - module parameter metadata │
│ - outputs (array) - module output metadata │
│ - defaultConfig (Record<string, unknown>) │
│ - propertyGroups (array) │
│ - usage (object) │
│ - installCount, usedInUniverses, usedInSpaces │
│ - metadata (created, modified, author, license, repository, docs) │
│ - dependencies (string[]) │
└─────────────────────────────────────────────────────────────────────────────┘
🔌 Backend API Endpoints
Global Widgets API
Service: GlobalResourcesService
Controller: GlobalResourcesController
Base Path: /api/global-resources/
GET /api/global-resources/widgets // List all global widgets
GET /api/global-resources/widgets/:id // Get global widget
POST /api/global-resources/widgets // Create global widget
PUT /api/global-resources/widgets/:id // Update global widget
DELETE /api/global-resources/widgets/:id // Delete global widget
Space Widgets API
Service: WidgetsService
Controller: WidgetsController
Base Path: /api/spaces/:spaceId/widgets
GET /api/spaces/:spaceId/widgets // List space widgets
GET /api/spaces/:spaceId/widgets/:id // Get widget
POST /api/spaces/:spaceId/widgets // Create widget
PUT /api/spaces/:spaceId/widgets/:id // Update widget
DELETE /api/spaces/:spaceId/widgets/:id // Delete widget
Widget Modules API
Service: WidgetModulesService
Controller: WidgetModulesController
Base Path: /api/spaces/:spaceId/widget-modules
GET /api/spaces/:spaceId/widget-modules // List modules
GET /api/spaces/:spaceId/widget-modules/:id // Get module
POST /api/spaces/:spaceId/widget-modules // Create module
PUT /api/spaces/:spaceId/widget-modules/:id // Update module
DELETE /api/spaces/:spaceId/widget-modules/:id // Delete module
GET /api/spaces/:spaceId/widget-modules/by-source/:widgetId // Get by source widget
Core Widgets API
Service: CoreWidgetsService
Database: gograb-api
Collection: core_widgets
Internal service for managing core/built-in widgets.
📦 Widget Data Model
CreateWidgetDto (Frontend → Backend)
interface CreateWidgetDto {
id?: string;
name: string;
type: string;
category: string;
description?: string;
icon?: string;
scope?: 'private' | 'public';
variants?: Array<{
id: string;
name: string;
description?: string;
properties: Record<string, unknown>;
preview?: string;
createdAt?: string;
updatedAt?: string;
}>;
defaultVariant?: string;
defaultConfig?: Record<string, unknown>;
propertyConfig?: {
groups: Array<{
id: string;
title: string;
properties: Array<{
key: string;
label: string;
type: string;
defaultValue?: unknown;
}>;
}>;
values: Record<string, unknown>;
};
metadata?: {
author?: string;
version?: string;
tags?: string[];
};
}
WidgetResponse (Backend → Frontend)
interface WidgetResponse {
id: string;
name: string;
type: string;
category: string;
description: string;
icon: string;
spaceId: string;
scope: 'private' | 'public';
variants: Array<{
id: string;
name: string;
description: string;
properties: Record<string, unknown>;
preview?: string;
createdAt: string;
updatedAt: string;
}>;
defaultVariant: string;
defaultConfig: Record<string, unknown>;
propertyConfig: {
groups: Array<{
id: string;
title: string;
properties: Array<{
key: string;
label: string;
type: string;
defaultValue?: unknown;
}>;
}>;
values: Record<string, unknown>;
};
usage: {
usedInUniverses: string[];
usedInPages: string[];
instanceCount: number;
};
metadata: {
created: string;
modified: string;
author: string;
version: string;
tags: string[];
};
}
🔄 The Three-Tier Architecture
Tier 1: Global Widgets (Platform Level)
Purpose: Platform-wide reusable widgets
Database: gograb-api
Collection: widgets
Managed By: GoGrab Team
Examples: Button, Input, Card, Hero, Gallery
Characteristics:
- ✅ Maintained by platform
- ✅ Available to all spaces
- ✅ Core functionality
- ✅ Versioned
- ✅ Can be public or premium
Tier 2: Space Widgets (Space Level)
Purpose: Custom widgets created by space users
Database: space_{spaceId}_{shortId}
Collection: space_widgets
Managed By: Space users
Examples: Custom contact form, pricing table, etc.
Characteristics:
- ✅ Stored in MongoDB (not NX libraries)
- ✅ Per-space isolation
- ✅ Can be private or public within space
- ✅ Supports variants
- ✅ Property groups for configuration
- ✅ Usage tracking
Tier 3: Widget Modules (Module Level)
Purpose: Modular wrappers around widgets
Database: space_{spaceId}_{shortId}
Collection: widget_modules
Managed By: Space users
Characteristics:
- ✅ References a source widget (sourceWidgetId)
- ✅ Adds embeddable components
- ✅ Adds inputs/outputs (module parameters)
- ✅ Property groups integration
- ✅ Dependency tracking
- ✅ Can be installed/shared
Key Difference: Widget Modules wrap widgets to make them modular and embeddable in other contexts.
💡 Key Insights
1. Widget Modules Already Exist!
The backend already has a WidgetModulesService that wraps widgets into modular components. This is the missing link between simple widgets and the module system.
Flow:
Widget Builder → Creates Space Widget → Optionally wraps in Widget Module
2. Variants Are Built Into Backend
The backend fully supports variants:
- Stored in
variantsarray - Each variant has properties, preview, timestamps
defaultVariantfield points to default
The frontend just needs to connect to this!
3. Property Groups Are Backend-Supported
The backend stores property groups in propertyConfig.groups:
propertyConfig: {
groups: [{
id: 'appearance',
title: 'Appearance',
properties: [
{ key: 'color', label: 'Color', type: 'color', defaultValue: '#000' }
]
}],
values: { color: '#ff0000' }
}
4. The Missing NX Library Generation
What's NOT in the backend:
- ❌ NX library structure generation
- ❌
project.json,tsconfig.lib.jsonfile generation - ❌ BrowserModuleContract code generation
- ❌ Workspace registration
This is the gap identified in Priority 5.
🎯 How Frontend Should Use Backend
For Simple Widgets (Current)
// Widget Builder saves to space_widgets
const widget = await http.post(`/api/spaces/${spaceId}/widgets`, {
name: 'My Widget',
type: 'custom',
category: 'content',
variants: [{ /* variant */ }],
propertyConfig: { /* property groups */ }
});
For Widget Modules (Should Add)
// After creating widget, optionally create module wrapper
const widgetModule = await http.post(`/api/spaces/${spaceId}/widget-modules`, {
name: 'My Widget Module',
sourceWidgetId: widget.id,
embeddableComponents: [{ /* embeddable */ }],
inputs: [{ /* inputs */ }],
outputs: [{ /* outputs */ }]
});
For Variants (Should Add to Frontend)
// Smart Variant Creator should save to backend
const widget = await http.get(`/api/spaces/${spaceId}/widgets/${widgetId}`);
// Add new variant
widget.variants.push({
id: `variant_${Date.now()}`,
name: 'New Variant',
description: 'Description',
properties: { /* configured properties */ }
});
// Update widget
await http.put(`/api/spaces/${spaceId}/widgets/${widgetId}`, widget);
🔄 Complete Widget Lifecycle
┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. CREATION │
│ Widget Builder → POST /api/spaces/:spaceId/widgets │
│ └─> Saves to space_{spaceId}.space_widgets │
├─────────────────────────────────────────────────────────────────────────────┤
│ 2. VARIANT CREATION │
│ Smart Variant Creator → Update widget.variants array │
│ └─> PUT /api/spaces/:spaceId/widgets/:id │
├─────────────────────────────────────────────────────────────────────────────┤
│ 3. MODULE WRAPPING (Optional) │
│ Widget Module Creator → POST /api/spaces/:spaceId/widget-modules │
│ └─> References sourceWidgetId │
├─────────────────────────────────────────────────────────────────────────────┤
│ 4. USAGE │
│ Page Editor → Uses widget via WidgetHostComponent │
│ └─> Loads from embeddable registry or backend │
├─────────────────────────────────────────────────────────────────────────────┤
│ 5. USAGE TRACKING │
│ Backend tracks usage.usedInUniverses, usage.usedInPages │
│ └─> Updated automatically when widget is used │
└─────────────────────────────────────────────────────────────────────────────┘
🎯 Action Items for Frontend
Priority 2: Variant Creator Integration ✅
Backend Support: ✅ Full support
API: PUT /api/spaces/:spaceId/widgets/:id
Implementation: Update variants array in widget
Priority 3: Widget Builder Consolidation
Backend Support: ✅ Full support
API: POST /api/spaces/:spaceId/widgets
Ensure: Property groups are saved in propertyConfig.groups
Priority 5: Widget Module Integration
Backend Support: ✅ Full support via WidgetModulesService
API: POST /api/spaces/:spaceId/widget-modules
Implementation: Add "Save as Module" option that creates widget module
📊 Summary
The backend has a complete, robust widget system with:
- ✅ Three-tier architecture (Global/Space/Module)
- ✅ Full variant support
- ✅ Property groups integration
- ✅ Usage tracking
- ✅ Multi-tenant isolation
What's Missing: Frontend integration with these APIs, especially:
- Variant creation/editing UI
- Widget module creation
- NX library generation (Priority 5)
Document Version: 1.0
Session: 9
Status: ✅ Complete
Next: Implement Priority 2 using these APIs