A lightweight, gamepad-first web browser for retro handhelds, Android, and desktops.
retsurf (retro + surfing) is a web browser written in Rust. The goal is to bring a fully featured web experience to devices that traditional browsers weren't designed to run on. Powered by Servo for web rendering, SDL2 for windowing and input, retsurf runs without X11, Wayland, or even a GPU, and provides gamepad-first navigation.
It supports PortMaster-compatible handhelds, Miyoo Mini Flip and Plus running OnionOS and Allium, as well as regular desktops and Android. Where there is no compositor, retsurf renders straight to KMSDRM through OpenGL ES; on GPU-less devices such as the Miyoo Mini, the software build rasterizes both web pages and the UI on the CPU.
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, JS-heavy sites, while desktop browsers depend on a windowing system, mouse and keyboard, and hardware that these devices don't have. retsurf is an attempt to fill that gap: a modern web engine, gamepad-first controls, and direct rendering without a compositor.
-
Gamepad-first navigation
Virtual cursor with stick/D-pad control, Vimium-style link hints, and an on-screen keyboard (QWERTY + ЙЦУКЕН). -
Customizable controls
Every action is rebindable in-app or inbindings.toml: with support for taps, holds and button chords. -
Tabs, bookmarks, history, and downloads
Everything lives in one full-screen menu. Downloads run in the background with progress and cancellation, with a toolbar chip for active downloads. -
Real page zoom
Reflows the layout rather than magnifying it, following Firefox's 50–300% zoom ladder; zoom is per-tab. -
Reader mode
Strips pages down to their articles using Mozilla's Readability. Runs in place, so it also works with logged-in and dynamically rendered pages. -
Dark web pages
Uses sites' own dark themes throughprefers-color-scheme, or forces a dark appearance by inverting pages that don't provide one. -
Ad & tracker blocking
Network-level blocking powered by Brave'sadblock-rust, using EasyList and EasyPrivacy. Filters are compiled and cached locally, making warm starts instant and allowing blocking to work offline. -
Native start page
A search/URL field over a speed-dial grid of pins (retsurf:home), fully controller-navigable like every other overlay. -
In-app updates
Checks GitHub for updates and shows release notes inline. On PortMaster handhelds and Linux desktops, updates can be installed in place; elsewhere, the release page is opened. Supports stable, beta, and dev channels. -
Web Audio
Custom Servo media backend with SDL2 output. Supports oscillators, gain, filters, panners, scripted buffers, anddecodeAudioDatafor MP3, WAV, FLAC, Ogg/Vorbis, and AAC/M4A, with resampling to the context rate. -
Hardware-accelerated rendering
Servo's WebRender uses OpenGL ES 3.x with a single GL context and zero CPU readback, drawing directly into the on-screen framebuffer. -
Software rendering
Thesoftwarebuild replaces both renderers with CPU-based ones: SWGL rasterizes web pages, while SDL's 2D renderer draws the browser UI.
Download retsurf-portmaster.zip from
Releases and unpack it into your
ports folder (e.g. /roms/ports/).
Download the appropriate zip from Releases and unzip it at the root of the SD card.
| OS | Package | Location |
|---|---|---|
| OnionOS | retsurf-onionos.zip |
App/Retsurf/ |
| Allium | retsurf-allium.zip |
Apps/Retsurf.pak/ |
The app appears in the respective Apps menu and MENU quits it on both.
Download retsurf-android-arm64.apk from
Releases and sideload it.
Download the appropriate zip from Releases, unpack and run.
| OS | Package |
|---|---|
| Linux | retsurf-linux-x86_64.zip, retsurf-linux-aarch64.zip |
| Windows | retsurf-windows-x86_64.zip |
| macOS | retsurf-macos-aarch64.dmg |
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 runWith 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. See Configuration & bindings for every option and the
full bindings reference.
- Web rendering by Servo
- SDL2 through rust-sdl2 for window, input and audio
- egui draws every overlay, with icons from Phosphor
- Blocking by Brave's adblock-rust, over EasyList and EasyPrivacy
- Reader mode by Mozilla's Readability
- Media by Symphonia and openh264 over Cisco's codec
- TLS by rustls
- SDL2 for the Miyoo Mini by Steward Fu









