"Technology is best when it disappears."
— adapted from Mark Weiser
Bare is not a small web browser. It is a reading instrument that happens to speak HTTP, Gemini and Gopher. Every engineering decision serves a single goal: turn whatever a server sends into clean, consistent, private text — and then get out of your way.
This page explains how that is built, honestly, including the things Bare deliberately does not do.
ðïļ The shape of the program
Bare is a Tauri 2 application: a Rust core wrapped in the operating system's own WebView, with no bundled browser engine.
Frontend
Vanilla HTML/CSS/JavaScript — renders finished, sanitized HTML
Bridge
Tauri IPC — message passing only, no shared network access
Rust core
fetch · extract · sanitize · render
Why this split matters:
- All networking, parsing and sanitization happen in Rust — never inside the page.
- The WebView only ever receives finished, already-sanitized HTML. It never talks to the network itself.
- There is no Chromium to ship, so the entire application is a few megabytes instead of a few hundred.
ð ïļ Main Components
Rust
Rust is the programming language powering Bare's backend.
Why Rust?
- Memory safety: Rust's ownership rules prevent memory errors like buffer overflows
- Performance: Compiled to native code, as fast as C/C++
- Security: No garbage collection, no runtime overhead
- Concurrency: Excellent support for asynchronous programming
- Ecosystem: Rich package ecosystem (crates.io)
Rust libraries used in Bare:
- pulldown-cmark — Fast CommonMark + GFM Markdown parser
- reqwest — Async HTTP client
- tauri — Tauri Rust library
Tauri 2.0
Tauri is the foundational framework that makes Bare possible.
Why Tauri?
| Tauri | Electron | |
|---|---|---|
| App size | ~2-5 MB | ~100-200 MB |
| Memory usage | Low | High |
| Security | High (Rust) | Medium (JS) |
| Performance | High | Medium |
| Platform support | Windows, macOS, Linux | Windows, macOS, Linux |
Tauri advantage: 20-100x smaller, 5x less RAM, memory safety, native speed.
Vanilla Web Technologies
Bare's frontend is built with pure web technologies:
- HTML5: Semantic markup for structure
- CSS3: Minimal styling, focused on readability
- JavaScript (ES6+): Clean, efficient code without frameworks
Advantages of this approach:
- No dependencies: No npm packages, no build steps
- Fast loading: No frameworks to load
- Easy maintenance: No version conflicts
- Long lifespan: Standards that don't change radically
ð Protocol Support
Bare supports a range of protocols to offer a rich text-based browsing experience.
HTTP/HTTPS
Standard web protocols with full support for GET, HEAD, redirects, SSL/TLS.
Special for Markdown: Bare sends an Accept header that signals preference for Markdown:
Accept: text/markdown, text/plain;q=0.9, text/html;q=0.5
Gemini
Gemini is a modern, text-based protocol with mandatory TLS encryption.
Bare's Gemini support includes:
- Full protocol implementation (RFC)
- TOFU (Trust On First Use) certificate handling
- Gemtext to Markdown conversion
- Interactive pages (input dialog)
Gemtext format:
# Heading 1
## Heading 2
This is a paragraph.
=> https://example.com Link description
Gopher
Gopher is the classic protocol from 1991.
Bare's Gopher support includes:
- Full RFC 1436 implementation
- Gophermap to Markdown conversion
- Support for text files, menus, and search
- Emoji icons for different content types
- Search dialog for interactive Gopher queries
Local files
Bare can open Markdown files directly from your computer via file://
protocol.
ð The reading pipeline
The heart of Bare is what happens between "you click a link" and "you see text." For an ordinary HTML page it is four stages, all in Rust:
1. Fetch
reqwest over rustls
+ ring (no OpenSSL, no native-tls), capped at 5 MB, sending an
Accept header that politely asks the server for Markdown first:
Accept: text/markdown, text/plain;q=0.9, text/html;q=0.5
2. Extract
A real DOM-based readability pass scores the document tree, lifts out the article, and discards navigation, sidebars, ad slots and comment threads. This replaced an earlier naive string-search method in v0.1.6 — content extraction is the core promise, so it had to be done properly, not approximated.
3. Sanitize
The result is run through ammonia, an allowlist-based Rust HTML sanitizer, stripping scripts, event handlers and anything that could carry a payload. This runs on the Markdown path too, so untrusted content is cleaned in depth, not only fenced off by policy.
4. Render
pulldown-cmark turns the
cleaned Markdown into HTML with CommonMark + GitHub extensions (tables, task
lists, strikethrough), and syntect adds syntax highlighting to code
blocks.
Gemtext and gophermaps skip the extraction stage entirely — they are already clean by design and go straight to dedicated converters.
⥠Speed by subtraction
Bare is fast because it does less, not because it works harder. An
LRU render cache in the Rust core makes returning to a recently
visited page instant; typical pages stripped to their content are
5–50 KB rather than multi-megabyte payloads; and async I/O
(tokio) means fetching never blocks the interface.
Design targets the project measures itself against:
| Metric | Target |
|---|---|
| Cached re-render | ≈ one frame (~16 ms) |
| Typical page, fetch → readable | well under half a second |
| External network calls beyond the document | zero |
| Application binary | single-digit megabytes |
| Resident memory | ~10–20 MB |
ð Privacy the code actually enforces
Privacy in Bare is not a preference panel; it is a property of the architecture. Three mechanisms make it real rather than aspirational:
Structural image blocking
The WebView ships with a strict Content-Security-Policy of
img-src 'self' data:. The page is forbidden at the engine
level from loading a remote image, so a tracking pixel cannot fire even
if one survives extraction. The ImageMode setting
(Block · Placeholder · Show) puts that choice
in your hands.
One click, one request
The WebView never originates network traffic. Only the Rust core fetches, and it fetches exactly the document you asked for — no fonts, analytics beacons, or third-party assets load in the background to leak your visit.
TOFU for Gemini
Gemini connections are verified Trust-On-First-Use: a SHA-256 fingerprint of
each server's certificate is stored in known_hosts.json, and a
later mismatch is flagged as a possible machine-in-the-middle attack —
the same model SSH uses.
No JavaScript, no cookies, no telemetry. The most private data is the data that is never collected.
ð ïļ Build Process
Development Environment
# Clone repository
git clone https://github.com/FrankBurmo/bare.git
cd bare
# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install Tauri CLI
cargo install tauri-cli
# Start development server
cargo tauri dev
Production Build
# Build for current platform
cargo tauri build
# Build for specific platform
cargo tauri build --target x86_64-pc-windows-msvc
cargo tauri build --target x86_64-unknown-linux-gnu
cargo tauri build --target universal2-apple-darwin
â Quality and trust
Bare is small, but it is not casual about correctness:
- 117+ unit tests across the core logic — extraction, protocol clients, converters, settings.
- Idiomatic Rust:
Result+thiserroreverywhere,?propagation, almost nounwrap()outside tests, per-module error types. - A safe stack:
rustlswithring(no OpenSSL), clamped numeric settings, allowlist sanitization. - 13 interface languages, in place unusually early for a project this size.
ðŦ What Bare will deliberately never build
A roadmap is also a list of refusals. These are not missing features — they are guarantees:
- No plugin or extension system. Non-extensibility is the central promise; a tool that cannot be extended cannot be quietly corrupted.
- No JavaScript engine. Ever. It is the largest source of tracking and attack surface on the web.
- No telemetry, no cloud sync, no accounts. Your reading is yours.
- No author-controlled styling. Presentation belongs to the reader.
What is genuinely on the table stays in character — improvements to reading, never to running code: PDF export, heading anchors and a table of contents, and richer reading-typography controls.