How ladybird is put together
Ladybird is a from-scratch cross-platform web browser written primarily in C++ (C++20-style, custom standard library 'AK'), organized into a large set of 'Libraries/' (LibWeb, LibJS, LibGfx, LibURL, LibWasm, LibUnicode, LibTextCodec, LibRegex) plus a multi-process architecture documented as the Ladybird/browser/UI layer. Selected performance- and safety-sensitive pieces are implemented in Rust as workspace crates bridged to C++ via cbindgen-generated FFI (e.g., content blocking via the 'adblock' crate, YUV conversion in LibGfx). WebPlatform IDL interfaces are compiled into C++ binding wrappers by Python generators under Meta/Generators/libweb_bindings, which parse WebIDL and emit wrapper/hook code consumed by LibWeb's Bindings layer.
Languages
Frameworks
Infrastructure
Major components
AK
In-house C++ base library providing strings (String/ByteString/FlyString/Utf16FlyString), smart pointers, containers, JSON, streams, formatting, and FFI helpers used by all other libraries.
Libraries/LibJS
JavaScript engine implementation, including an experimental Flap compiler toolchain (excluded from the main Cargo workspace) that compiles .flap sources to assembly for x86_64/aarch64.
Libraries/LibWeb
The web rendering engine implementing HTML/CSS/DOM, with Rust sub-crates for content blocking (adblock) and an HTML parser, plus generated C++ IDL binding wrappers.
Meta/Generators (libweb_bindings)
Python generator framework that parses WebIDL and emits C++ wrapper classes, indexed/named property hooks, and value-conversion code for LibWeb bindings.
Rust workspace crates
Rust implementations embedded in AK, LibGfx (yuv color conversion), LibJS, LibRegex, LibTextCodec, LibUnicode, LibURL, LibWasm, and LibWeb, exposed to C++ via staticlib/rlib + cbindgen headers.
Base/res/ladybird/about-pages
Internal browser UI pages (e.g., settings) written in vanilla JavaScript/HTML that communicate with the browser core via ladybird.sendMessage / WebUIMessage events.
Meta/Linters
Python-pinned lint tooling (actionlint, pyright, ruff) used in CI/pre-commit to validate shell workflows, Python typing, and style.
Build system & CI configuration
Top-level CMakeLists.txt, CMakePresets.json, Cargo workspace manifest, .clang-format/.clang-tidy, and pre-commit config defining how the mixed C++/Rust/Python tree is built and checked.
The new Rust-based CSS query engine came online, with media, container, and supports queries now fully evaluated in Rust, alongside a wave of scrollbar fixes and layout speedups.
5 weeksWeek of 2026-08-24
Week of 2026-08-24latest
The new Rust-based CSS query engine came online, with media, container, and supports queries now fully evaluated in Rust, alongside a wave of scrollbar fixes and layout speedups.
Week of 2026-08-17
A massive 266-commit week completed the switchover to a Rust CSS parser and value parser, removing the old C++ versions entirely and adding benchmarks to track progress.
Week of 2026-08-10
A quiet week with just five commits, mostly small correctness and cleanup changes to video playback timing and HTML parsing internals.
Week of 2026-08-03
Video streaming infrastructure got a major upgrade, with codec capability reporting, in-band configuration changes, and several Media Source Extensions behaviors implemented.
Week of 2026-07-27
Eight focused commits hardened Media Source Extensions playback, covering out-of-order frames, buffer eviction, and a new MP4-style byte stream format.
Over the past month the Ladybird browser team has been steadily replacing its C++ CSS machinery with a Rust-based implementation, moving parsing and evaluation of media queries, container queries, supports conditions, values, and shorthands into Rust while cutting out the old C++ tokenizers and parsers. Alongside this big engine overhaul, work continued on making web video (Media Source Extensions) actually usable — fixing playback ordering, buffering, and codec handling — plus a steady stream of layout performance improvements and scrollbar interaction fixes. The pace was highest in mid-August during the CSS parser migration, with lighter weeks focused on media plumbing and polish.
Week by week
2026-08-24The new Rust-based CSS query engine came online, with media, container, and supports queries now fully evaluated in Rust, alongside a wave of scrollbar fixes and layout speedups.latest6 changes
Feature
CSS queries evaluated entirely in Rust
Media queries, container queries, and supports conditions are now parsed, serialized, and evaluated by the new Rust code, with the old C++ query logic removed.
Fix
Smoother scrollbar dragging
A series of fixes made scrollbars handle clicks, drags, hover states, and edge cases like zero-width gutters and stray mouse releases correctly.
Refactor
Faster page styling
Layout now reuses cached measurements across similar elements and skips redundant style recalculations, reducing wasted work when rendering pages.
Refactor
CSS values parsed without extra round trips
Substituted values (like variables) are now parsed directly instead of bouncing through a background worker, speeding up style processing.
Refactor
Stylesheet rule management rebuilt
The internal bookkeeping for matching stylesheet rules to elements was rebuilt from attached stylesheets, avoiding unnecessary sorting work.
Fix
Qt Vulkan window input fixes
Pointer events, alpha blending, and window masks in the Qt/Vulkan display path were corrected or validated.
2026-08-17A massive 266-commit week completed the switchover to a Rust CSS parser and value parser, removing the old C++ versions entirely and adding benchmarks to track progress.6 changes
Feature
Rust is now the default CSS parser
Every kind of CSS — longhands, shorthands, fonts, images, gradients, grid values, and more — is parsed in Rust, which is now the authoritative path.
Refactor
Old C++ tokenizer and value parser deleted
With the Rust parser proven correct against its C++ counterpart, the legacy C++ CSS tokenizer and value parser were removed from the codebase.
Feature
Advanced CSS functions resolved in Rust
Modern CSS features like if(), custom functions, attr(), inherit(), env(), and registered custom properties are now handled natively in Rust.
Feature
Media Source Extensions polish
Font-face registration de-duplicated, DOM and animation style records preserved during removal, and selection between the UI and browser became asynchronous for snappier behavior.
Chore
Crash and stability fixes
Closing a browser tab no longer risks crashing, and the benchmark tooling now reliably detects when a performance test finishes.
Refactor
Parser overhead reduced
Allocations and fixed costs in the new Rust value parser were trimmed, and a dedicated microbenchmark was added to keep it fast.
2026-08-10A quiet week with just five commits, mostly small correctness and cleanup changes to video playback timing and HTML parsing internals.4 changes
Fix
Video timestamps handled as signed
The media player now treats a video file's base timestamp as signed, preventing misinterpretation that could break playback.
Feature
Meta tags can change content encoding
Web pages can now alter their text encoding via meta elements, matching how other browsers behave on pages with non-standard character sets.
Refactor
HTML parser cleanup
Internal tidy-ups: removing unneeded declarations and using the standard object creation pattern when building HTML parsers.
Docs
Spec comments added
Missing explanatory comments referencing the HTML standard were added to part of the parser code.
2026-08-03Video streaming infrastructure got a major upgrade, with codec capability reporting, in-band configuration changes, and several Media Source Extensions behaviors implemented.6 changes
Feature
Browser can report supported video formats
A new support-query system lets the page ask which audio/video MIME types and codecs the browser can play, powering both MSE and regular video elements.
Feature
SourceBuffer timestampOffset implemented
Web apps that stitch together video segments can now shift their timestamps as the standard requires.
Feature
Codec changes handled mid-stream
Videos that change codec settings partway through playback now pass those updates along to the decoders instead of breaking.
Feature
Old video data can be evicted
SourceBuffer coded frame removal was implemented so streaming sites can discard already-watched video and stay within memory limits.
Refactor
Demuxers organized via registry
Format detection and decoder construction were centralized with whitelists, fixing memory leaks on errors and clarifying which formats are supported.
Refactor
Codec housekeeping
Unsupported codecs were dropped, Theora properly categorized, PCM-in-Matroska added, and frame data storage simplified.
2026-07-27Eight focused commits hardened Media Source Extensions playback, covering out-of-order frames, buffer eviction, and a new MP4-style byte stream format.6 changes
Fix
Out-of-order video frames handled
MSE now copes when incoming frames arrive in an unexpected order rather than producing glitches.
Fix
Buffer cleanup keeps video playable
After evicting old data, track buffers remain decodable from keyframes, and the coded-frame removal steps were corrected to match the spec.
Feature
MP4 byte stream format supported
The ISO BMFF byte stream format — how MP4 video is delivered over MSE — gained support, broadening site compatibility.
Fix
Durations tracked accurately
The maximum duration across a SourceBuffer's contents is now tracked so seeking and end-of-playback behave correctly.
Fix
WebM segments more tolerant
Elements that should be ignored after a second WebM init segment are now skipped instead of causing errors.
Refactor
Decoder internals simplified
Decode timestamps are stored directly on frames and a redundant duration map was removed from the FFmpeg video decoder.
Dependencies and code review
Dependency advisories
Security Watch
No known advisories across 0 scanned dependencies.
No known advisories in the scanned dependencies.
Code review
Libraries/LibWeb/PermissionsAPI/Permissions.cpp, function request_permission() (reached from Geolocation's permission request flow via permission_state/request_permission)
An attacker's web page silently obtains the user's geographic location without any consent prompt.
Fix: Remove the unconditional `descriptor.name == "geolocation"` branch in request_permission(); implement the FIXME user prompt (or default non test origins to PermissionState::Denied) so geolocation is only Granted after explicit user consent, keeping the automatic grant exclusively under HTML::Window::in_test_mode().
Get this report every week for your repos.
GitZoid learns each repo, reports what changed, and flags what needs attention. One flat price for the whole team.
$19 a month, flat · First 10 outputs free · No card required