EDITOR PERSISTENCE FLOW

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

Editor Persistence Flow

📍 Where Your Page is Saved

When you create a new page on the blank canvas (/editor), the data is persisted in two separate Flash Persistence storage keys:

1. Editor State (flash:editor-state)

Stores the current editor session:

Storage Key: flash:editor-state

2. Pages Registry (flash:pages-state)

Stores the catalog of all pages:

Storage Key: flash:pages-state


🔄 Complete Flow: Creating a New Page

Step 1: User Adds Widgets

User navigates to: /space/{spaceSlug}/editor
User adds a widget (e.g., button)

Step 2: EditorService Creates Temporary Page

// In EditorService.setWidgets()
if (!currentPageId && widgets.length > 0) {
  // Creates a temporary page
  const tempPage: Page = {
    id: `page-${Date.now()}-${random}`,
    title: 'New Page',
    // ... other properties
  };
  this.setPage(tempPage); // Stores in EditorService.editorState.page
}

Saved to: flash:editor-state.page

Step 3: Widgets Saved Per Page

// In EditorService.setWidgets()
this.editorState.update(state => ({
  widgetsByPage: {
    ...state.widgetsByPage,
    [currentPageId]: widgets // 🔥 Page-specific widgets
  }
}));

Saved to: flash:editor-state.widgetsByPage[pageId]

Step 4: Auto-Registration in PagesStateService

// In EditorWorkspaceComponent constructor (effect)
effect(() => {
  const currentPage = this.editorService.page();
  if (currentPage) {
    // Register page in PagesStateService so it's discoverable
    this.pageService.addPageIfNotExists(currentPage);
    this.pageService.setActivePage(currentPage);
  }
});

Saved to: flash:pages-state.pages[] and flash:pages-state.activePage


📊 Data Structure in Storage

flash:editor-state (EditorService)

{
  "page": {
    "id": "page-1762354037137-abc123",
    "title": "New Page",
    "slug": "new-page-1762354037137",
    "widgets": [],
    "layout": { ... },
    "meta": { ... }
  },
  "widgets": [], // Legacy - kept for backward compatibility
  "widgetsByPage": {
    "page-1762354037137-abc123": [
      {
        "id": "widget-123",
        "name": "Button",
        "type": "button",
        "properties": { ... }
      }
    ]
  },
  "selectedWidgetIds": [],
  "zoom": 1,
  "mode": "design",
  // ... other editor UI state
}

flash:pages-state (PagesStateService)

{
  "pages": [
    {
      "id": "page-1762354037137-abc123",
      "title": "New Page",
      "slug": "new-page-1762354037137",
      "widgets": [], // Lightweight - full widgets stored in editor-state
      "status": "draft",
      "meta": {
        "customMeta": {
          "moduleId": "module-123" // If created in module-builder context
        }
      }
    }
  ],
  "activePage": {
    "id": "page-1762354037137-abc123",
    // ... same as in pages[]
  },
  "draftPages": [ ... ],
  "publishedPages": [ ... ]
}

🔍 How Reload Works

On Page Reload:

  1. Flash Persistence automatically loads both storage keys:

    • flash:editor-state → Restores EditorService.editorState
    • flash:pages-state → Restores PagesStateService.state
  2. EditorWorkspaceComponent checks route params:

    if (params['pageId']) {
      this.pageId.set(params['pageId']);
      // Effect triggers: loadPageById(pageId)
    }
    
  3. loadPageById() looks for page in PagesStateService:

    const existingPage = this.pageService.pages().find(p => p.id === pageId);
    if (existingPage) {
      // Load widgets from EditorService.widgetsByPage[pageId]
      this.editorService.setPage(existingPage);
      this.editorService.setWidgets(existingPage.widgets || []);
    }
    
  4. Widgets are restored from flash:editor-state.widgetsByPage[pageId]


🎯 Key Points

✅ What Persists:

⚠️ Important Notes:

  1. Dual Storage:

    • Editor state = Working session data
    • Pages state = Page catalog/registry
  2. Page-Scoped Widgets:

    • Widgets are stored per page ID: widgetsByPage[pageId]
    • This prevents widget pollution between pages
  3. Auto-Registration:

    • When EditorService creates a page, EditorWorkspaceComponent automatically registers it in PagesStateService
    • This makes the page discoverable in page selectors
  4. Blank Canvas:

    • When navigating to /editor without a pageId, no page is loaded
    • First widget addition creates a temporary page

🔧 Viewing Storage Data

You can inspect the persisted data in the browser:

// In browser console
// Check Editor State
localStorage.getItem('flash:editor-state') // or IndexedDB depending on storage strategy

// Check Pages State  
localStorage.getItem('flash:pages-state') // or IndexedDB

// Or use Chrome DevTools → Application → Storage → IndexedDB
// Look for your app's database → Check 'flash:editor-state' and 'flash:pages-state' keys

📝 Summary

Your new page is saved in TWO places:

  1. flash:editor-state - Contains the full page object + widgets for current editing session
  2. flash:pages-state - Contains the page metadata in the pages catalog (for discovery/listing)

When you reload:

The system uses Flash Persistence (automatic IndexedDB/LocalStorage) - no manual save button needed! 🚀