A gamepad-native web browser for unconventional devices.
retsurf (retro + surfing) is an experimental web browser written in Rust. The goal is to bring a fully featured web browser to devices where traditional browsers aren't practical. Web rendering comes from Servo, with SDL2 for windowing and input and egui for the UI.
retsurf runs without X11 or Wayland, rendering OpenGL ES directly through KMSDRM, and is designed for gamepad-first navigation. It targets PortMaster-compatible Linux handhelds, as well as regular desktops and Android (touch + system keyboard).
Work in progress. Early development — expect bugs.
![]() |
![]() |
![]() |
| Start page | Browsing | Link hints | Keyboard |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Tabs | Downloads | Reader mode | Settings |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Handheld Linux devices have no good browser options. Lightweight browsers often struggle with modern, JavaScript-heavy sites, while desktop browsers depend on a windowing system, mouse and keyboard, and hardware that these devices do not have.
retsurf is an attempt to fill that gap: a modern web engine, gamepad-first controls, and direct rendering without a compositor.
- Gamepad-native navigation — a virtual cursor (stick / D-pad), Vimium-style link hints, and an on-screen keyboard (QWERTY + ЙЦУКЕН). Every gesture is rebindable in-app or in
bindings.toml, with a D-pad scroll mode for stickless devices. - Tabs, bookmarks, history, downloads — in one full-screen menu. Files download in the background with progress, cancel, and a ⬇ toolbar chip.
- Real page zoom — reflows the layout (not a magnifier) along Firefox's 50–300% ladder, per tab, so the whole web fits a small screen.
- Reader mode — strips a page to its article with Mozilla's Readability. Runs in place, so logged-in and dynamic pages work too.
- Dark web pages — asks sites for their dark theme (
prefers-color-scheme), or forces one by inverting the pages that ship none. Off by default, seepage_theme. - Ad & tracker blocking — network-level via Brave's adblock-rust (EasyList + EasyPrivacy), compiled and cached locally so warm starts are instant and work offline.
- Native start page — a search/URL field over a speed-dial grid of pins (
retsurf:home), controller-navigable like every other overlay. - In-app updates — checks GitHub, shows release notes inline, and installs in place on PortMaster handhelds and Linux desktops (elsewhere it opens the release page). Stable, beta, and dev channels.
- Web Audio — custom Servo media backend with SDL2 output. Supports oscillators, gain, filters, panners, scripted buffers, and decodeAudioData for MP3, WAV, FLAC, Ogg/Vorbis, and AAC/M4A, with resampling to the context rate.
- Modern rendering — Servo's WebRender on OpenGL ES 3.x: a single GL context and zero CPU readback, Servo drawing straight into the on-screen framebuffer.
You need Servo's build dependencies. On Debian/Ubuntu:
sudo apt-get install -y build-essential clang cmake curl git gperf pkg-config python3 \
libssl-dev libdbus-1-dev libfreetype6-dev libglib2.0-dev \
libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev \
libharfbuzz-dev liblzma-dev libudev-dev libunwind-dev libsdl2-devThen:
cargo runOn a Wayland desktop, retsurf auto-selects SDL's Wayland driver and a GLES context. Environment variables override the config, data, and download paths and set logging — see Configuration.
retsurf also builds an APK: SDL2 loads the Rust code as a cdylib and the GLES render path carries over, with touch input and the system soft keyboard. With the Android SDK/NDK installed:
rustup target add aarch64-linux-android
cargo install cargo-ndk --locked
./android/scripts/build.sh release # android/app/build/outputs/apk/release/app-release.apk
adb install -r android/app/build/outputs/apk/release/app-release.apkconfig.toml (settings) and bindings.toml (gamepad/keyboard mappings) live in the
user data dir (SDL_GetPrefPath, e.g. ~/.local/share/mxmgorin/retsurf/ on Linux).
Templates with the defaults are written on first run, and most settings are editable
in-app from the settings overlay.
See Configuration & bindings for every option and the full bindings reference.
Bug reports and ideas are welcome — open an issue for anything broken or missing. If you find retsurf useful, a star on GitHub helps others discover it — and keeps me motivated.
- Handheld notes — how it works, architecture, porting status
- Android notes — build/packaging, storage, touch, lifecycle, status
- The Servo Book — the embedded engine: architecture, concepts, build system











