Problem
Every track downloaded by the a-Shell pipeline has to be manually imported through the file picker (src/components/ImportButton.jsx). The app can't watch the a-Shell library folder because iOS Safari has no File System Access API — a PWA cannot save a folder path and re-read it later. The sandbox constraint is real, but the experience of "I downloaded 3 songs, why aren't they in the app?" is fixable.
Constraint (so nobody fights it)
- No persistent folder handles on iOS Safari. Zero-setup true folder-watching is impossible from the PWA alone.
- What we do control: the picker allows multi-select, dedup already exists (
addLocalTrack() in src/lib/db.js skips existing tracks by YouTube id or title+artist+duration), and the a-Shell engine writes index.json (context.md §2).
Phased plan
Phase 1 — "Sync" flow (MVP, no new infra)
Turn the existing dedup into a one-gesture sync:
Phase 2 — localhost bridge (auto-detect for real, one Shortcut tap)
a-Shell can run Python: serve the library folder on http://127.0.0.1:<port> (e.g. via a small script wrapping http.server). The PWA polls http://127.0.0.1:<port>/index.json; when reachable, it diffs against the local catalog and offers "3 new downloads found — add all?" (or auto-adds behind a setting), fetching the .m4a bytes straight into audioBlobs.
Phase 3 (fallback if Phase 2 is blocked) — Shortcut hand-off
iOS Shortcut base64-encodes a downloaded file + metadata to the clipboard; a "Paste import" affordance in the PWA reads it via navigator.clipboard.readText() and stores the track. Clunkier, but zero picker interaction.
Acceptance criteria
After downloading N tracks in a-Shell, getting them into Melody takes at most one gesture, never per-file selection, and duplicates are never created.
Problem
Every track downloaded by the a-Shell pipeline has to be manually imported through the file picker (
src/components/ImportButton.jsx). The app can't watch the a-Shell library folder because iOS Safari has no File System Access API — a PWA cannot save a folder path and re-read it later. The sandbox constraint is real, but the experience of "I downloaded 3 songs, why aren't they in the app?" is fixable.Constraint (so nobody fights it)
addLocalTrack()insrc/lib/db.jsskips existing tracks by YouTube id or title+artist+duration), and the a-Shell engine writesindex.json(context.md §2).Phased plan
Phase 1 — "Sync" flow (MVP, no new infra)
Turn the existing dedup into a one-gesture sync:
ImportButton.onPick; todayskippedis only shown when nonzero — invert the emphasis)index.json, parse it and list catalog entries that were not among the picked/imported audio files ("2 tracks in your download folder weren't selected") so missed files are visiblePhase 2 — localhost bridge (auto-detect for real, one Shortcut tap)
a-Shell can run Python: serve the library folder on
http://127.0.0.1:<port>(e.g. via a small script wrappinghttp.server). The PWA pollshttp://127.0.0.1:<port>/index.json; when reachable, it diffs against the local catalog and offers "3 new downloads found — add all?" (or auto-adds behind a setting), fetching the.m4abytes straight intoaudioBlobs.http://127.0.0.1is permitted by current iOS/WebKit (localhost is spec'd as potentially trustworthy; must be confirmed in Safari standalone mode — this is the go/no-go)http://127.0.0.1:*toconnect-srcin the CSP (vite.config.js)Phase 3 (fallback if Phase 2 is blocked) — Shortcut hand-off
iOS Shortcut base64-encodes a downloaded file + metadata to the clipboard; a "Paste import" affordance in the PWA reads it via
navigator.clipboard.readText()and stores the track. Clunkier, but zero picker interaction.Acceptance criteria
After downloading N tracks in a-Shell, getting them into Melody takes at most one gesture, never per-file selection, and duplicates are never created.