Context
PathView already integrates the File System Access API (showSaveFilePicker / showOpenFilePicker) for direct save / open without the download dialog round-trip, with a graceful fallback to the legacy upload/download path on browsers that don't support it. Autosave is wired through localStorage (key pathview_autosave), debounced ~500 ms and additionally backed up every 30 s.
Relevant code:
src/lib/schema/fileOps.ts — saveFile() (line 387), saveAsFile() (line 410), openImportDialog() (line 777), debouncedAutoSave() (line 335), loadAutoSave() (line 348), setupAutoSave() (line 482)
src/lib/utils/download.ts — legacy fallback
That covers the basics. Two follow-ups would meaningfully improve the desktop-app feel:
Gap 1 — no "Recent files" entry point
Today, every new tab/session forces the user back through showOpenFilePicker. FileSystemFileHandle objects are structured-cloneable, so the app can persist them across sessions in IndexedDB and present a "Recent" menu. On click the browser issues a quick permission re-prompt (handle.queryPermission / handle.requestPermission), then opens directly.
Proposal: keep an LRU of the last 5–10 file handles in IndexedDB, surface them in the Open dropdown. On Firefox/Safari (no FSAA), gracefully degrade to "no recent files" — same as today.
Gap 2 — autosave size cap
localStorage caps around 5–10 MB per origin and stores everything as a single string blob. Larger graphs (lots of subsystems, embedded annotations, big code contexts) will quietly fall over once they cross the limit, with no clean error path.
Proposal: move autosave to IndexedDB. Removes the cap, lets us also store binary blobs (e.g. cached simulation results) without base64-encoding them. The serialization format (PVM JSON) stays unchanged; only the storage layer moves.
Optional follow-up — project directories
showDirectoryPicker would let users pin a "project folder" containing .pvm plus related assets (CSVs, custom toolbox source, generated plots). PathView could mirror the folder into a virtual workspace and re-open everything on next session via the same persisted handle.
Probably not v1 — needs UI design — but worth keeping on the radar.
Implementation sketch
- New
src/lib/schema/handleStore.ts (IndexedDB wrapper, ~50 LOC) — get/set/delete file-handle entries with metadata (name, lastOpened, lastSaved).
- Refactor
setupAutoSave / loadAutoSave to write/read from the same IndexedDB instead of localStorage. Migrate existing pathview_autosave localStorage entries on first load, then remove.
- Topbar Open button gets a small dropdown caret with last-N recent files, each calling
handle.requestPermission({ mode: 'readwrite' }) then loadFromHandle.
- Feature-detect
'showOpenFilePicker' in window for the Recent-Files UI; hide it on browsers that don't support it.
Browser matrix
- Recent-files / persistent handles: Chromium-based browsers only (Chrome 86+, Edge 86+, Opera 72+, Brave). Firefox/Safari fall back to "no recent files" (current behaviour).
- IndexedDB autosave: universal. Even Firefox/Safari users benefit from the larger storage cap.
Context
PathView already integrates the File System Access API (
showSaveFilePicker/showOpenFilePicker) for direct save / open without the download dialog round-trip, with a graceful fallback to the legacy upload/download path on browsers that don't support it. Autosave is wired throughlocalStorage(keypathview_autosave), debounced ~500 ms and additionally backed up every 30 s.Relevant code:
src/lib/schema/fileOps.ts—saveFile()(line 387),saveAsFile()(line 410),openImportDialog()(line 777),debouncedAutoSave()(line 335),loadAutoSave()(line 348),setupAutoSave()(line 482)src/lib/utils/download.ts— legacy fallbackThat covers the basics. Two follow-ups would meaningfully improve the desktop-app feel:
Gap 1 — no "Recent files" entry point
Today, every new tab/session forces the user back through
showOpenFilePicker.FileSystemFileHandleobjects are structured-cloneable, so the app can persist them across sessions in IndexedDB and present a "Recent" menu. On click the browser issues a quick permission re-prompt (handle.queryPermission/handle.requestPermission), then opens directly.Proposal: keep an LRU of the last 5–10 file handles in IndexedDB, surface them in the Open dropdown. On Firefox/Safari (no FSAA), gracefully degrade to "no recent files" — same as today.
Gap 2 — autosave size cap
localStoragecaps around 5–10 MB per origin and stores everything as a single string blob. Larger graphs (lots of subsystems, embedded annotations, big code contexts) will quietly fall over once they cross the limit, with no clean error path.Proposal: move autosave to IndexedDB. Removes the cap, lets us also store binary blobs (e.g. cached simulation results) without base64-encoding them. The serialization format (PVM JSON) stays unchanged; only the storage layer moves.
Optional follow-up — project directories
showDirectoryPickerwould let users pin a "project folder" containing.pvmplus related assets (CSVs, custom toolbox source, generated plots). PathView could mirror the folder into a virtual workspace and re-open everything on next session via the same persisted handle.Probably not v1 — needs UI design — but worth keeping on the radar.
Implementation sketch
src/lib/schema/handleStore.ts(IndexedDB wrapper, ~50 LOC) — get/set/delete file-handle entries with metadata (name, lastOpened, lastSaved).setupAutoSave/loadAutoSaveto write/read from the same IndexedDB instead of localStorage. Migrate existingpathview_autosavelocalStorage entries on first load, then remove.handle.requestPermission({ mode: 'readwrite' })thenloadFromHandle.'showOpenFilePicker' in windowfor the Recent-Files UI; hide it on browsers that don't support it.Browser matrix