wilsonzlin/fastrenderPublic

Experimental new browser engine

AI summary: Experimental browser rendering engine written in Rust for research into AI coding agents.

Stars
1.6K
+2 today
Forks
105
Watchers
9
Open issues
18
Open PRs
0
Contributors
~8
Commits
29.9K
Branches
1

HTMLNo licenseCreated Nov 16, 2025Last push 6mo ago+4 stars this week+4 this month

Star history

since Dec 14, 2025
05001K1.5KDec 2025Mar 2026May 2026Aug 2026
1.6K stars as of Aug 6, 2026, tracked back to Dec 14, 2025. Historical curve reconstructed from public GitHub event archives, calibrated to the current total.

Contribution activity

commits per day, last 52 weeks
AugSepOctNovDecJanFebMarAprMayJunJulMonWedFri2025-08-03: 0 commits2025-08-04: 0 commits2025-08-05: 0 commits2025-08-06: 0 commits2025-08-07: 0 commits2025-08-08: 0 commits2025-08-09: 0 commits2025-08-10: 0 commits2025-08-11: 0 commits2025-08-12: 0 commits2025-08-13: 0 commits2025-08-14: 0 commits2025-08-15: 0 commits2025-08-16: 0 commits2025-08-17: 0 commits2025-08-18: 0 commits2025-08-19: 0 commits2025-08-20: 0 commits2025-08-21: 0 commits2025-08-22: 0 commits2025-08-23: 0 commits2025-08-24: 0 commits2025-08-25: 0 commits2025-08-26: 0 commits2025-08-27: 0 commits2025-08-28: 0 commits2025-08-29: 0 commits2025-08-30: 0 commits2025-08-31: 0 commits2025-09-01: 0 commits2025-09-02: 0 commits2025-09-03: 0 commits2025-09-04: 0 commits2025-09-05: 0 commits2025-09-06: 0 commits2025-09-07: 0 commits2025-09-08: 0 commits2025-09-09: 0 commits2025-09-10: 0 commits2025-09-11: 0 commits2025-09-12: 0 commits2025-09-13: 0 commits2025-09-14: 0 commits2025-09-15: 0 commits2025-09-16: 0 commits2025-09-17: 0 commits2025-09-18: 0 commits2025-09-19: 0 commits2025-09-20: 0 commits2025-09-21: 0 commits2025-09-22: 0 commits2025-09-23: 0 commits2025-09-24: 0 commits2025-09-25: 0 commits2025-09-26: 0 commits2025-09-27: 0 commits2025-09-28: 0 commits2025-09-29: 0 commits2025-09-30: 0 commits2025-10-01: 0 commits2025-10-02: 0 commits2025-10-03: 0 commits2025-10-04: 0 commits2025-10-05: 0 commits2025-10-06: 0 commits2025-10-07: 0 commits2025-10-08: 0 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 0 commits2025-10-12: 0 commits2025-10-13: 0 commits2025-10-14: 0 commits2025-10-15: 0 commits2025-10-16: 0 commits2025-10-17: 0 commits2025-10-18: 0 commits2025-10-19: 0 commits2025-10-20: 0 commits2025-10-21: 0 commits2025-10-22: 0 commits2025-10-23: 0 commits2025-10-24: 0 commits2025-10-25: 0 commits2025-10-26: 0 commits2025-10-27: 0 commits2025-10-28: 0 commits2025-10-29: 0 commits2025-10-30: 0 commits2025-10-31: 0 commits2025-11-01: 0 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 0 commits2025-11-05: 0 commits2025-11-06: 0 commits2025-11-07: 0 commits2025-11-08: 0 commits2025-11-09: 0 commits2025-11-10: 0 commits2025-11-11: 0 commits2025-11-12: 0 commits2025-11-13: 0 commits2025-11-14: 0 commits2025-11-15: 0 commits2025-11-16: 1 commit2025-11-17: 0 commits2025-11-18: 0 commits2025-11-19: 0 commits2025-11-20: 14 commits2025-11-21: 1 commit2025-11-22: 26 commits2025-11-23: 7 commits2025-11-24: 3 commits2025-11-25: 1 commit2025-11-26: 0 commits2025-11-27: 1 commit2025-11-28: 17 commits2025-11-29: 15 commits2025-11-30: 2 commits2025-12-01: 1 commit2025-12-02: 1 commit2025-12-03: 0 commits2025-12-04: 0 commits2025-12-05: 0 commits2025-12-06: 0 commits2025-12-07: 0 commits2025-12-08: 1 commit2025-12-09: 0 commits2025-12-10: 0 commits2025-12-11: 0 commits2025-12-12: 0 commits2025-12-13: 0 commits2025-12-14: 0 commits2025-12-15: 0 commits2025-12-16: 31 commits2025-12-17: 780 commits2025-12-18: 488 commits2025-12-19: 396 commits2025-12-20: 226 commits2025-12-21: 28 commits2025-12-22: 264 commits2025-12-23: 5 commits2025-12-24: 322 commits2025-12-25: 42 commits2025-12-26: 66 commits2025-12-27: 152 commits2025-12-28: 111 commits2025-12-29: 44 commits2025-12-30: 12 commits2025-12-31: 575 commits2026-01-01: 655 commits2026-01-02: 280 commits2026-01-03: 48 commits2026-01-04: 862 commits2026-01-05: 524 commits2026-01-06: 226 commits2026-01-07: 961 commits2026-01-08: 888 commits2026-01-09: 2440 commits2026-01-10: 1598 commits2026-01-11: 2202 commits2026-01-12: 3696 commits2026-01-13: 6031 commits2026-01-14: 1388 commits2026-01-15: 0 commits2026-01-16: 23 commits2026-01-17: 1 commit2026-01-18: 48 commits2026-01-19: 0 commits2026-01-20: 0 commits2026-01-21: 0 commits2026-01-22: 0 commits2026-01-23: 0 commits2026-01-24: 0 commits2026-01-25: 0 commits2026-01-26: 0 commits2026-01-27: 0 commits2026-01-28: 0 commits2026-01-29: 0 commits2026-01-30: 0 commits2026-01-31: 0 commits2026-02-01: 0 commits2026-02-02: 0 commits2026-02-03: 0 commits2026-02-04: 0 commits2026-02-05: 0 commits2026-02-06: 0 commits2026-02-07: 0 commits2026-02-08: 0 commits2026-02-09: 0 commits2026-02-10: 0 commits2026-02-11: 0 commits2026-02-12: 0 commits2026-02-13: 0 commits2026-02-14: 0 commits2026-02-15: 0 commits2026-02-16: 0 commits2026-02-17: 0 commits2026-02-18: 0 commits2026-02-19: 0 commits2026-02-20: 0 commits2026-02-21: 0 commits2026-02-22: 0 commits2026-02-23: 0 commits2026-02-24: 0 commits2026-02-25: 0 commits2026-02-26: 0 commits2026-02-27: 0 commits2026-02-28: 0 commits2026-03-01: 0 commits2026-03-02: 0 commits2026-03-03: 0 commits2026-03-04: 0 commits2026-03-05: 0 commits2026-03-06: 0 commits2026-03-07: 0 commits2026-03-08: 0 commits2026-03-09: 0 commits2026-03-10: 0 commits2026-03-11: 0 commits2026-03-12: 0 commits2026-03-13: 0 commits2026-03-14: 0 commits2026-03-15: 0 commits2026-03-16: 0 commits2026-03-17: 0 commits2026-03-18: 0 commits2026-03-19: 0 commits2026-03-20: 0 commits2026-03-21: 0 commits2026-03-22: 0 commits2026-03-23: 0 commits2026-03-24: 0 commits2026-03-25: 0 commits2026-03-26: 0 commits2026-03-27: 0 commits2026-03-28: 0 commits2026-03-29: 0 commits2026-03-30: 0 commits2026-03-31: 0 commits2026-04-01: 0 commits2026-04-02: 0 commits2026-04-03: 0 commits2026-04-04: 0 commits2026-04-05: 0 commits2026-04-06: 0 commits2026-04-07: 0 commits2026-04-08: 0 commits2026-04-09: 0 commits2026-04-10: 0 commits2026-04-11: 0 commits2026-04-12: 0 commits2026-04-13: 0 commits2026-04-14: 0 commits2026-04-15: 0 commits2026-04-16: 0 commits2026-04-17: 0 commits2026-04-18: 0 commits2026-04-19: 0 commits2026-04-20: 0 commits2026-04-21: 0 commits2026-04-22: 0 commits2026-04-23: 0 commits2026-04-24: 0 commits2026-04-25: 0 commits2026-04-26: 0 commits2026-04-27: 0 commits2026-04-28: 0 commits2026-04-29: 0 commits2026-04-30: 0 commits2026-05-01: 0 commits2026-05-02: 0 commits2026-05-03: 0 commits2026-05-04: 0 commits2026-05-05: 0 commits2026-05-06: 0 commits2026-05-07: 0 commits2026-05-08: 0 commits2026-05-09: 0 commits2026-05-10: 0 commits2026-05-11: 0 commits2026-05-12: 0 commits2026-05-13: 0 commits2026-05-14: 0 commits2026-05-15: 0 commits2026-05-16: 0 commits2026-05-17: 0 commits2026-05-18: 0 commits2026-05-19: 0 commits2026-05-20: 0 commits2026-05-21: 0 commits2026-05-22: 0 commits2026-05-23: 0 commits2026-05-24: 0 commits2026-05-25: 0 commits2026-05-26: 0 commits2026-05-27: 0 commits2026-05-28: 0 commits2026-05-29: 0 commits2026-05-30: 0 commits2026-05-31: 0 commits2026-06-01: 0 commits2026-06-02: 0 commits2026-06-03: 0 commits2026-06-04: 0 commits2026-06-05: 0 commits2026-06-06: 0 commits2026-06-07: 0 commits2026-06-08: 0 commits2026-06-09: 0 commits2026-06-10: 0 commits2026-06-11: 0 commits2026-06-12: 0 commits2026-06-13: 0 commits2026-06-14: 0 commits2026-06-15: 0 commits2026-06-16: 0 commits2026-06-17: 0 commits2026-06-18: 0 commits2026-06-19: 0 commits2026-06-20: 0 commits2026-06-21: 0 commits2026-06-22: 0 commits2026-06-23: 0 commits2026-06-24: 0 commits2026-06-25: 0 commits2026-06-26: 0 commits2026-06-27: 0 commits2026-06-28: 0 commits2026-06-29: 0 commits2026-06-30: 0 commits2026-07-01: 0 commits2026-07-02: 0 commits2026-07-03: 0 commits2026-07-04: 0 commits2026-07-05: 0 commits2026-07-06: 0 commits2026-07-07: 0 commits2026-07-08: 0 commits2026-07-09: 0 commits2026-07-10: 0 commits2026-07-11: 0 commits2026-07-12: 0 commits2026-07-13: 0 commits2026-07-14: 0 commits2026-07-15: 0 commits2026-07-16: 0 commits2026-07-17: 0 commits2026-07-18: 0 commits2026-07-19: 0 commits2026-07-20: 0 commits2026-07-21: 0 commits2026-07-22: 0 commits2026-07-23: 0 commits2026-07-24: 0 commits2026-07-25: 0 commits2026-07-26: 0 commits2026-07-27: 0 commits2026-07-28: 0 commits2026-07-29: 0 commits2026-07-30: 0 commits2026-07-31: 0 commits2026-08-01: 0 commits
25,504 commits in the last yearLessMore

