Ladybird separates its rendering engine from its user interface entirely, which means the browser window, tabs, and address bar are implemented in a dedicated frontend layer sitting on top of LibWebView. Four frontends are maintained today: a native macOS frontend built with AppKit, a cross-platform frontend built with Qt6, an experimental Linux frontend built with GTK4 and libadwaita, and a native Android frontend. Choosing the right frontend — or building a new one — is a straightforward process controlled by a single CMake option or a flag to theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ladybirdBrowser/ladybird/llms.txt
Use this file to discover all available pages before exploring further.
ladybird.py helper script.
Supported Frontends
- AppKit (macOS)
- Qt6 (Linux / other)
- GTK4 (experimental)
- Android
The AppKit frontend is the default on macOS and uses Apple’s native AppKit framework. It is one of the two officially supported UI ports alongside Qt6. No additional prerequisites are needed beyond the standard macOS build dependencies (Xcode 15 or clang from Homebrew).To explicitly select AppKit:
Selecting a Frontend
The frontend is controlled by theLADYBIRD_GUI_FRAMEWORK CMake cache variable or the --gui argument to ladybird.py. Both accept the same values: AppKit, Qt, and Gtk (Android is selected by building the Android project directly).
GTK Frontend Style Guide
The GTK frontend is a thin shell over LibWebView. All core browser logic lives in the shared library layer; the GTK code only handles what is strictly necessary to present a GTK window.GObject Rules
Type registration and struct definitions
Type registration and struct definitions
Only register GTypes (
G_DEFINE_FINAL_TYPE) for widgets that are referenced in GtkBuilder UI template files. Do not use G_DECLARE_FINAL_TYPE — instead, define structs and GType functions manually to avoid reserved _TypeName naming conflicts. Prefer GtkBuilder with .ui resource files for declarative layout wherever practical.Namespacing convention:Ladybird::for C++ classesLadybirdWidgets::for GObject widget helpers
Signal handling
Signal handling
- Do not use
bind_template_callback— connect signals in C++ withg_signal_connect_swapped. - Do not use
g_signal_new— useFunction<>callbacks instead of custom GObject signals. - Prefer
g_signal_connect_swappedoverg_signal_connectto avoid castinguser_data. - For buttons in popover menus, prefer
action-nameproperties over click signal handlers.
Memory management with GObjectPtr
Memory management with GObjectPtr
Never call
g_object_unref manually — use GObjectPtr<T> (defined in UI/Gtk/GLibPtr.h). Never call g_free manually — use g_autofree.The GTK frontend must follow the GNOME HIG. Prefer libadwaita widgets (
AdwTabView, AdwHeaderBar, AdwAlertDialog, AdwToast, etc.) over custom widget implementations. Use D-Bus via GApplication for single-instance and IPC — not custom socket or file mechanisms.Porting: Building a New UI Frontend
UI ports concern themselves with the browser window, tabs, address bar, and any other UI surface. The engine itself lives in LibWebView and is shared across all frontends.Port Types
There are two distinct types of ports in Ladybird:| Type | Scope | Examples |
|---|---|---|
| UI port | Browser window, tabs, address bar | Qt6, AppKit, GTK4, Android |
| Platform port | File I/O, networking, process management | GNU/Linux, macOS, Android (in progress) |
Currently Supported Ports
Supported UI ports: Qt6 (generic), AppKit/Cocoa (macOS native). Supported platform ports: GNU/Linux, macOS.Many other POSIX platforms — including Alpine Linux, FreeBSD, OpenBSD, and Haiku — are known to work or have worked in the past but are not officially supported. These are community-driven ports with no regular CI. Contributions to restore or improve compatibility are welcome.
Implementing a New UI Port
Subclass WebView::ViewImplementation
WebView::ViewImplementation is the primary interface between the UI process and the WebContent processes. Each browser tab is expected to have its own WebContent process, and this relationship is managed by the WebView layer. Your subclass is responsible for bridging WebView events to your UI toolkit’s event loop.Subclass WebView::Application
Each UI port must also subclass
WebView::Application to register any UI-specific command-line flags and to perform any toolkit-specific application initialization.Platform Port Requirements
Platform ports adjust the underlying OS-specific code in AK and LibCore:AK/Platform.h— add a new platform define for conditional compilation.AK::StackInfo— most likely class to need platform-specific code in AK.LibCore— wraps lower-level OS functionality. Key classes:Core::System,Core::Process,Core::Socket.LibIPC— mostly platform-agnostic; based on Unix domain sockets, so any platform supporting them should work with minimal adjustment.
Explore More
DevTools
Enable Ladybird’s DevTools server and connect Firefox DevTools to inspect the DOM, run JavaScript, and trace the actor protocol.
Contributing a Port
Step-by-step expectations for community ports and guidance on getting a new platform or UI port accepted upstream.
