Prisme
A browser is not a page viewer — it's a reader that understands
An intelligent iOS browser where every page is understood locally before it is displayed — SwiftUI, WebKit, and Apple Foundation Models, with zero servers, zero accounts, and zero telemetry.
35
Swift files, ~4,100 lines
0
third-party dependencies
6/6
end-to-end UI tests green
4
semantic zoom levels
144
lines of injected JavaScript
100%
on-device AI
Overview
The modern web is hostile: consent walls, 2,000 words of SEO filler around a 40-word answer, manipulative patterns, tracking. Ordinary browsers render that hostility faithfully. Prisme interposes itself: each page is distilled locally before display, then re-presented according to the reader's intent — while the raw page always stays one gesture away.
The signature feature is semantic zoom: pinching doesn't change the text size, it changes the level of detail — Text, Sections, Outline, Essence — and pinching out past Text returns the raw page. A comprehension strip appears after every load ("Article · ~4 min read") with a one-tap entry into the native reader, whose typography adapts to the page type.
Everything is on-device. The Distiller pipeline extracts typed DOM blocks with deterministic JavaScript, budgets tokens, and only then asks the ~3B Foundation Models for a guided @Generable digest — cached by content hash, anchored back to source blocks, and fully degradable: on devices without Apple Intelligence, every feature still works through deterministic paths. Identity containers (Personal, Work, Shopping, Sensitive) isolate cookies and sessions, and the Sensitive universe is never written to history at all.
Key Features
Semantic zoom
Pinch to change the level of detail, not the font size: Text, Sections, Outline, Essence — and back out to the raw page.
The Distiller
A 5-step pipeline — DOM extraction, typed blocks, token budgeting, deterministic condensation, guided @Generable generation — with a content-hash cache.
Semantic history
Every visited page is distilled and indexed with on-device sentence embeddings — natural-language recall directly in the address bar.
Structured bookmarks
Pages saved as native data (title, essence, outline, type) and text selections saved with their DOM anchor and section context — not links that rot.
Identity containers
Personal, Work, Shopping, and Sensitive universes with isolated cookie stores — and Sensitive visits are never written to memory at all.
Honest AI, always anchored
Generated content is visually distinct, anchored to its source block, and never replaces the page. A summary without an anchor doesn't render.
How It Works
Extract deterministically
144 lines of versioned JavaScript injected at documentEnd pull typed blocks (headings, paragraphs, code, tables) with their DOM paths — zero AI in the extraction path.
Budget and condense
A 30,000-token page must fit a 4–8K context: token budgeting reserves 30% for the response and condensation never cuts mid-sentence.
Generate guided digests
The on-device model produces a typed PageDigest via @Generable — never free text to parse — cached by content hash so no page is distilled twice.
Route by tier
Every task declares its tier: heuristics first, the local model for frequent free work, and cloud only for explicit actions — an LLM is the last resort, not the first.
Degrade totally
On devices without Apple Intelligence, the reader, zoom, history, and bookmarks all work through deterministic fallbacks — the test suite runs with the model unavailable.
Tech Stack
Platform
Engine & intelligence
Privacy
Highlights
- Semantic zoom: the pinch gesture changes the level of detail, not the text size — the signature interaction
- A pooled WKWebView architecture preserves per-tab session state without one webview per tab
- Six end-to-end XCUITests over real network and real gestures — zero mocks
- Zero third-party dependencies: SwiftUI, WebKit, Foundation Models, SwiftData, NaturalLanguage only
- The Sensitive research container is never stored-then-filtered — its visits are never seen by memory at all
- Every generated element carries the index of its source block; unanchored summaries simply don't display