sk2andy/candy-browser

▲ 22 stars today★ 536⑂ 18

Gesture-first Android browser with Material 3 Expressive design and local privacy tools

About sk2andy/candy-browser

sk2andy/candy-browser is an open-source project on GitHub, mainly written in Kotlin. Gesture-first Android browser with Material 3 Expressive design and local privacy tools It currently holds 536 stars and 18 forks with 46 open issues, and was last pushed on 2026-10-10 (repository created 2026-08-06).

Project Overview

Git Homed tracks it on the Today's Trending board, currently at rank #49 with 22 new stars today.

GitHub Repository Details

Repository sk2andy/candy-browser · default branch main · size 124128 KB · watchers 1 · source: GitHub REST API and repository README

README

https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser logo

Candy Browser

Firefox extensions on Android, powered by GeckoView.
A gesture-first browser with selectable GeckoView and Android System WebView engines, an iOS WKWebView/Liquid Glass target, and local privacy tools.

https://github.com/sk2andy/candy-browser/blob/HEAD/Release https://github.com/sk2andy/candy-browser/blob/HEAD/Android 13+ https://github.com/sk2andy/candy-browser/blob/HEAD/Kotlin https://github.com/sk2andy/candy-browser/blob/HEAD/Jetpack Compose https://github.com/sk2andy/candy-browser/blob/HEAD/License: MPL 2.0

GitHub Pages website · Privacy · Releases

https://github.com/sk2andy/candy-browser/blob/HEAD/Buy me a coffee

[!NOTE]
Next release: stability fixes. I'm focusing on finding and fixing as many bugs as possible
and testing the changes over an extended period to make Candy Browser more reliable.

🎉 Firefox extensions on Android

Candy uses GeckoView by default and supports Mozilla-signed Firefox extensions directly inside the Android app. A fresh Gecko profile comes with uBlock Origin and I still don't care about cookies, while additional compatible extensions can be installed and managed from Candy's browser settings.

Extension actions, popups, options, permissions, updates, and enable/disable controls stay inside Candy's browser chrome. See Platform engines for the supported GeckoView integration and current compatibility boundaries.

https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser start page   https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser cover-flow tab overview   https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser Privacy X-Ray

Cross-device sync

Candy Sync turns every connected Android, Chromium, or Firefox device into a writable profile. Open a desktop profile on your phone to inspect its live tab list, open new tabs, navigate, pin, reorder, or close them. The same small tab changes flow back to every connected client instead of re-uploading the complete browser state.

https://github.com/sk2andy/candy-browser/blob/HEAD/A synced desktop device selected as a writable profile in Candy Browser    https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Sync device binding, profile icon, accent color, and E2EE warning on Android

Changes are encrypted locally and written to a durable outbox. REST commits provide ordered, retry-safe storage; authenticated WebSocket notifications deliver committed changes immediately. After suspension or network loss, clients recover missing changes through REST.

E2EE in short

The first client creates a random 256-bit workspace key. The immutable passphrase derives a local recovery key with Argon2id; HKDF-SHA-256 derives purpose- and device-specific keys, and AES-256-GCM encrypts and authenticates tab data. Every device also creates its own P-256 private key locally. The passphrase, workspace key, private keys, URLs, titles, device names, and icons never reach the server in plaintext—the server stores ciphertext plus the routing metadata required for sync.

Start Candy Sync

cd sync/server
cp .env.example .env

Set a unique username, password, public URL, and TLS host in .env.

Never put the E2EE passphrase in server configuration.

docker compose pull candy-sync docker compose up -d

The public sk2andy/candy-sync:latest image supports Linux AMD64 and ARM64. Contributors can still build the server locally with docker compose up --build -d.

Build and load the WebExtension from sync/extension/, open its browser-managed Options Page, and enter the endpoint plus an E2EE passphrase. In Candy Browser, open Settings → Synchronization and join with the same endpoint, credentials, and passphrase.

See the Candy Sync guide for server deployment, local TLS, Chromium/Firefox loading, Android setup, backups, protocol details, and the full security model.

Candy Sync roadmap

See Candy in motion

https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser showcase with two Android web engines and Firefox extensions

Watch or download the 16:9 feature showcase (MP4, 60 fps)

After its gesture-first opener, the showcase moves straight to the Android engine choice and Firefox extensions. It then combines self-hosted Android/Chromium/Firefox tab sync with E2EE, live API 36 emulator footage, current Topping scripts, and repository screenshots to show Link Peek, Spoilerfree Sports, Hacker News Comfort, Privacy X-Ray, Reader Studio, Candy Trails, and profiles. Its original soundtrack, kinetic typography, and camera motion are generated entirely from repository-owned sources.

Why Candy?

wider screens, swipe into the visual overview, and dismiss cards with spring motion and haptic feedback. tab lists as writable device profiles while the server never sees their contents in plaintext. Origin, or Android System WebView for Android's system-managed runtime while keeping Toppings and Candy protection. passkeys, downloads, sharing, printing, and default-browser integration.

Architecture

