Palimpsest — iOS MVP Scope
V1 · Edinburgh, the Royal Mile, c. 1824 · preview scope document
1. What Palimpsest is
An iPhone walking companion. At a marked stop on a curated route, the user raises the phone and sees a historian-reviewed reconstruction of the same view in an earlier era, aligned to the real buildings through the camera, with a short audio story. Everything works offline after a one-time pack download.
What it is not: instant reconstruction of arbitrary places, an encyclopedia, a game, or a social app. One city, deeply, before any second city.
2. Audience and job to be done
| Audience | Job |
|---|---|
| Curious city-break visitor (primary) | "I'm standing on the Royal Mile for one afternoon — make it mean something." A self-guided, ~75-minute experience that beats a $20 group tour on depth and pace. |
| Repeat visitor / heritage enthusiast | "Show me the layer I can't see." Era switching and the conjecture-hatched honesty are the draw. |
| Local / proud resident | "Explain my city to the people I bring here." Shareable stops, giftable pack. |
Non-goals for V1: user accounts (deferred — packs keyed to Apple ID via StoreKit 2, no custom backend identity), social features, UGC, Android.
3. Golden path
- Open app → onboarding (3 screens: what it does, honesty promise, download prompt).
- Download Edinburgh pack (~250 MB over Wi-Fi; resumable).
- Route screen shows the six-stop itinerary with distances and a map.
- Walk to Stop I → "raise to see 1824" prompt (haptic).
- AR view: present-day camera feed with reconstruction fading in; alignment guides ("move left", "tilt up") until lock ≥ threshold.
- Era chips let the user switch layers (e.g., 1590 / 1824 / 1880 where produced).
- Audio story auto-plays (~2 min); transcript available; lock-screen controls work.
- "Next stop" card with walking direction; loop to step 4.
- End of route → recap card ("you walked 1.1 mi through 4 eras"), pass/pack upsell if not yet purchased, share sheet.
4. Screens (V1 inventory)
| Screen | Contents | Acceptance criteria |
|---|---|---|
| Onboarding | Value prop, honesty note ("reconstructions are reviewed illustrations"), location + notification permission primers | Skippable; each permission asked only in context later |
| Library | Downloaded/available city packs, size, manage storage | Works fully offline once a pack is installed |
| Route | Map + ordered stop list, per-stop era chips, estimated time | All stops reachable from route; "resume" returns to furthest stop |
| Stop detail | Plate image, story text, sources list ("composed from: Gordon of Rothiemay 1647, Edgar 1765, OS 1849") | Sources shown for every scene; conjecture legend linked |
| AR view | Camera feed + pinned overlay, alignment coach marks, era chips, story controls | Overlay anchored within ~1.5° of composed bearing at marked spot; usable without network |
| Compare still | Non-AR fallback: full-screen now/then slider (same gesture as web page) | Offered on unsupported devices, Low Power Mode, camera denied, or by toggle |
| Player | Audio story w/ transcript, speed, position | Background + lock-screen playback via MPRemoteCommandCenter |
| Settings | Storage, units, reduce-motion, conjecture-hatch toggle, sources/licensing, privacy | Camera/location permission states deep-link to system settings |
| Paywall | City Pack / Trip Pass offer | Prices labeled; restore purchases works; paywall never blocks a purchased pack |
5. Architecture and Apple frameworks
- SwiftUI app shell (iOS 17+ target) with SwiftData for pack manifest, progress, and settings persistence.
- ARKit + RealityKit for the overlay: scene pinned by
CLLocation+ device heading/attitude (CoreMotion) at a composed viewpoint; optionalARGeoTrackingConfiguration(CLLocation-anchored AR) evaluated during pilot — Edinburgh's coverage must be field-verified before committing. - CoreLocation geofences (
CLCircularRegion, ~30 m) wake "you've arrived" prompts; MapKit for route/stop maps with a bundled vector-tile extract of the Old Town for offline use. - AVFoundation/AVAudioSession for stories (spoken-word category, duck-others off), MPRemoteCommandCenter for lock-screen controls, transcripts as plain text + chapter markers.
- StoreKit 2 for pack/pass IAP; Transaction.updates listener; StoreKit Testing in Xcode for CI.
- BackgroundAssets / URLSession for resumable pack downloads; packs are signed content bundles (see §7).
- WidgetKit (later): "nearest stop" widget — stretch, not V1.
6. Permissions UX (ask in context, never at launch)
| Permission | When asked | Fallback if denied |
|---|---|---|
| Location (When In Use) | First arrival prompt attempt | Route list still navigable; user self-navigates to stops |
| Precise location | Within location flow | Approximate geofence; manual "I'm here" button |
| Camera | First "raise to see" | Compare-still mode; clear explainer card |
| Notifications | After route completion or second launch | None needed — optional trip reminders |
| Motion (heading) | Auto with ARKit | Degraded alignment hints (manual rotate) |
7. Content pipeline (the real product)
Each scene ships as a Reconstruction Bundle:
scene.json — stop id, GPS anchor, composed bearing/fov, era list,
provenance (source list + reviewer sign-off), version
layers/*.heic — per-era reconstructed plate (16:9 + 9:16 crops)
uncertainty.map — per-region conjecture mask (drives hatch rendering)
story.m4a + story.vtt — audio + transcript
- Authored in a small internal tool (image editor + georef spreadsheet); MVP imports bundles from a folder — no CMS dependency.
- Bundles are versioned and signed; the app verifies and can hot-update a single scene without re-downloading the pack.
- Uncertainty marking: the conjecture mask renders rust-hatched in the AR overlay and compare view; tap → "why we're unsure" note.
- Licensing: where archival plates are used (e.g., Gordon of Rothiemay's 1647 plan, Hill & Adamson calotypes — public domain), record source + license in scene.json; commissioned illustration gets written license/assignment. No unlicensed imagery ships.
8. Local vs hosted
| Concern | V1 decision |
|---|---|
| Reconstruction rendering | Local only — pre-baked overlays; no on-device generative imagery and no server-side scene synthesis |
| Pack content | Hosted on a CDN (e.g., Cloudflare R2 + signed URLs); app caches entire pack |
| Purchase/entitlement | StoreKit 2 on-device; server receipt verification deferred (not needed for non-consumables) |
| Analytics | Minimal, anonymous: pack installs, stops completed, AR vs compare usage, crash opt-out — all local-first batched |
| Accounts | None in V1 |
9. Device coverage
- iOS 17+, iPhone XS and later for compare-still mode.
- AR mode: A12+ (all XS+ iPhones qualify);
ARGeoTrackingpath — if used — requires coverage check + iPhone with GPS accuracy ≥ threshold; degraded to manual-align on older devices. - iPad supported as "reader mode" (compare stills + stories) — no camera walk experience promised.
10. Monetization (hypotheses — see gtm.md)
- City Pack £6.99 non-consumable (test A).
- Trip Pass £12.99 / 72 h unlock of all packs — non-renewing IAP (test B); implemented as timed entitlement checked on-device.
- Free tier: Stop I (Esplanade) unlocked in full as the try-before-you-buy demo; rest of route behind paywall.
- No subscriptions, no ads.
11. Build sequence (4 milestones)
- M1 — Skeleton + content spine: route, stop detail, compare-still slider, bundled demo scene for 2 stops, offline manifest. Internal TestFlight.
- M2 — AR alignment: camera overlay, geofenced arrival prompts, alignment coach, manual-align fallback; field-test on the Mile.
- M3 — Stories + offline: audio pipeline, transcripts, pack download/resume, storage management.
- M4 — Commerce + polish: StoreKit 2 both offers, paywall, restore, a11y audit (VoiceOver on compare mode, Dynamic Type), App Store listing + review submission.
12. Key unresolved decisions
- Anchor tech: manual georef + heading (broad device support, more
alignment friction) vs
ARGeoTracking(precise where covered, coverage-limited). Decided by M2 field tests. - Overlay style: painterly plate vs photoreal reconstruction — user testing in pilot; current direction is painterly for honesty + cost.
- Historical uncertainty UX depth: always-hatched vs tap-to-reveal; pilot A/B.
- Second city trigger: explicit criteria (activation ≥ X, rating ≥ Y, content cost/stop ≤ Z) — see gtm.md §Validation gates.
- Guide/museum licensing partnerships may change free-tier shape (bundled access codes).