NullBrowser
github.com/akaieuan/null-browser · Read PHILOSOPHY.md
Repo, product site, and the living invariant list in the repo.
Earlier reference on this site: concept sketch · philosophy draft. The shipped build supersedes both, but these show how the constraints evolved.
Open source · pre-v0.1
Null
A browser that refuses to ship what the user didn't ask for. null.sh
What this is
Null is three commitments shipped as one project: a perspective arguing that browsers have quietly become advertising infrastructure and that the invariants usually waved away as "nice to have" are actually the only load-bearing specification; a shell built on Tauri 2.0 + the system WebView: not a Chromium fork, not a vendored engine, roughly 15k lines of Rust and TypeScript doing the work of a million; and a manifest, six rules that every feature has to earn against, enforced in code and in the PR template. The shipped app adds four separate AI surfaces (grounded tab chat, tab summarize, user-configured search, save to artifacts), a SQLite artifacts browser, and Tauri channel streaming for those flows, all inspectable. The argument, the implementation, and the constraints, in one place.
What I actually built
- Six invariants, enforced in code. Zero telemetry. No default cloud connections. All AI inference local by default (Ollama). Every outbound connection visible in the inspector. Data on disk, not in an account. No dark patterns. Each one is a line item in
docs/PHILOSOPHY.mdand a gate in review. - The three questions. Every change that touches networking, storage, or AI routing answers from the diff alone: what does this store, transmit, remember?
- Tauri 2.0 multi-webview shell. Every tab is its own child WebView with its own cookie jar. The React chrome lives in the main webview and never sees page content. Tab switching is native show/hide, not CSS visibility tricks.
AI as four collaborator modes, not one chat. The modes are the philosophy in code. The model never clicks, types, or navigates on its own, it summarizes what is on screen, answers questions about it, saves it, or runs search at your request.
- Chat. Grounded in the active tab with
chatWithPage, streamsChatEvents(grounded, chunk, done, error) over a Tauri channel. - Summarize.
summarizeCurrentTabextracts the page, streams a summary with optional focus, and can save a persistent artifact. - Search. Web search via a user-configured search instance from
searchGetInstance, rendered asSearchResult[]cards. - Save.
saveCurrentTabsnapshots a page into the artifacts collection.
Every mode streams on Tauri channels, not polling for those flows. Every cloud call passes a permission broker and shows in the network inspector before it leaves the machine.
- Chat. Grounded in the active tab with
- Artifacts as a first-class object. SQLite stores saved pages and summaries, with
listArtifacts,getArtifact, anddeleteArtifact, a full list-and-detail browser, and markdown in the reader viareact-markdownandremark-gfm, openable in a dedicated view inside the drawer. The streamingArtifactEventpath (extracted, chunk, saved, error) is built on Tauri channels instead of polling, local, and visible. The AI never routes you to a new place; it saves what the user is already looking at. - Local-first provider router. Ollama is the only provider enabled at startup. Anthropic and OpenAI-compatible providers are opt-in, per-key, per-call. Keys live in the OS keychain, not localStorage, not SQLite.
ProviderRowis provider key management inline: paste an Anthropic or OpenAI key there without leaving the chrome. - The inspector is a surface, not a devtool. Every subresource, every AI call, every connection. Origins can be blocked live through a SQLite-backed allowlist wired into a
beforeRequesthook. - One button to forget everything. "Clear history & logins" wipes the SQLite history table and clears cookies, localStorage, sessionStorage, and IndexedDB across every live tab webview in one transaction.
Why it's unusual
Most "privacy browsers" are a Chromium fork with a VPN upsell and a logo change. Null is the opposite bet: a tiny Tauri shell where every feature has to justify existing against six invariants, and every outbound connection is visible without opening a devtool. I wrote the manifest that says browsers became ad infrastructure because nobody was enforcing the constraints that made them trustworthy, then built the shell that enforces those constraints in code, then wrote the review gates that keep them enforced as the project grows. Positioning, authorship, engineering, and governance are one piece of work. The manifest is not marketing. The manifest is the build.
How I describe the skill set
Rust and Tauri 2.0 runtime internals, multi-webview architecture, SQLite schema authorship and migrations, React 19 + TypeScript, Tailwind v4 design tokens, Tauri channel streaming for chat and artifacts, AI router and permission-broker design, OS keychain and inline provider setup, network instrumentation, open-source principled positioning, and the discipline to refuse features the invariants don't accept.
Most browsers ship what the vendor wants to ship. Null ships what the user consented to. Zero telemetry, no default cloud, local-first AI, every connection in the open. The invariants aren't copy. They're the build.