What fastrender does

FastRender is a from-scratch browser rendering engine built entirely in Rust. It takes responsibility for parsing HTML and CSS, computing styles, managing layout algorithms, and painting pixels to the screen. The project includes a basic desktop browser shell and integrates an embedded JS engine to execute JavaScript. It serves primarily as a research vehicle for exploring collaborative parallel AI coding agents rather than a production-ready browser alternative.

AI researchers, browser engine enthusiasts, and Rust systems programmers. This is a highly experimental, unstable project not intended for end-users or production environments.

  • Rust core: built with memory safety and performance in mind using Rust.
  • Full rendering pipeline: implements HTML/CSS parsing, style computation, layout, and painting.
  • Embedded JS engine: executes JavaScript alongside the custom rendering logic.
  • Desktop shell: provides a standalone window for viewing rendered output.
  • Research focused: designed specifically as a testbed for scaling parallel AI coding agents.

Where teams use it

AI agent research

Serve as a complex, multi-component codebase for testing parallel AI coding capabilities.

Rendering engine education

Study the internal mechanics of how web browsers parse and paint content.

Rust systems programming

Analyze patterns for building large-scale desktop applications and parsers in Rust.

Experimental web features

Implement and test novel layout algorithms without the overhead of Chromium.

Getting started: cargo build --release

