PERSISTENCE ARCHITECTURE

Ecosistema completo para organización y gestión de contenido con interfaces espaciales

Singularity: Systematic Persistence Architecture

Date: October 8, 2025
Status: ✅ Fixed and Documented


🎯 The Systematic Approach

This document explains how we systematically fixed persistence issues in the Singularity logic builder.


🚨 The Problem

Connections were not persisting across page refreshes, despite blocks persisting correctly. This revealed a systematic architectural problem:

Root Cause: Duplicate State Management

// ❌ BAD: Two sources of truth
blockConnections: Array<LogicConnection> = [];  // Local array
canvasConnections = signal<LogicConnection[]>([]); // Flash Persistence

// Template was using the wrong one!
@for (connection of blockConnections; track ...) { }  // ❌ Local only!

Result: Connections were stored locally but never persisted to Flash Persistence.


✅ The Systematic Fix

Principle: Single Source of Truth

All persistent data MUST use Flash Persistence via SingularityService

// ✅ GOOD: Single source of truth
// NO local arrays, only Flash Persistence signals
canvasBlocks = signal<LogicBlock[]>([]);        // From Flash Persistence
canvasConnections = signal<LogicConnection[]>([]); // From Flash Persistence

Pattern Applied

// 1️⃣ Create/Update Data
const connection: LogicConnection = {
  id: generateId(),
  sourceBlock: source.id,
  targetBlock: target.id,
  // ... other fields
  createdAt: new Date(),
  updatedAt: new Date()
};

// 2️⃣ Save to Flash Persistence (Single Source of Truth)
this.singularityService.addConnection(connection);

// 3️⃣ UI updates automatically via signal reactivity
// Template: @for (connection of canvasConnections(); track ...)

📋 Architecture Checklist

✅ Data Layer (Flash Persistence)

✅ Component Layer (Logic Builder)

✅ Template Layer (HTML)


🔧 Files Modified

1. logic-builder.component.ts

Before:

❌ blockConnections: Array<LogicConnection> = [];  // Local only
❌ this.blockConnections.push(connection);          // Never persists

After:

✅ // No local array - use Flash Persistence
✅ this.singularityService.addConnection(connection); // Persists automatically

2. logic-builder.component.html

Before:

❌ @for (connection of blockConnections; track ...) { }

After:

✅ @for (connection of canvasConnections(); track ...) { }

3. updateConnectionCoordinates()

Before:

❌ this.blockConnections.forEach(connection => {
❌   connection.x1 = newX;  // Mutates local array
❌ });

After:

✅ const connections = this.canvasConnections();
✅ const updatedConnections = connections.map(conn => ({
✅   ...conn,
✅   x1: newX  // Immutable update
✅ }));
✅ this.singularityService.setConnections(updatedConnections);

🎯 The Systematic Pattern

Rule 1: Single Source of Truth

// ✅ ALWAYS use Flash Persistence
readonly blocks = computed(() => this.singularityService.blocks());

// ❌ NEVER create local copies
private myBlocks: LogicBlock[] = [];  // DON'T DO THIS!

Rule 2: Immutable Updates

// ✅ GOOD: Immutable update
this.singularityService.setBlocks([
  ...currentBlocks,
  newBlock
]);

// ❌ BAD: Mutating array
this.myBlocks.push(newBlock);

Rule 3: Automatic Persistence

// ✅ Flash Persistence handles everything
this.singularityService.addConnection(connection);
// Automatically:
// - Saves to IndexedDB
// - Syncs to Firebase
// - Updates all subscribers
// - Triggers change detection

🧪 Testing Checklist

Before Code Review:

Verification:

// Check console logs:
✅ "💾 Flash Persistence: Persisted flash:singularity:blocks"
✅ "💾 Flash Persistence: Persisted flash:singularity:connections"
✅ "🎯 flash:singularity:blocks loaded with persisted value"
✅ "🎯 flash:singularity:connections loaded with persisted value"

🚀 Benefits of This Architecture

1. Automatic Persistence

2. Reactive UI

3. Data Integrity

4. Scalability


📚 Related Documentation


💡 Key Takeaways

  1. Never create local copies of persistent data
  2. Always use SingularityService for state management
  3. Template reads from signal() directly
  4. Updates go through service methods
  5. Flash Persistence handles the rest

✅ Verification Complete

All persistent data now follows this systematic architecture:

No more manual save/load code!
No more duplicate state!
No more persistence bugs!


Version: 1.0.0
Status: ✅ Production Ready