Architecture & State Management
Visual system design
Data flows through three strictly isolated layers:
- Presentation layer — Ace Editor & vanilla DOM UI, reading via
state.editor.getValue() - Local persistence — IndexedDB (
VeyrixFS), written viaDB.save(state.files) - Cloud share (lazy) — Firebase Firestore, written via
addDoc(shared_snippets)— only touched when the user explicitly shares to the cloud
State management pattern
To maintain extreme performance on low-end mobile devices, Veyrix eschews frameworks like React or Vue. Instead it relies on a mutable, global singleton state object. UI updates happen through explicit imperative functions triggered by state mutations, avoiding full tree diffing.
// Global State Singleton
const state = {
files: [], // Array of File objects
activeFileId: null, // ID of currently rendered file
editor: null, // Ace Editor instance reference
db: null, // IndexedDB connection instance
renameTargetId: null // Transient state for UI modals
};
Architectural decision record (ADR): the Ace Editor manages its own complex internal state (cursors, selections, undo stacks). Wrapping it in a reactive framework often causes race conditions during rapid typing. By keeping the source of truth in state.editor and extracting value asynchronously via debounced events, Veyrix achieves sub-16ms frame times.
Local storage model (IndexedDB)
Persistence is managed entirely via the browser's native IndexedDB API through a Promisified wrapper. The database is named VeyrixFS (Version 1).
Schema: files ObjectStore
KeyPath: id
// TypeScript representation of the IndexedDB record
interface VeyrixFile {
id: string; // e.g., "f_a1b2c3d4e_1679000000"
name: string; // Base filename (e.g., "app")
ext: string; // Extension (e.g., "js", "html")
content: string; // Raw string payload of the editor
unsaved: boolean; // Tracks dirty state for the UI
lastModified: number; // Epoch timestamp
snapshotCounter?: number;
snapshots?: Snapshot[]; // Array (max length: 5, FIFO eviction)
}
Cloud & synchronization strategy
Veyrix uses a zero-cost initial load strategy: Firebase SDKs (App, Auth, Firestore) are not bundled or loaded on startup. They're dynamically imported via ES Modules only when a user initiates a "Cloud Share."
1. Fast local share (LZ-String)
Compresses the payload with LZString.compressToEncodedURIComponent, yielding a base64-like URI-safe string appended directly to the URL. Entirely offline, entirely client-side.
2. Cloud share (Firestore)
Authenticates using signInAnonymously(), pushes the payload to the shared_snippets root collection, and returns a lightweight document ID reference in the URL.