README

main branch

FastRender

A browser rendering engine in Rust. Parses HTML/CSS, computes styles, performs layout, and paints pixels. Includes a desktop browser shell and JavaScript execution via an embedded JS engine.

Under heavy development. APIs are unstable and change frequently. Not recommended for production use.

Developed as part of research into collaborative parallel AI coding agents.

Repository structure

src/
├── api.rs                 # Public API (FastRender, RenderOptions)
├── dom.rs                 # DOM tree, parsing, shadow DOM
├── dom2/                  # Live DOM for JS mutation
├── css/                   # CSS parsing, selectors, values
├── style/                 # Cascade, computed styles, media queries
│   ├── cascade.rs         # Cascade algorithm, layers, scope
│   ├── properties.rs      # Property definitions
│   └── values.rs          # Value types, calc(), colors
├── tree/                  # Box tree generation
│   ├── box_tree.rs        # Box nodes, formatting contexts
│   ├── box_generation.rs  # Styled → box mapping
│   └── table_fixup.rs     # Anonymous table wrapper insertion
├── layout/                # Layout algorithms
│   ├── contexts/
│   │   ├── block/         # Block formatting context
│   │   ├── inline/        # Inline formatting, line boxes
│   │   ├── flex.rs        # Flexbox
│   │   └── grid.rs        # CSS Grid
│   ├── table.rs           # Table layout (auto + fixed)
│   ├── fragmentation.rs   # Pagination, column breaks
│   └── absolute_positioning.rs
├── text/                  # Text processing
│   ├── pipeline.rs        # Itemization, shaping, layout
│   ├── bidi.rs            # Bidirectional algorithm
│   ├── line_break.rs      # Line breaking, hyphenation
│   └── color_fonts/       # COLR, sbix, SVG-in-OT
├── paint/                 # Painting
│   ├── display_list.rs    # Display list structure
│   ├── stacking.rs        # Stacking contexts, z-order
│   ├── painter.rs         # Rasterization
│   └── svg_filter.rs      # CSS/SVG filter effects
├── js/                    # JavaScript integration
│   ├── event_loop.rs      # Task queues, microtasks
│   ├── html_script_*.rs   # Script loading, execution
│   ├── vmjs/              # vm-js bindings
│   └── import_maps/       # ES module import maps
├── ui/                    # Desktop browser UI
│   ├── browser_app.rs     # Window, tabs, chrome
│   ├── render_worker.rs   # Background rendering
│   └── messages.rs        # UI ↔ worker protocol
├── sandbox/               # OS sandboxing
│   ├── linux_seccomp.rs   # seccomp-bpf filters
│   ├── macos_seatbelt.rs  # Seatbelt profiles
│   └── windows.rs         # AppContainer
├── resource/              # Network, caching
│   ├── disk_cache.rs      # On-disk asset cache
│   └── web_fetch/         # Fetch API implementation
└── bin/                   # CLI binaries

vendor/
├── ecma-rs/               # JavaScript engine (vm-js)
└── taffy/                 # Flexbox/Grid layout

tests/
├── integration.rs         # Integration test harness
├── pages/fixtures/        # Offline page captures
└── wpt/                   # Web Platform Tests subset

