Quick Start
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
Flash Persistence - Quick Start
Get started with auto-persistent signals in less than 5 minutes.
Installation
Flash Persistence is part of the @storage-system library, which is already installed in the monorepo.
# Already available in your NX workspace
import { autoFlashState } from '@storage-system';
Step 1: App Configuration
Add Flash Persistence to your app configuration:
// apps/your-app/src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideFlashPersistence } from '@storage-system';
export const appConfig: ApplicationConfig = {
providers: [
// ... other providers
provideFlashPersistence({
// Optional: enable MongoDB sync
enableMongoDBSync: false, // Set to true if you want cloud sync
// Optional: customize debounce
debounceMs: 300, // Wait 300ms before persisting changes
// Optional: pre-load specific keys
preloadKeys: ['user-preferences', 'app-state']
})
]
};
That's it for setup! Flash Persistence is now ready to use.
Step 2: Create Your First Persistent Signal
Basic Example
// apps/your-app/src/app/components/settings.component.ts
import { Component } from '@angular/core';
import { autoFlashState } from '@storage-system';
@Component({
selector: 'app-settings',
standalone: true,
template: `
<div class="settings">
<h2>Settings</h2>
<label>
Theme:
<select [value]="userPrefs().theme"
(change)="updateTheme($event)">
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label>
<label>
Language:
<select [value]="userPrefs().language"
(change)="updateLanguage($event)">
<option value="en">English</option>
<option value="es">Español</option>
</select>
</label>
<p>Current theme: {{ userPrefs().theme }}</p>
<p>Current language: {{ userPrefs().language }}</p>
</div>
`
})
export class SettingsComponent {
// ✅ Create persistent signal
userPrefs = autoFlashState({
key: 'user-preferences',
initialValue: {
theme: 'light',
language: 'en'
}
});
updateTheme(event: Event) {
const theme = (event.target as HTMLSelectElement).value;
this.userPrefs.update(prefs => ({ ...prefs, theme }));
// ✅ Automatically persisted!
}
updateLanguage(event: Event) {
const language = (event.target as HTMLSelectElement).value;
this.userPrefs.update(prefs => ({ ...prefs, language }));
// ✅ Automatically persisted!
}
}
Try it:
- Change the theme
- Refresh the page
- 🎉 Your selection is preserved!
Step 3: Use in Multiple Components
Shared State Pattern
// apps/your-app/src/app/services/app-state.service.ts
import { Injectable, signal } from '@angular/core';
import { autoFlashState } from '@storage-system';
export interface AppState {
sidebarOpen: boolean;
currentView: 'list' | 'grid';
filters: string[];
}
@Injectable({ providedIn: 'root' })
export class AppStateService {
// Persistent app state
state = autoFlashState<AppState>({
key: 'app-state',
initialValue: {
sidebarOpen: true,
currentView: 'list',
filters: []
}
});
// Computed signals
sidebarOpen = () => this.state().sidebarOpen;
currentView = () => this.state().currentView;
filters = () => this.state().filters;
// Actions
toggleSidebar() {
this.state.update(s => ({ ...s, sidebarOpen: !s.sidebarOpen }));
}
setView(view: 'list' | 'grid') {
this.state.update(s => ({ ...s, currentView: view }));
}
addFilter(filter: string) {
this.state.update(s => ({
...s,
filters: [...s.filters, filter]
}));
}
removeFilter(filter: string) {
this.state.update(s => ({
...s,
filters: s.filters.filter(f => f !== filter)
}));
}
}
Use in Component
// apps/your-app/src/app/components/sidebar.component.ts
import { Component, inject } from '@angular/core';
import { AppStateService } from '../services/app-state.service';
@Component({
selector: 'app-sidebar',
standalone: true,
template: `
<aside [class.open]="appState.sidebarOpen()">
<button (click)="appState.toggleSidebar()">
Toggle Sidebar
</button>
<!-- Sidebar content -->
</aside>
`
})
export class SidebarComponent {
appState = inject(AppStateService);
}
Common Patterns
1. Form Auto-Save
import { Component } from '@angular/core';
import { autoFlashState } from '@storage-system';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-draft-editor',
standalone: true,
imports: [FormsModule],
template: `
<div class="editor">
<h2>Draft Editor</h2>
<p class="autosave-indicator">
{{ draft() ? 'Draft saved ✓' : 'No draft' }}
</p>
<textarea
[(ngModel)]="draftContent"
(ngModelChange)="updateDraft($event)"
placeholder="Start typing...">
</textarea>
<button (click)="clearDraft()">Clear Draft</button>
</div>
`
})
export class DraftEditorComponent {
draft = autoFlashState({
key: 'draft',
initialValue: ''
});
draftContent = this.draft();
updateDraft(content: string) {
this.draft.set(content);
// ✅ Auto-saved with 300ms debounce
}
clearDraft() {
this.draft.set('');
this.draftContent = '';
}
}
2. Shopping Cart
export interface CartItem {
id: string;
name: string;
price: number;
quantity: number;
}
@Injectable({ providedIn: 'root' })
export class CartService {
cart = autoFlashState<CartItem[]>({
key: 'shopping-cart',
database: 'ecommerce',
collection: 'cart',
initialValue: []
});
// Computed
itemCount = computed(() =>
this.cart().reduce((sum, item) => sum + item.quantity, 0)
);
total = computed(() =>
this.cart().reduce((sum, item) => sum + (item.price * item.quantity), 0)
);
// Actions
addItem(item: CartItem) {
const existing = this.cart().find(i => i.id === item.id);
if (existing) {
this.updateQuantity(item.id, existing.quantity + 1);
} else {
this.cart.update(items => [...items, item]);
}
}
removeItem(id: string) {
this.cart.update(items => items.filter(i => i.id !== id));
}
updateQuantity(id: string, quantity: number) {
this.cart.update(items =>
items.map(i => i.id === id ? { ...i, quantity } : i)
);
}
clear() {
this.cart.set([]);
}
}
3. Recent Items
@Injectable({ providedIn: 'root' })
export class RecentItemsService {
recentItems = autoFlashState<string[]>({
key: 'recent-items',
initialValue: [],
ttl: 7 * 24 * 60 * 60 * 1000 // 7 days
});
addRecentItem(itemId: string) {
this.recentItems.update(items => {
// Remove if exists, add to front
const filtered = items.filter(id => id !== itemId);
const updated = [itemId, ...filtered];
// Keep only last 10
return updated.slice(0, 10);
});
}
clearRecent() {
this.recentItems.set([]);
}
}
MongoDB Sync (Optional)
Enable Cloud Sync
// app.config.ts
import { provideFlashPersistence, provideMongoDBSync } from '@storage-system';
export const appConfig: ApplicationConfig = {
providers: [
provideFlashPersistence(),
// Add MongoDB sync
provideMongoDBSync({
connectionString: environment.mongoDbConnectionString,
database: 'my-app',
defaultStrategy: {
mode: 'offline-first',
priority: 'normal',
conflictResolution: 'last-write-wins'
}
})
]
};
Use with Sync
// Now your signals sync to MongoDB!
const syncedPrefs = autoFlashState({
key: 'preferences',
database: 'my-app',
collection: 'user-settings',
initialValue: { theme: 'dark' },
priority: 'high' // Sync every 5 minutes
});
// Works offline - syncs when back online
syncedPrefs.set({ theme: 'light' });
// ✅ Local: Instant (0.3ms)
// ✅ MongoDB: Background sync (non-blocking)
Next Steps
Learn More
- 📖 Overview - Architecture and concepts
- 🎯 Component Integration - Advanced patterns
- 📚 API Reference - Complete API
- 🎓 Best Practices - Recommendations
Examples
- 🛒 Shopping Cart Example - Full implementation
- ⚙️ Settings Panel - User preferences
- 📝 Form Auto-Save - Draft persistence
- 🌐 Multi-Device Sync - MongoDB integration
Troubleshooting
Q: My signal isn't persisting
A: Check that you've called provideFlashPersistence() in your app.config.ts.
Q: Values aren't loading on page refresh
A: Flash Persistence pre-loads during app initialization. Make sure:
provideFlashPersistence()is in your config- You're using
autoFlashState(not regularsignal) - The
keyis unique and consistent - The hydrator service is being initialized properly
Q: Performance seems slow
A: Flash Persistence is designed for 0.3ms reads. If you're seeing slower performance:
- Check if you're bypassing the cache
- Verify the cache budget isn't exhausted
- Use computed signals for derived values
Q: How do I clear all persisted data?
A:
import { inject } from '@angular/core';
import { GgStorage } from '@storage-system';
const storage = inject(GgStorage);
await storage.clear(); // Clears all storage
Questions? Check the API Reference or GitHub Discussions.