Overview
A browser built on an infinite canvas instead of tabs, shipped to the App Store and Google Play. Windows, images, and sticky notes share one surface, connected by lines and grouped by color, and the whole arrangement saves and reloads. Performance was the constraint that shaped it. A canvas can hold a dozen live web views, so pan and zoom run as Reanimated shared values on the UI thread and never cross the bridge. Skia draws the parts that are genuinely drawings, the bezier connection lines, the coordinate grid, and the session thumbnails. The second constraint was privacy. It is a browser, so the analytics had to be built so that a full URL cannot reach them even by accident: a closed set of event names, a typed property shape per event, and no field anywhere that could carry a page address, a search string, or the text of a note. There is no backend at all, so there is no sync, and we took that tradeoff up front instead of deferring it. React Native and Expo, Zustand persisted to device storage, and Maestro driving reproducible store screenshots from seeded canvases.
How it’s built
Reanimated for the viewport, Skia for the ink
Pan and zoom are shared values, so a gesture never crosses the JS bridge and the canvas holds 60fps with a dozen live web views on it. Skia handles the things that are genuinely drawings: the bezier connection lines, the coordinate grid, and the thumbnails in the sessions list.
A closed, metadata-only analytics contract
Event names are a const object and each event’s properties are a type, so a call site cannot invent a field. The rule the module enforces is that no full URL, query string, or note text can reach the analytics provider. For a browser, that constraint is the product decision.
No backend, and the tradeoff that comes with it
Sessions, history, and preferences are Zustand stores persisted to device storage. Sharing a session produces a link carrying an identifier that resolves against a canvas already on that device, so nothing is ever uploaded. The cost is no cross-device sync, which is the most common request we get.
Deterministic screenshot seeds
Store listing captures are driven by Maestro against named canvases built through a dev-only deep link, so a shot is reproducible run to run instead of hand-arranged. It also turned up a measurement that changed the asset plan. Note text renders at roughly 4pt once a full canvas is zoomed to fit, so one slide cannot show both the workspace and readable notes.
Color that cascades down a connection tree
A color set on an item is inherited by everything connected below it unless a child overrides. That is what lets a line of inquiry read as one group when the canvas is zoomed out far enough that no text is legible.