docs/                      # Internal documentation
instructions/              # Workstream guides
progress/pages/            # Pageset accuracy tracking

Rendering pipeline

flowchart LR
    subgraph Parse
        HTML[HTML bytes] --> DOM[DOM tree]
        CSS[CSS bytes] --> Sheets[Stylesheet collection]
    end
    
    subgraph Style
        DOM --> Styled[Styled tree]
        Sheets --> Styled
        Styled --> |cascade + inherit| Computed[Computed values]
    end
    
    subgraph Layout
        Computed --> BoxTree[Box tree]
        BoxTree --> |anonymous wrappers| Fragments[Fragment tree]
    end
    
    subgraph Paint
        Fragments --> DisplayList[Display list]
        DisplayList --> |stacking order| Raster[Pixmap]
    end
Loading

Each stage produces an immutable tree consumed by the next. This separation enables caching: change only CSS and re-cascade without re-parsing HTML; scroll without re-laying-out.

Box generation

flowchart TD
    Element[Styled element] --> Display{display value?}
    Display --> |block| Block[Block box]
    Display --> |inline| Inline[Inline box]
    Display --> |flex| Flex[Flex container]
    Display --> |grid| Grid[Grid container]
    Display --> |table| Table[Table wrapper]
    Display --> |none| Skip[Skip subtree]
    Display --> |contents| Contents[Unwrap children]
    
    Block --> Anon{needs wrapper?}
    Anon --> |mixed content| AnonBlock[Anonymous block]
    Anon --> |table child| AnonTable[Anonymous table parts]
    
    Element --> Pseudo{pseudo-elements?}
    Pseudo --> Before[::before]
    Pseudo --> After[::after]
    Pseudo --> Marker[::marker]
Loading

The box tree is not 1:1 with the DOM. display: contents removes an element's box while keeping its children. Tables generate anonymous row/cell wrappers per CSS 2.1 §17.2. Mixed block/inline children trigger anonymous block box creation.

Layout contexts

flowchart TD
    Box[Box node] --> FC{formatting context}
    
    FC --> BFC[Block formatting context]
    BFC --> |floats, margins| BFCLayout[Block layout]
    BFCLayout --> Clear[Float clearing]
    BFCLayout --> Collapse[Margin collapsing]
    
    FC --> IFC[Inline formatting context]
    IFC --> |line boxes| IFCLayout[Inline layout]
    IFCLayout --> Bidi[Bidi reordering]
    IFCLayout --> Shaping[Text shaping]
    IFCLayout --> Wrap[Line breaking]
    
    FC --> FlexFC[Flex formatting context]
    FlexFC --> |main/cross axis| FlexLayout[Flex layout]
    FlexLayout --> FlexGrow[flex-grow/shrink]
    FlexLayout --> FlexAlign[Alignment]
    
    FC --> GridFC[Grid formatting context]
    GridFC --> |tracks, areas| GridLayout[Grid layout]
    GridLayout --> AutoPlace[Auto-placement]
    GridLayout --> TrackSize[Track sizing]
    
    FC --> TableFC[Table formatting context]
    TableFC --> |rows, columns| TableLayout[Table layout]
    TableLayout --> ColWidth[Column distribution]
    TableLayout --> BorderCollapse[Border collapse]
    
    FC --> MultiCol[Multi-column context]
    MultiCol --> |fragmentainers| ColLayout[Column layout]
    ColLayout --> ColBreak[Column breaks]
    ColLayout --> ColBalance[Balancing]
Loading

Layout is recursive: a flex container lays out its items, each of which may establish its own formatting context. Block and inline contexts are implemented natively. Flexbox and grid delegate to a vendored layout library (Taffy). Tables use a native implementation with bidirectional constraint solving for auto layout.

Block formatting context: Floats, margin collapsing, clear. Floats interact with line boxes — text wraps around floated elements. Margin collapsing follows CSS 2.1 rules including the many edge cases (empty blocks, clearance, negative margins).

Inline formatting context: Line box construction, baseline alignment, bidirectional text. Text is shaped into glyph runs, then broken into lines respecting word-break, overflow-wrap, hyphens. Bidi reordering happens after line breaking.

Table layout: Column width distribution with table-layout: auto requires measuring content, distributing excess space proportionally, and respecting min/max constraints. Border collapsing follows CSS 2.1 §17.6 conflict resolution.

Multi-column: Content flows through column fragmentainers. Column breaks respect break-before/break-after/break-inside. Balancing attempts to equalize column heights.

Paint order

flowchart TD
    Fragments[Fragment tree] --> DL[Display list builder]
    
    DL --> Stack{stacking context?}
    Stack --> |z-index, opacity, transform| NewCtx[New stacking context]
    Stack --> |normal flow| Parent[Parent context]
    
    NewCtx --> Order[Paint order]
    Order --> BG[1. Background/borders]
    Order --> Neg[2. Negative z-index]
    Order --> BlockBG[3. Block backgrounds]
    Order --> Float[4. Floats]
    Order --> InlineContent[5. Inline content]
    Order --> Pos[6. Positioned z-index 0]
    Order --> PosZ[7. Positive z-index]
    
    DL --> Effects{effects?}
    Effects --> Filter[CSS filters]
    Effects --> Blend[mix-blend-mode]
    Effects --> Backdrop[backdrop-filter]
    Effects --> Clip[clip-path]
    Effects --> Mask[mask layers]
    
    DL --> Transform{transforms?}
    Transform --> T2D[2D transforms]
    Transform --> T3D[3D + perspective]
    Transform --> Flatten[Flatten to 2D for raster]
