Session 19.2 - Implementation Plan
Detailed plan to fix Universe vs Module architecture in vibe-universe-generator
Session 19.2: Implementation Plan
🎯 Goal
Transform the vibe-universe-generator from creating a single "platform module" to properly creating a Universe with separate Modules.
📊 Current vs Target Architecture
Current (WRONG)
// Saves ONE module called "Fitness Management"
ModuleContext {
moduleId: "fitness-management-1767058598901",
moduleName: "Fitness Management",
entities: [Member, Trainer, Class, ...], // ALL entities mixed together
actions: [...], // ALL actions mixed together
embeddables: [...] // ALL embeddables mixed together
}
// Saved to: module-context:fitness-management-1767058598901
// Problem: This is NOT a module, it's a platform!
Target (CORRECT)
// 1. Create UNIVERSE
Universe {
_id: "universe-fitness-management-1767058598901",
name: "Fitness Management",
slug: "fitness-management",
modules: [
"mod-member-management-xxx",
"mod-trainer-management-xxx",
"mod-class-schedule-xxx",
...
],
structure: [...], // Module tree
spaceId: "69250a03857479fe44376823"
}
// 2. Create 7 separate MODULES
SpaceModule {
_id: "mod-member-management-xxx",
name: "Member Management",
slug: "member-management",
universeId: "universe-fitness-management-1767058598901",
scope: "universe",
defaultConfig: {
entities: [Member],
actions: [CreateMember, UpdateMember, ...],
embeddables: [MemberList, MemberCard, ...]
}
}
// ... repeat for each module
🔧 Implementation Steps
Phase 1: Refactor deployToUniverse() Method
Current Issues:
- Creates universe but doesn't save modules properly
- Uses
PlatformStateService.addModuleToPlatform()which is for modularity-lib - Doesn't link modules to universe
New Implementation:
async deployToUniverse(): Promise<void> {
const manifest = this.generatedManifest();
const platformName = manifest.name;
const platformSlug = platformName.toLowerCase().replace(/\s+/g, '-');
// Step 1: Create or get Universe
let universe = await this.spaceService.getUniverseBySlug(platformSlug);
if (!universe) {
universe = await this.spaceService.createUniverse({
name: platformName,
description: manifest.description
});
}
// Step 2: Extract all modules from manifest
const moduleNames = this.extractModulesFromNavigation(manifest);
const createdModuleIds: string[] = [];
// Step 3: Create each module separately
for (const moduleName of moduleNames) {
const moduleData = this.extractModuleDataFromManifest(manifest, moduleName);
// Create module in space_modules collection
const module = await firstValueFrom(
this.backendModuleApi.createSpaceModule(spaceId, {
name: moduleName,
slug: toKebabCase(moduleName),
type: 'feature-module',
description: moduleData.description,
icon: moduleData.icon,
universeId: universe.id,
scope: 'universe',
defaultConfig: {
entities: moduleData.entities,
actions: moduleData.actions,
embeddables: moduleData.embeddables
},
ai: {
description: moduleData.description,
keywords: [platformName, moduleName],
capabilities: moduleData.entities.map(e => e.name),
complexity: 'moderate',
suggestionWeight: 80
}
})
);
createdModuleIds.push(module._id);
}
// Step 4: Update universe with modules
await firstValueFrom(
this.backendUniverseApi.updateUniverse(spaceId, universe.id, {
modules: createdModuleIds,
moduleTreeVersion: universe.moduleTreeVersion + 1
})
);
// Step 5: Navigate to universe canvas
this.router.navigate(['/space', spaceSlug, 'universe', platformSlug, 'canvas']);
}
Phase 2: Fix editModule() Method
Current: Creates a ModuleContext (for modularity-lib workbench) Target: Navigate to the actual generated module in the universe
New Implementation:
async editModule(moduleName: string): Promise<void> {
const manifest = this.generatedManifest();
const platformSlug = manifest.name.toLowerCase().replace(/\s+/g, '-');
// Find the module in space_modules
const modules = await firstValueFrom(
this.backendModuleApi.getSpaceModules(spaceId, {
universeId: `universe-${platformSlug}-xxx`,
name: moduleName
})
);
if (modules.length === 0) {
this.toast.error('Module not found');
return;
}
const module = modules[0];
// Navigate to module in context of universe
this.router.navigate([
'/space', spaceSlug,
'universe', platformSlug,
'module', module.slug
]);
}
Phase 3: Fix proceedToWorkbench() Method
Current: Creates a single ModuleContext with all platform data Target: Navigate to universe canvas where user can arrange modules
New Implementation:
async proceedToWorkbench(): Promise<void> {
const manifest = this.generatedManifest();
const platformSlug = manifest.name.toLowerCase().replace(/\s+/g, '-');
const spaceSlug = this.universeContext.spaceSlug();
// Navigate to universe canvas (modular-universe)
this.router.navigate([
'/space', spaceSlug,
'universe', platformSlug,
'canvas'
], {
queryParams: {
source: 'vibe-universe-generator',
newlyGenerated: 'true'
}
});
}
Phase 4: Enhance Module Cards
Add to each module card:
interface ModuleCardData {
name: string;
description: string;
icon: string;
// Counts
entityCount: number;
actionCount: number;
embeddableCount: number;
// Status
status: 'draft' | 'ready' | 'deployed';
// Links
moduleId: string;
universeId: string;
universeName: string;
}
🗄️ MongoDB Schema Alignment
Universe Document
{
_id: "universe-fitness-management-1767058598901",
name: "Fitness Management",
slug: "fitness-management",
description: "Complete fitness management platform",
spaceId: "69250a03857479fe44376823",
// Module references (IDs only)
modules: [
"mod-member-management-xxx",
"mod-trainer-management-xxx",
...
],
// Structure (tree)
structure: [
{
moduleId: "mod-member-management-xxx",
order: 1,
config: {}
},
...
],
deploymentStatus: "draft",
moduleTreeVersion: 1,
moduleSchemaVersion: "2025.12"
}
Module Document
{
_id: "mod-member-management-xxx",
name: "Member Management",
slug: "member-management",
type: "feature-module",
description: "Manage gym members with profiles and memberships",
icon: "fas fa-users",
// Link to universe
spaceId: "69250a03857479fe44376823",
universeId: "universe-fitness-management-1767058598901",
scope: "universe",
// Module data
defaultConfig: {
entities: [
{
id: "entity-member-xxx",
name: "Member",
fields: [...]
}
],
actions: [
{
id: "action-create-member-xxx",
name: "CreateMember",
...
}
],
embeddables: [
{
id: "emb-member-list-xxx",
name: "MemberList",
...
}
]
},
// AI metadata
ai: {
description: "Manage gym members",
keywords: ["fitness", "member", "gym"],
capabilities: ["Member"],
complexity: "moderate",
suggestionWeight: 80
},
isActive: true,
order: 1
}
🔄 Service Integration
Services to Use
| Service | Purpose | Method |
|---|---|---|
SpaceService |
Create universe | createUniverse(data) |
BackendUniverseApiService |
Update universe | updateUniverse(spaceId, universeId, updates) |
BackendModuleApiService |
Create modules | createSpaceModule(spaceId, moduleData) |
UniverseModuleService |
Link modules to universe | install(universeId, moduleData) |
Proper Flow
// 1. Create Universe
const universe = await this.spaceService.createUniverse({
name: platformName,
description: manifest.description
});
// 2. Create each Module
for (const moduleName of moduleNames) {
const moduleData = extractModuleDataFromManifest(manifest, moduleName);
// Save to space_modules
const module = await firstValueFrom(
this.backendModuleApi.createSpaceModule(spaceId, {
...moduleData,
universeId: universe.id,
scope: 'universe'
})
);
moduleIds.push(module._id);
}
// 3. Update Universe with module IDs
await firstValueFrom(
this.backendUniverseApi.updateUniverse(spaceId, universe.id, {
modules: moduleIds
})
);
// 4. Navigate to universe canvas
this.router.navigate(['/space', spaceSlug, 'universe', universe.slug, 'canvas']);
🎨 UI Changes
Platform Summary Component
Before:
- Shows "Fitness Management" as a single entity
- "Edit Module" tries to edit the whole platform
After:
- Shows "Fitness Management Universe" with 7 modules
- Each module card shows:
- Module name
- Description
- Entity/Action/Embeddable counts
- "Edit Module" → Navigate to that specific module
- "View in Universe" → Navigate to universe canvas
Module Card Enhancement
<div class="module-card">
<div class="module-header">
<i class="fas {{ module.icon }}"></i>
<h4>{{ module.name }}</h4>
</div>
<p class="module-description">{{ module.description }}</p>
<div class="module-stats">
<span><i class="fas fa-database"></i> {{ module.entityCount }} entities</span>
<span><i class="fas fa-bolt"></i> {{ module.actionCount }} actions</span>
<span><i class="fas fa-th-large"></i> {{ module.embeddableCount }} components</span>
</div>
<div class="module-actions">
<button (click)="editModule(module)">
<i class="fas fa-edit"></i> Edit
</button>
<button (click)="previewModule(module)">
<i class="fas fa-eye"></i> Preview
</button>
</div>
</div>
✅ Success Criteria
- Universe created in
universescollection - Each module created in
space_modulescollection - Modules linked to universe via
universeId - Module cards show proper metadata
- "Deploy to Universe" navigates to universe canvas
- "Edit Module" navigates to specific module
- Page reload preserves all data
- MongoDB sync works offline/online
📁 Files to Modify
| File | Changes |
|---|---|
vibe-universe-generator.component.ts |
Refactor deployToUniverse(), editModule(), proceedToWorkbench() |
platform-summary.component.ts |
Enhance module cards with metadata |
platform-summary.component.html |
Update UI to show module details |
Confidence Level: 97%
This architecture aligns with the Building Blocks Architecture and ensures proper separation of concerns.