Candy keeps browser behavior and production UI in shared Kotlin. The address bar, gestures, menus, tab switcher, Hero/Grid/List previews, settings structure, and their motion rules are not rebuilt for each platform. Small platform adapters connect that shared product layer to the native browser engine, image types, resources, haptics, and visual effects.

flowchart TD
    K[Shared Kotlin behavior and state] --> C[Shared Compose UI and motion]
    C --> A[Android platform adapter]
    C --> I[iOS platform adapter]
    A --> E{Selected Android engine}
    E --> G[GeckoView sessions]
    E --> S[System WebView sessions]
    G --> F[Signed Firefox WebExtensions]
    K --> T[Shared Topping model and grants]
    T --> GT[Gecko userScripts host]
    T --> ST[System WebView userScripts host]
    T --> WT[WKUserScript host]
    I --> W[WKWebView sessions]
    W --> WT

Android defaults to GeckoView and can switch the whole app to Android System WebView from Browser settings. Candy checkpoints tab URLs and restarts into a fresh process, keeping tabs, bookmarks, history, profiles, and settings shared while cookies, logins, native back-forward lists, and other engine-owned session state stay separate. Firefox extensions remain available only in GeckoView; System WebView keeps Toppings and Candy protection. iOS uses WKWebView behind the same shared Kotlin contracts and Compose browser chrome, with native Liquid Glass supplied through an iOS effect adapter.

Implementation boundaries, invariants, and the current parity status are documented in Platform engines and Platform feature parity.

Tablet and Foldable support

At 600 dp and wider, the floating address bar shows a horizontally scrollable tab strip. Tap another tab to open it, or tap the current tab to edit its address. Configurable actions and the More menu stay in place. Horizontal swipes scroll the strip; the upward overview gesture remains. The visual tab overview also adapts its previews and grid to larger screens.

https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser floating tab strip with website favicons on a landscape Android tablet
Tablet browsing with floating, scrollable tabs and website favicons.

https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser floating tab strip on an unfolded Android foldable in landscape
Unfolded foldable layout with the same tab strip and fixed browser actions.

Features

Browsing and gestures

address field or wide-screen tab strip and a docked edge mode provider-backed search suggestions (disabled in private tabs) normal address input, History, or >recall, with no private-tab or cloud indexing download managers tab or history entry, then send it to a background tab through the pulsing plus target instead of creating a tab immediately. A compact bottom pill keeps the current host visible, combines the outlined Open in Candy action with its profile picker, and offers share, copy, find-in-page, and desktop-site actions before the page is promoted to a real tab. Temporary app switches keep the preview; explicitly opening Candy from its app icon, widget, or launcher shortcut discards it.

https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser Link Peek live preview   https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser profile commands in the address bar

Appearance and browser chrome

live background blur where the selected Android engine and version support it

https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser frosted transparent address bar over a loaded page

Tabs, profiles, and journeys

collapse from the card marker in Coverflow or Grid, and choose Coverflow, Grid, or List for the folder-style member view and forkable paths and minimal browser chrome

https://github.com/sk2andy/candy-browser/blob/HEAD/Creating an isolated Candy Browser profile   https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Trail with a branching navigation journey

https://github.com/sk2andy/candy-browser/blob/HEAD/Cover-flow tab overview   https://github.com/sk2andy/candy-browser/blob/HEAD/Compact grid tab overview   https://github.com/sk2andy/candy-browser/blob/HEAD/Preview-free list tab overview

Reading and page tools

offline saves, and text-to-speech keyboard Discover, install, update, toggle, import, and edit bounded userscripts that customize matching regular tabs without privileged browser or GM_* APIs. The reviewed catalog lives in candy-browser-toppings, so new Toppings do not require a Candy Browser release

https://github.com/sk2andy/candy-browser/blob/HEAD/Candy Browser Reader Studio

Firefox extension support

default from pinned, unmodified Mozilla-signed XPIs bundled for offline installation. Their corresponding GPL-3.0-only sources are pinned to immutable upstream Git commits. respected; uninstalling it records a durable removal marker, so Candy does not restore it later. Default extensions are never enabled for private tabs without the user's explicit opt-in. GeckoView for signature validation, permission approval, installation, updates, enable/disable, uninstall, and explicit private-browsing access. storage, signature, identity, compatibility, platform support, Mozilla blocklist, enterprise-only, cancellation, and restart-required failures instead of showing one generic error. and options pages do not introduce a second address bar, menu system, or tab switcher. not a guarantee that every Firefox Desktop extension is compatible. Desktop-only APIs and fields GeckoView rejects before Candy can handle them cannot be emulated reliably. For example, tabs.update({ muted: ... }) and tabs.update({ pinned: ... }) are rejected by GeckoView 155's extension schema. for supported APIs and exact platform boundaries.

Pinned source URLs, versions, hashes, licenses, and delivery modes live in app/src/gecko/assets/gecko_default_extensions/catalog.json. Maintainers verify local assets with python3 scripts/generate_gecko_default_extensions.py verify, audit both upstream files with python3 scripts/generate_gecko_default_extensions.py audit-remote, and refresh the bundled XPI only with python3 scripts/generate_gecko_default_extensions.py refresh.

