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.
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). Web rendering comes from Servo, with SDL2 for windowing and input and egui for the UI.
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