Loading

Stacking contexts isolate z-ordering. Elements with opacity < 1, transform, filter, or explicit z-index on positioned elements create new stacking contexts. Paint order within a context follows CSS 2.1 Appendix E.

3D transforms with perspective are supported but flattened to 2D for the software rasterizer. transform-style: preserve-3d is partially supported.


Text pipeline

flowchart LR
    Text[Text content] --> Segment[Segmentation]
    Segment --> |UAX #29| Grapheme[Grapheme clusters]
    Segment --> |UAX #14| LineBreak[Line break opportunities]
    
    Segment --> Bidi[Bidi algorithm]
    Bidi --> |UAX #9| Levels[Embedding levels]
    Levels --> Reorder[Visual reordering]
    
    Reorder --> Itemize[Script itemization]
    Itemize --> Runs[Shaped runs]
    
    Runs --> Shape[OpenType shaping]
    Shape --> |features| GSUB[GSUB substitution]
    Shape --> |positioning| GPOS[GPOS positioning]
    
    Shape --> Glyphs[Glyph buffer]
    Glyphs --> Raster{glyph type?}
    Raster --> |outline| Outline[Outline rasterization]
    Raster --> |COLR| COLR[Color layers]
    Raster --> |sbix/CBDT| Bitmap[Embedded bitmap]
    Raster --> |SVG| SVGGlyph[SVG rendering]
Loading