Media, fullscreen, and picture-in-picture

replaces or restyles its video element

Local protection

pinned HaGeZi Pro host delta

Download

Candy Browser requires Android 13 (API 33) or newer.

Download Candy Browser

Standard and User CA production builds check GitHub for updates at startup and offer a signed APK for download. Standard installs on ARM64 devices prefer the smaller ARM64 APK and fall back to the universal APK when needed. Both use the same application ID, version, and signing key, so either can update an existing standard install. The FOSS build disables this updater. Android still requires you to open a downloaded file and approve installation.

Obtainium

Use the filtered setup link so Obtainium always selects the standard certificate-trust channel:

https://github.com/sk2andy/candy-browser/blob/HEAD/Get it on Obtainium

The standard and User CA channels use separate application IDs, so both can stay installed and keep independent profiles, settings, and caches. Keep the asset filter: it prevents Obtainium from selecting a different channel than the configured app.

F-Droid

Candy includes a separately installable foss distribution flavor for the official F-Droid repository. It uses the application ID dev.sk2andy.materialbrowser.foss, removes Google Play services, Google Cast, Google Code Scanner, and Candy's GitHub update checker, and keeps its profiles, settings, and caches isolated from the other channels. Remote search suggestions default to off. F-Droid builds this variant from tagged public source and verifies it against Candy's upstream-signed FOSS APK.

The isolated F-Droid listing starts with 0.37; older FOSS APKs used the universal application ID and cannot become versions of the new package. Submission files and maintainer steps live in distribution/fdroid. Candy publishes a signed FOSS reference APK so F-Droid can verify its source build and preserve update compatibility with the upstream signing key.

Releases contain four APK channels plus an architecture-optimized standard APK:

| APK suffix | Certificate trust | Intended use | | --- | --- | --- | | -release.apk | Android system CAs only | Universal compatibility fallback | | -arm64-v8a-release.apk | Android system CAs only | Recommended smaller APK for ARM64 devices | | -systemwebview-release.apk | Android system CAs only | Small, separately installed build using only Android System WebView | | -foss-release.apk | Android system CAs only | F-Droid reproducible-build reference without proprietary Google integrations | | -ca-release.apk | System CAs plus every CA in Android's user store | Explicit opt-in for HTTPS filtering/proxy tools such as AdGuard |

Both standard APKs use dev.sk2andy.materialbrowser and the same release signature. The System WebView-only build uses dev.sk2andy.materialbrowser.systemwebview, the FOSS build uses dev.sk2andy.materialbrowser.foss, and the User CA build uses dev.sk2andy.materialbrowser.ca. Android therefore installs all four channels side by side with isolated app data. Their launcher labels distinguish the channels; the warning under Settings → Protection & data additionally identifies the User CA build's broader trust policy. Updates stay on the installed channel. The System WebView build never downloads a GeckoView APK.

Releases through v0.36 used the standard application ID for all three APKs. Android cannot migrate an installed package to a different application ID, so the isolated FOSS and CA channels start with fresh app data. The new CA asset name is -ca-release.apk; legacy CA installs therefore do not get offered an incompatible package as an in-place update.

Security warning: a trusted user CA can inspect and modify all HTTPS traffic made by Candy, including normal and private tabs, suggestions, filter subscriptions, and update metadata. Only install the User CA APK when you trust every CA in Android's user credential store and the software that controls its private key. APK signature verification still protects Candy updates from APKs signed by another key.

Advanced users who intentionally need this channel can use the filtered User CA Obtainium setup%7B1%2C2%7D-ca-release%5C%5C%5C%5C.apk%24%5C%22%7D%22%7D).

Build from source

Requirements: Android SDK 37.1 and JDK 17. Point JAVA_HOME to your JDK 17 installation.

./gradlew testFullDebugUnitTest lintFullDebug assembleFullDebug

To verify the F-Droid-compatible

GitHub Stars & Activity

536Stars
18Forks
46Open issues
KotlinLanguage

GitHub Popularity

GitHub stars536
Forks18
Open issues46
Primary languageKotlin
LicenseMPL-2.0
Stars gained today22
Created2026-08-06
Last pushed2026-10-10

Trending History

Daily boardrank #49 · ▲ 22 stars

Related GitHub Projects

1

JunkFood02 / Seal

Kotlin★ 29,633⑂ 1,463▲ 45 stars
→
2

android / compose-samples

Kotlin★ 23,506⑂ 5,498▲ 4 stars
→
3

tiann / KernelSU

Kotlin★ 19,035⑂ 4,257▲ 24 stars
→
4

utkarshdalal / GameNative

Kotlin★ 11,114⑂ 451▲ 33 stars
→
5

KernelSU-Next / KernelSU-Next

Kotlin★ 4,403⑂ 1,171▲ 14 stars
→
6

HuangZhuoRui / LocationSpoofer

Kotlin★ 1,420⑂ 262▲ 48 stars
→
7

PimpinPumpkin / Vela

Kotlin★ 1,363⑂ 56▲ 83 stars
→
8

software-mansion / enriched-markdown

Kotlin★ 1,210⑂ 104▲ 17 stars
→

More Trending Repositories