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:
- Current page being edited (
page) - Widgets for each page (
widgetsByPage[pageId]) - Editor UI state (zoom, grid, selected widgets, etc.)
Storage Key: flash:editor-state
2. Pages Registry (flash:pages-state)
Stores the catalog of all pages:
- List of all pages (
pages[]) - Active page reference (
activePage) - Published/draft/archived 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:
Flash Persistence automatically loads both storage keys:
flash:editor-state→ RestoresEditorService.editorStateflash:pages-state→ RestoresPagesStateService.state
EditorWorkspaceComponent checks route params:
if (params['pageId']) { this.pageId.set(params['pageId']); // Effect triggers: loadPageById(pageId) }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 || []); }Widgets are restored from
flash:editor-state.widgetsByPage[pageId]
🎯 Key Points
✅ What Persists:
- ✅ Page metadata (title, slug, layout, meta)
- ✅ Widgets per page (
widgetsByPage[pageId]) - ✅ Editor UI state (zoom, grid, selected widgets)
- ✅ Page list in PagesStateService
⚠️ Important Notes:
Dual Storage:
- Editor state = Working session data
- Pages state = Page catalog/registry
Page-Scoped Widgets:
- Widgets are stored per page ID:
widgetsByPage[pageId] - This prevents widget pollution between pages
- Widgets are stored per page ID:
Auto-Registration:
- When
EditorServicecreates a page,EditorWorkspaceComponentautomatically registers it inPagesStateService - This makes the page discoverable in page selectors
- When
Blank Canvas:
- When navigating to
/editorwithout apageId, no page is loaded - First widget addition creates a temporary page
- When navigating to
🔧 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:
flash:editor-state- Contains the full page object + widgets for current editing sessionflash:pages-state- Contains the page metadata in the pages catalog (for discovery/listing)
When you reload:
- Both states are automatically restored from Flash Persistence
EditorWorkspaceComponentloads the page and its widgets- Everything is restored exactly as you left it!
The system uses Flash Persistence (automatic IndexedDB/LocalStorage) - no manual save button needed! 🚀