Text rendering involves:

  1. Segmentation: Split text at script boundaries, identify grapheme clusters (UAX #29) and line break opportunities (UAX #14).

  2. Bidi: Run the Unicode Bidirectional Algorithm (UAX #9) to determine embedding levels. Mixed LTR/RTL text gets reordered for visual display.

  3. Shaping: OpenType shaping via RustyBuzz applies GSUB substitutions (ligatures, contextual alternates) and GPOS positioning (kerning, mark placement). Complex scripts like Arabic and Devanagari require shaping for correct rendering.

  4. Line breaking: Break shaped runs into lines respecting available width, word-break, overflow-wrap, and soft hyphens. hyphens: auto uses language-specific hyphenation dictionaries.

  5. Color fonts: Glyphs may be outlines (rasterized normally), COLR layers (multiple colored paths), sbix/CBDT bitmaps (embedded PNGs), or SVG (rendered via resvg). COLR v1 supports gradients and blend modes.


JavaScript integration

flowchart TD
    subgraph "HTML parsing"
        Parser[HTML parser] --> Script{script tag?}
        Script --> |inline| Inline[Queue inline script]
        Script --> |src| Fetch[Fetch external]
        Script --> |defer| Defer[Defer queue]
        Script --> |async| Async[Async queue]
        Script --> |module| Module[Module graph]
    end
    
    subgraph "Event loop"
        TaskQ[Task queue] --> Pick[Pick oldest task]
        Pick --> Run[Run to completion]
        Run --> Micro[Microtask checkpoint]
        Micro --> |drain all| Micro
        Micro --> RAF{rAF callbacks?}
        RAF --> Frame[Run frame callbacks]
        Frame --> Render[Render]
        Render --> Idle{idle time?}
        Idle --> RIC[requestIdleCallback]
    end
    
    subgraph "VM execution"
        Run --> VM[vm-js bytecode]
        VM --> |fuel budget| Budget[Interrupt check]
        Budget --> |exceeded| Pause[Yield to host]
        VM --> |DOM call| Binding[WebIDL binding]
        Binding --> Mutation[DOM mutation]
        Mutation --> Invalidate[Invalidate style/layout]
    end
Loading

JavaScript execution follows the HTML spec's processing model:

Script loading: Parser-inserted scripts block parsing until executed. defer scripts run after parsing in document order. async scripts run when ready. Module scripts build a dependency graph and execute after all imports resolve.

Event loop: Tasks (timers, network callbacks, user events) are queued and executed one at a time. After each task, the microtask queue drains completely (Promise reactions, queueMicrotask). Frame callbacks (requestAnimationFrame) run before rendering. Idle callbacks (requestIdleCallback) run when the event loop has spare time.

Budgeting: The VM (vm-js) uses fuel-based budgeting. Each operation consumes fuel; when fuel exhausts, execution yields to the host. This prevents infinite loops from hanging the browser. Wall-time limits provide a secondary bound.

DOM bindings: Web IDL bindings expose DOM APIs to JavaScript. DOM mutations trigger style/layout invalidation. The binding layer is incomplete — many methods are stubbed and throw. Coverage is growing.

Import maps: <script type="importmap"> is supported. Module specifier resolution goes through the import map before URL resolution.


CSS cascade

flowchart TD
    Rules[All matching rules] --> Origin{origin?}
    
    Origin --> UA[User-agent]
    Origin --> Author[Author]
    
    Author --> Layer{layer?}
    Layer --> Unlayered[Unlayered rules]
    Layer --> Named[Named layers]
    Named --> LayerOrder[Layer order]
    
    Author --> Scope{scope?}
    Scope --> Scoped[Scoped rules]
    Scoped --> Proximity[Scope proximity]
    
    Rules --> Important{important?}
    Important --> |yes| Reverse[Reverse origin order]
    Important --> |no| Normal[Normal order]
    
    Normal --> Specificity[Sort by specificity]
    Specificity --> |id, class, type| Spec[Specificity tuple]
    
    Spec --> Order[Source order]
    Order --> Winner[Winning declaration]
    
    Winner --> Inherit{inherited?}
    Inherit --> |yes| Parent[From parent]
    Inherit --> |no| Initial[Initial value]
    
    Winner --> Compute[Computed value]
    Compute --> Resolve[Resolve relative units]
    Resolve --> Final[Used value]
Loading

The cascade implements CSS Cascade Level 4:

Origins: User-agent styles (browser defaults) < author styles. !important reverses the order.

Layers: @layer groups rules into named layers. Layer order is determined by first appearance. Unlayered rules beat layered rules (within the same origin).

Scope: @scope limits rule applicability to a subtree. Scope proximity breaks ties when multiple scoped rules match.

Specificity: (id count, class/attribute/pseudo-class count, type/pseudo-element count). Higher specificity wins.

Custom properties: --custom properties participate in the cascade and inherit by default. var(--x, fallback) substitution happens at computed-value time.

Container queries: @container rules match based on ancestor container size or style. Style queries can test custom property values.


Multiprocess architecture (target)

flowchart TD
    subgraph "Browser process"
        UI[Browser UI] --> Chrome[Chrome/tabs]
        Chrome --> Nav[Navigation]
        Nav --> IPC1[IPC channel]
    end
    
    subgraph "Network process"
        IPC1 --> NetMgr[Network manager]
        NetMgr --> HTTP[HTTP stack]
        NetMgr --> Cache[Disk cache]
        NetMgr --> Cookie[Cookie jar]
    end
    
    subgraph "Renderer process (sandboxed)"
        IPC1 --> Renderer[Renderer]
        Renderer --> Pipeline[Render pipeline]
        Renderer --> JS[JS execution]
        
        Sandbox[OS sandbox]
        Sandbox --> |Linux| Seccomp[seccomp-bpf]
        Sandbox --> |macOS| Seatbelt[Seatbelt profile]
        Sandbox --> |Windows| AppContainer[AppContainer]
    end
    
    Renderer --> |shared memory| Compositor[Compositor]
    Compositor --> GPU[GPU process]
Loading

This is the target architecture. Currently the browser runs the renderer on a worker thread within the same process.

Sandbox helpers exist and are tested:

  • Linux: seccomp-bpf denies filesystem opens, network socket creation, and exec. Landlock provides optional filesystem restriction.
  • macOS: Seatbelt profiles restrict filesystem and network access.
  • Windows: AppContainer with zero capabilities; Job Objects enforce process limits.

The IPC layer (src/ipc/, crates/fastrender-ipc/) defines message protocols for navigation, resource loading, and frame transport. Shared memory frame buffers avoid copying pixel data.


Build requirements

All platforms

  • Rust 1.70+ (stable)
  • Git (submodules)
  • CMake

macOS

xcode-select --install
brew install cmake make

Linux (Ubuntu/Debian)

sudo apt-get update
sudo apt-get install -y \
  build-essential pkg-config cmake clang lld \
  libasound2-dev libwayland-dev libxkbcommon-dev \
  libvulkan-dev libegl1-mesa-dev libx11-dev

Building

Initialize submodules:

git submodule update --init vendor/ecma-rs

Build and run the browser:

cargo run --release --features browser_ui --bin browser

The browser_ui feature enables the desktop shell. Core renderer builds can omit this.

Binaries

Binary Purpose
browser Desktop browser with tabs, navigation, bookmarks
fetch_and_render Fetch URL, render to PNG
fetch_pages Cache pageset HTML
prefetch_assets Warm subresource cache
pageset_progress Render pageset, update accuracy scoreboard
render_fixtures Render offline test fixtures
bundle_page Capture page + subresources for offline replay
inspect_frag Dump fragment tree, pipeline state
dump_a11y Export accessibility tree as JSON
diff_renders Pixel-diff two render outputs

Library API

use fastrender::FastRender;

let mut renderer = FastRender::new()?;
let pixmap = renderer.render_html("<h1>Hello</h1>", 800, 600)?;
pixmap.save_png("out.png")?;

For URL rendering with diagnostics:

use fastrender::{FastRender, RenderOptions, DiagnosticsLevel};

let mut renderer = FastRender::new()?;
let result = renderer.render_url_with_options(
    "https://example.com",
    RenderOptions::new()
        .with_diagnostics_level(DiagnosticsLevel::Basic)
        .allow_partial(true),
)?;

for error in &result.diagnostics.fetch_errors {
    eprintln!("{}: {}", error.url, error.message);
}
result.pixmap.save_png("example.png")?;

For live documents with JavaScript, use BrowserTab which provides an event loop, script execution, and incremental rendering. See docs/runtime_stacks.md.

Conformance

Spec Status
HTML5 parsing Complete
CSS Selectors 4 Complete
CSS Cascade 4 Complete (layers, scope, custom properties)
CSS Grid 1 Supported (subgrid maturing)
CSS Flexbox 1 Complete
CSS Multi-column 1 Complete
CSS Tables Complete (auto + fixed layout)
CSS Transforms 2D complete, 3D flattened to 2D
CSS Filters Supported (subset of SVG filter graph)
CSS Animations Supported (keyframes, transitions, scroll/view timelines)
CSS Container Queries Supported (size + style queries)
CSS Fonts 4 Supported (variations, features, color fonts)
CSS Text 3/4 Supported (bidi, hyphenation, justification)
JavaScript Partial (event loop, DOM subset, growing Web API surface)
ARIA / ACCNAME 1.2 Supported (role mapping, name computation)

See docs/conformance.md for the detailed matrix with implementation links.

Testing

cargo test --lib                        # unit tests in src/
cargo test --test integration           # integration tests
cargo test --lib css::parser            # specific module

Unit tests live alongside code in src/. Integration tests are in tests/integration.rs. Paint regressions are in src/paint/tests/. WPT coverage is in tests/wpt/.

Test fixtures in tests/pages/fixtures/ are self-contained page captures with all subresources inlined. Chrome-vs-FastRender diffs validate pixel accuracy against a reference browser.

View on GitHub

Recent activity

commits and pull requests

Recent open issues

view all

Commits per week

last 52 weeks
133410Week of 2025-08-03: 0 commitsWeek of 2025-08-10: 0 commitsWeek of 2025-08-17: 0 commitsWeek of 2025-08-24: 0 commitsWeek of 2025-08-31: 0 commitsWeek of 2025-09-07: 0 commitsWeek of 2025-09-14: 0 commitsWeek of 2025-09-21: 0 commitsWeek of 2025-09-28: 0 commitsWeek of 2025-10-05: 0 commitsWeek of 2025-10-12: 0 commitsWeek of 2025-10-19: 0 commitsWeek of 2025-10-26: 0 commitsWeek of 2025-11-02: 0 commitsWeek of 2025-11-09: 0 commitsWeek of 2025-11-16: 42 commitsWeek of 2025-11-23: 44 commitsWeek of 2025-11-30: 4 commitsWeek of 2025-12-07: 1 commitsWeek of 2025-12-14: 1921 commitsWeek of 2025-12-21: 879 commitsWeek of 2025-12-28: 1725 commitsWeek of 2026-01-04: 7499 commitsWeek of 2026-01-11: 13341 commitsWeek of 2026-01-18: 48 commitsWeek of 2026-01-25: 0 commitsWeek of 2026-02-01: 0 commitsWeek of 2026-02-08: 0 commitsWeek of 2026-02-15: 0 commitsWeek of 2026-02-22: 0 commitsWeek of 2026-03-01: 0 commitsWeek of 2026-03-08: 0 commitsWeek of 2026-03-15: 0 commitsWeek of 2026-03-22: 0 commitsWeek of 2026-03-29: 0 commitsWeek of 2026-04-05: 0 commitsWeek of 2026-04-12: 0 commitsWeek of 2026-04-19: 0 commitsWeek of 2026-04-26: 0 commitsWeek of 2026-05-03: 0 commitsWeek of 2026-05-10: 0 commitsWeek of 2026-05-17: 0 commitsWeek of 2026-05-24: 0 commitsWeek of 2026-05-31: 0 commitsWeek of 2026-06-07: 0 commitsWeek of 2026-06-14: 0 commitsWeek of 2026-06-21: 0 commitsWeek of 2026-06-28: 0 commitsWeek of 2026-07-05: 0 commitsWeek of 2026-07-12: 0 commitsWeek of 2026-07-19: 0 commitsWeek of 2026-07-26: 0 commitsAug 3, 2025Jul 26, 2026
25.5K commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 163 commitsSun 1:00 — 246 commitsSun 2:00 — 124 commitsSun 3:00 — 317 commitsSun 4:00 — 257 commitsSun 5:00 — 392 commitsSun 6:00 — 374 commitsSun 7:00 — 277 commitsSun 8:00 — 254 commitsSun 9:00 — 223 commitsSun 10:00 — 198 commitsSun 11:00 — 221 commitsSun 12:00 — 222 commitsSun 13:00 — 249 commitsSun 14:00 — 247 commitsSun 15:00 — 171 commitsSun 16:00 — 153 commitsSun 17:00 — 135 commitsSun 18:00 — 106 commitsSun 19:00 — 258 commitsSun 20:00 — 382 commitsSun 21:00 — 362 commitsSun 22:00 — 349 commitsSun 23:00 — 262 commitsMon 0:00 — 266 commitsMon 1:00 — 204 commitsMon 2:00 — 182 commitsMon 3:00 — 155 commitsMon 4:00 — 213 commitsMon 5:00 — 129 commitsMon 6:00 — 118 commitsMon 7:00 — 100 commitsMon 8:00 — 124 commitsMon 9:00 — 82 commitsMon 10:00 — 114 commitsMon 11:00 — 122 commitsMon 12:00 — 100 commitsMon 13:00 — 67 commitsMon 14:00 — 16 commitsMon 15:00 — 0 commitsMon 16:00 — 26 commitsMon 17:00 — 302 commitsMon 18:00 — 467 commitsMon 19:00 — 418 commitsMon 20:00 — 337 commitsMon 21:00 — 251 commitsMon 22:00 — 3 commitsMon 23:00 — 0 commitsTue 0:00 — 72 commitsTue 1:00 — 336 commitsTue 2:00 — 367 commitsTue 3:00 — 343 commitsTue 4:00 — 335 commitsTue 5:00 — 424 commitsTue 6:00 — 364 commitsTue 7:00 — 363 commitsTue 8:00 — 387 commitsTue 9:00 — 321 commitsTue 10:00 — 254 commitsTue 11:00 — 211 commitsTue 12:00 — 186 commitsTue 13:00 — 141 commitsTue 14:00 — 214 commitsTue 15:00 — 238 commitsTue 16:00 — 287 commitsTue 17:00 — 318 commitsTue 18:00 — 248 commitsTue 19:00 — 246 commitsTue 20:00 — 194 commitsTue 21:00 — 204 commitsTue 22:00 — 155 commitsTue 23:00 — 139 commitsWed 0:00 — 156 commitsWed 1:00 — 162 commitsWed 2:00 — 138 commitsWed 3:00 — 135 commitsWed 4:00 — 86 commitsWed 5:00 — 81 commitsWed 6:00 — 87 commitsWed 7:00 — 98 commitsWed 8:00 — 89 commitsWed 9:00 — 92 commitsWed 10:00 — 74 commitsWed 11:00 — 70 commitsWed 12:00 — 63 commitsWed 13:00 — 55 commitsWed 14:00 — 10 commitsWed 15:00 — 0 commitsWed 16:00 — 0 commitsWed 17:00 — 0 commitsWed 18:00 — 0 commitsWed 19:00 — 0 commitsWed 20:00 — 0 commitsWed 21:00 — 0 commitsWed 22:00 — 0 commitsWed 23:00 — 1 commitsThu 0:00 — 0 commitsThu 1:00 — 0 commitsThu 2:00 — 0 commitsThu 3:00 — 0 commitsThu 4:00 — 0 commitsThu 5:00 — 0 commitsThu 6:00 — 0 commitsThu 7:00 — 0 commitsThu 8:00 — 0 commitsThu 9:00 — 0 commitsThu 10:00 — 0 commitsThu 11:00 — 0 commitsThu 12:00 — 0 commitsThu 13:00 — 0 commitsThu 14:00 — 0 commitsThu 15:00 — 0 commitsThu 16:00 — 0 commitsThu 17:00 — 0 commitsThu 18:00 — 0 commitsThu 19:00 — 0 commitsThu 20:00 — 0 commitsThu 21:00 — 0 commitsThu 22:00 — 0 commitsThu 23:00 — 0 commitsFri 0:00 — 0 commitsFri 1:00 — 0 commitsFri 2:00 — 3 commitsFri 3:00 — 3 commitsFri 4:00 — 1 commitsFri 5:00 — 1 commitsFri 6:00 — 1 commitsFri 7:00 — 5 commitsFri 8:00 — 2 commitsFri 9:00 — 1 commitsFri 10:00 — 9 commitsFri 11:00 — 4 commitsFri 12:00 — 7 commitsFri 13:00 — 9 commitsFri 14:00 — 26 commitsFri 15:00 — 129 commitsFri 16:00 — 86 commitsFri 17:00 — 61 commitsFri 18:00 — 70 commitsFri 19:00 — 82 commitsFri 20:00 — 108 commitsFri 21:00 — 70 commitsFri 22:00 — 83 commitsFri 23:00 — 133 commitsSat 0:00 — 188 commitsSat 1:00 — 167 commitsSat 2:00 — 121 commitsSat 3:00 — 118 commitsSat 4:00 — 93 commitsSat 5:00 — 104 commitsSat 6:00 — 79 commitsSat 7:00 — 54 commitsSat 8:00 — 51 commitsSat 9:00 — 70 commitsSat 10:00 — 77 commitsSat 11:00 — 72 commitsSat 12:00 — 53 commitsSat 13:00 — 60 commitsSat 14:00 — 42 commitsSat 15:00 — 38 commitsSat 16:00 — 40 commitsSat 17:00 — 31 commitsSat 18:00 — 27 commitsSat 19:00 — 27 commitsSat 20:00 — 22 commitsSat 21:00 — 21 commitsSat 22:00 — 25 commitsSat 23:00 — 44 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.

Who is committing

last 52 weeks
Maintainer commits25,924 (87%)
Community commits3,934 (13%)

29,858 commits in total over the last year.

DateListRankStars gained
Jan 15, 2026daily#24+134
  • f/prompts.chat

    f.k.a. Awesome ChatGPT Prompts. Share, discover, and collect prompts from the community. Free and open source — self-host for your organization with complete privacy.

    166.9K stars · HTML

  • ripienaar/free-for-dev

    A list of SaaS, PaaS and IaaS offerings that have free tiers of interest to devops and infradev

    131.2K stars · HTML

  • shanraisshan/claude-code-best-practice

    from vibe coding to agentic engineering - practice makes claude perfect

    64.1K stars · HTML

  • op7418/guizang-ppt-skill

    AI-agent Skill for generating polished HTML slide decks: editorial magazine and Swiss layouts, image prompts, social covers, and a WebGL/low-power presentation runtime.

    23.5K stars · HTML

  • alchaincyf/huashu-design

    Huashu Design · HTML-native design skill for Claude Code · Claude Code 里 HTML 原生的设计 skill · 高保真原型 / 幻灯片 / 动画 + 20 设计哲学 + 5 维评审 + MP4 导出 · Agent-agnostic

    22.6K stars · HTML

  • hasaneyldrm/exercises-dataset

    1,324-exercise fitness dataset — animation GIFs, 180×180 thumbnails, muscle-group & equipment data, and step-by-step instructions in 6 languages. The exercise data layer behind the LogPress app.

    19.1K stars · HTML