cd /news/developer-tools/falco-tiny-browser-engine-written-fr… Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-83860] src=github.com β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

Falco: Tiny browser engine written from scratch in Rust

Falco, a browser engine written from scratch in Rust by a single developer, is now available as v0.1.0, comprising roughly 36,000 lines of code that render HTML, CSS, JavaScript, SVG, and images to PNG or an interactive window. The engine includes a custom JS VM with JIT compilation, a hand-written PNG encoder, and support for flex/grid/table layout, but many spec-compliant modules (e.g., WHATWG tokenizer, Shadow DOM, Selectors Level 4) are compiled but not yet integrated into the render pipeline, with full integration planned for v0.2.0.

read16 min views1 publishedAug 2, 2026
Falco: Tiny browser engine written from scratch in Rust
Image: source

Logo by Sanya β€” t.me/SanyochekDev

A tiny, fast browser engine written in Rust.

Renders HTML, CSS, JavaScript, SVG and images β€” to a PNG, or to a live interactive window.

Quick start Β· Interactive mode Β· Features Β· Architecture Β· Contributing

Falco is a real browser engine in roughly 36,000 lines of Rust. It parses HTML, applies CSS, executes JavaScript, loads images, computes layout, and paints to a canvas β€” either as a PNG file or a live interactive window where you can scroll, click links, fill out forms, and navigate.

HTML ──▢ DOM ──▢ Style tree ──▢ Layout tree ──▢ Paint commands ──▢ Canvas ──▢ PNG / Window
            β–²           β–²              β–²
            β”‚           β”‚              β”‚
       HTML5 tokenizer  CSS cascade    Flex / Grid / Table / Float / Absolute
       + tree builder   + Selectors 4  + Inline / Block flow
            β”‚
       JS (custom VM with closures, generators, Promise, BigInt, Symbol)
            β”‚
       Image  ──▢ HTTP / data: URL / local file

Falco is not a wrapper around WebKit, Gecko, or Chromium. Every module β€” HTML tokenizer, CSS parser, layout engine, JS VM, font rasterizer, PNG encoder β€” is written from scratch in Rust.

To set expectations clearly β€” this is v0.1.0, an early release by a single developer. Not everything listed in this README is production-ready. Here's what is actually wired into the render pipeline and what is structurally complete but not yet called:

  • HTML parser ( html/

) β€” legacy parser, not spec-compliant but functional - DOM types ( dom/

) β€” minimal node types, no observers/shadow - CSS parser ( css/

) β€” selectors, properties, cascade, color parsing - Style cascade ( style/

) β€” UA styles + inheritance + flex/grid props - Layout ( layout/

) β€” block / inline / flex /CSS Grid/** table**/ float / absolute - Painting ( paint/

) β€” fonts (ab_glyph), gradients, shadows, alpha compositing - SVG renderer ( svg/

) β€” paths, basic shapes, gradients, stroke + fill - Hand-written PNG encoder ( png/

) - Image ( image/

) β€” HTTP, data: URLs, local files - JS VM ( tjs/

) β€” bytecode interpreter + JIT (x86_64, Linux-only) - JS-DOM bindings ( js_tjs/

,js_runner/

) β€”document.getElementById

,console.log

,alert

,onclick

  • Networking ( net/

) β€” HTTP/1.1 (ureq), cookies, cache, websocket, redirect - Interactive --window

mode β€” scrolling, forms, navigation, history

These exist as spec-compliant replacements for the legacy modules. They compile and have their own unit tests, but render_with_base_url

does not call into them yet. This is the v0.2.0 milestone.

html::spec

β€” WHATWG Β§13.2 tokenizer (all 80 states) + tree builder (all 22 insertion modes) + serializer + XML parser + encoding detectiondom::spec

β€” spec DOM with MutationObserver, Shadow DOM, custom elements, accessibility treecss::spec

β€” Selectors Level 4 (:has()

,:is()

,:where()

, cascade layers, container queries)tjs_ext/

β€” Symbol, BigInt, Promise, microtasks, Map/Set, WeakMap/WeakSet, Reflect

security/

β€” SOP, multi-process, seccomp sandbox, CSP, TLS cert chain validation, permissions, extensions, DevTools protocol. All algorithms are in place and unit-tested, but the renderer doesn't enforce them yet.web_runtime/

β€”fetch()

,XMLHttpRequest

, event loop, Promise. The Promise / event loop integration is real and unit-tested, butfetch

andXHR

are stubbed (no real network behind them in the JS context). WebGL, video, MSE, EME, NDSD areheadless stubsβ€” they implement the API surface but don't actually render WebGL frames, decode H.264 video, or do DRM. They exist as scaffolding for future work.media/

β€”@media

queries are parsed but always applied (no conditional cascade yet)

real-http2

,real-webgl

,sandbox

Cargo features do not compile with--all-features

because their upstream APIs have drifted (h2::Body removed, glow API changed, seccomp pre_exec is Unix-only). They are disabled by default and the CI clippy step does not check them.- The JIT ( tjs/jit.rs

) works on Linux x86_64 but fails on macOS CI runners becausemmap(MAP_JIT)

requires code signing with thecom.apple.security.cs.allow-jit

entitlement. JIT tests are marked#[ignore]

on macOS. - DOM mutation from JS ( element.innerHTML = ...

,element.style.color = ...

) does not trigger re-render. - HTML5 spec-compliant tree repair (adoption agency, foster parenting) is in html/spec/tree_builder.rs

but the legacy parser is what actually runs.

Bottom line: if you cargo build && ./falco https://example.com --out out.png

, you get a real PNG render. The HTML/CSS/layout/paint path works end-to-end. The spec-compliant parsers, security enforcement, and advanced web runtime (WebGL/video/DRM) are scaffolding for future milestones, not working features. Please read the code before claiming otherwise.

cargo build --release

./target/release/falco page.html --out page.png --width 1200

./target/release/falco https://example.com --out example.png --width 800

./target/release/falco page.html --window

./target/release/falco README.html --css style.css --out readme.png

<style>

tags inside the HTML are automatically extracted and applied. External CSS via --css

is merged on top.

When you pass --window

, Falco opens a real browser window with an address bar at the top, the page content in the middle, and a status bar at the bottom. You can:

Click links(<a href>

) β€” Falco fetches the new URL and re-rendersAddress barβ€” click it or pressF6

, type a URL, pressEnter

Reload withr

β€” re-fetches the current pageBack/Forward withAlt+←

/Alt+β†’

β€” full history navigation

Click inputs to focus them, thentype to enter text (live update)Tab / Shift+Tabβ€” cycle focus between interactive elements** Backspace**β€” delete the last character** Enter**β€” submit form / click the focused button / follow focused link- Supported types: text

,email

,password

(masked),checkbox

,submit

,button

,textarea

Mouse wheel,** arrow keys**,** Page Up/Down**,** Home/End****Focus ring**β€” 2px blue outline around the focused element** Blinking caret**β€” 500ms blink in text inputs and the address bar** Hover hint**β€” when hovering a link, its href appears in the status bar

The window only re-paints when state actually changes (scroll, input text, focus, hover). On idle frames, only the address bar / status bar overlays are redrawn β€” the page canvas is cached. This keeps CPU usage low and scrolling smooth.

If no display is available (headless server, no X11/Wayland), Falco automatically falls back to PNG output with a warning.

falco β€” a tiny browser engine

USAGE
  falco <input> [OPTIONS]

INPUT
  A URL (http://...) or a path to a local .html file.

OPTIONS
  --css <path>       External CSS file (merged with <style> tags in HTML).
  --out <path>       Output PNG path. Default: falco.png
  --width <px>       Viewport width. Default: 1200
  --height <px>      Viewport height (canvas grows if content is taller). Default: 800
  --bg <hex>         Background color (0xRRGGBBAA). Default: 0xFFFFFFFF
  --window           Open a live interactive window instead of writing PNG.
  -h, --help         Show this help
  -V, --version      Print version

INTERACTIVE MODE KEYS (when --window is used)
  q / Esc       quit
  r             reload (prints message β€” restart Falco to actually reload)
  ↑ / ↓         scroll line
  PgUp / PgDn   scroll page
  Home / End    jump to top / bottom
  g / G         top / bottom (vim-style)
  mouse wheel   scroll
  mouse click   follow `<a href>` link (prints URL to stderr)
php
use falco::{render_to_png, RenderOptions};

fn main() -> anyhow::Result<()> {
    let html = std::fs::read_to_string("page.html")?;
    let css = std::fs::read_to_string("style.css")?;
    let opts = RenderOptions {
        width: 1200,
        height: 800,
        background: 0xFFFFFFFF,
    };
    render_to_png(&html, &css, opts, "out.png")?;
    Ok(())
}

HTML5 tokenizer(WHATWG Β§13.2.5) β€” all 80 states, script-data escape/double-escape, attribute parsing with duplicate detection, named + numeric character references with Windows-1252 quirksHTML5 tree builder(WHATWG Β§13.2.6) β€” all 22 insertion modes, stack of open elements with scope algorithms, active formatting elements list, reconstruct active formatting,adoption agency algorithm,** foster parenting**for table content,<template>

with separate DocumentFragment contentsEntity referencesβ€”&

,A

,Β©

, 50+ named entitiesWhitespace collapsing(browser-style)with separate DocumentFragment contents<template>

elementXML/XHTML parserβ€” strict, with namespace bindings, CDATA, PIs** Encoding detection**β€” BOM, HTTPContent-Type

charset,<meta charset>

,<meta http-equiv>

, heuristic UTF-8/UTF-16 detection, decoders for UTF-8 / UTF-16LE / UTF-16BE / Windows-1252Tree builder auto-closeβ€”<li>

,<p>

,<td>

,<tr>

,<option>

,<dt>

/<dd>

innerHTML / outerHTML serializationβ€” void elements,<template>

contents fragment, raw text elements, full attribute value escaping

NodeRef = Rc<RefCell<Node>>

withparent

,firstChild

,lastChild

,previousSibling

,nextSibling

pointers per specDocumentHandle = Rc<RefCell<Document>>

with weak back-ref from each NodeMutation records queued on every append/insert/remove/setAttribute/removeAttributeMutationObserver withobserve()

,disconnect()

,take_records()

,MutationObserverInit

(childList/attributes/characterData/subtree/attributeOldValue/ characterDataOldValue/attributeFilter), subtree ancestor matchingShadow DOMβ€”attachShadow()

with open/closed modes, host validation, named + default slots, fallback content, slot distribution (flatten tree algorithm),assignedSlot

lookupCustom elementsβ€”customElements.define()

with name validation,observedAttributes

tracking, lifecycle callbacks (connected / disconnected / adopted / attributeChanged / form-associated), pending upgrades, customized built-in elements (is="..."

)Accessibility treeβ€” parallel tree with role/name/description/ state/actions, implicit ARIA roles for ~50 HTML tags, honorsrole=""

,aria-hidden

,hidden

,display:none

, accessible name computation (aria-label > aria-labelledby > element-specific > title)

Selectors Level 4β€” type, class, id, universal (*

), descendant, child (>

), adjacent sibling (+

), general sibling (~

), attribute ([attr]

,=

,~=

,|=

,^=

,$=

,*=

)Pseudo-classesβ€”:hover

,:focus

,:focus-visible

,:focus-within

,:active

,:visited

,:checked

,:disabled

,:enabled

,:readonly

,:readwrite

,:required

,:optional

,:valid

,:invalid

,:empty

,:root

,:first-child

,:last-child

,:only-child

,:first-of-type

,:last-of-type

,:only-of-type

,:nth-child(an+b)

,:nth-last-child

,:nth-of-type

,:nth-last-of-type

,:nth-child(an+b of S)

,:is()

,:where()

,:not()

,:has()

,:lang()

,:dir()

Cascade & specificityβ€” (a, b, c) tuple,:where()

zero,:is()

/:not()

/:has()

most specific arg, CascadeOrigin (UA / User / Author) with reversed order for!important

, CascadeLayers (None wins over layered; later wins over earlier)Propertiesβ€”display

,position

,color

,background

(includinglinear-gradient

andradial-gradient

),font-*

,margin

,padding

,border

,border-radius

,width

,height

,min/max-width

,top/right/bottom/left

,z-index

,overflow

,opacity

,box-shadow

,white-space

,box-sizing

,gap

,flex*

,grid*

,writing-mode

, logical properties (margin-inline-start

, etc.)Valuesβ€” keywords, hex/rgb/rgba/named colors, lengths (px, em, rem, pt, %, vw, vh), percentages, numbers,!important

Functionsβ€”linear-gradient()

,radial-gradient()

,url()

,var()

,calc()

(simplified),rgb()

,rgba()

Shorthandsβ€”margin

,padding

,border

,background

,flex

@-rulesβ€”@media

(parsed and applied),@keyframes

/@animation

with cubic-bezier & steps timing functions,@font-face

with family/weight lookup,@layer

(cascade layers),@container

queries withevaluate_container_query()

Logical propertiesβ€”margin-inline-start

etc. resolved to physical properties based onwriting-mode

CSS countersβ€”counter-reset

,counter-increment

,counter-set

Containmentβ€”contain: layout/paint/size/style/inline-size/ block-size

,strict

,content

Filtersβ€”blur

,brightness

,contrast

,drop-shadow

,grayscale

,hue-rotate

,invert

,opacity

,saturate

,sepia

Clip-pathβ€”polygon

,circle

,ellipse

,inset

,path

,url()

Block flowβ€” vertical stacking** Inline flow**β€” horizontal text wrapping with proper baseline** Flexbox**β€”flex-direction

,justify-content

,align-items

,flex-wrap

,gap

,flex-grow

,flex-shrink

,flex-basis

CSS Gridβ€”grid-template-columns

/grid-template-rows

(withfr

,auto

,minmax()

,repeat()

),grid-column

/grid-row

placement,gap

/column-gap

/row-gap

,auto-flow

Table layoutβ€”<table>

,<tr>

,<td>

,<th>

,<thead>

,<tbody>

,<tfoot>

,<caption>

, column width distribution, border collapseFloatβ€”float: left/right

, simple clearInline-blockβ€” inline elements with block-like width/height** Box model**β€” margin, border, padding, content withbox-sizing: border-box

supportPositionβ€”static

,relative

,absolute

,fixed

(parsed, relative + absolute positioning applied)Unitsβ€” px, em, rem, pt, %, vw, vh** Writing modes**β€”horizontal-tb

,vertical-rl/lr

,sideways-rl/lr

Backgroundsβ€” solid colors and linear / radial gradients** Borders**β€” all four sides with custom colors and styles** Border-radius**β€” rounded corners (all four corners)** Box-shadow**β€” outer shadows with blur** Opacity**β€” alpha blending for entire elements** Text**β€” TrueType font rasterization viaab_glyph

, bold and italic synthesisAlpha compositingβ€” proper RGBA blending** SVG**β€” paths, basic shapes (rect

,circle

,ellipse

,line

,polyline

,polygon

), gradients, stroke + fillPNG encoderβ€” hand-written, noflate2

dependency

Falco ships its own JavaScript VM (the tjs

module) β€” pure Rust, no V8/SpiderMonkey/boa

. It is a bytecode VM with a generational GC, inline caching, hidden classes, and a JIT tier-up.

ES2015+ syntaxβ€”let

/const

, arrow functions, template literals, destructuring (object + array), default + rest params, spread,for...of

,for...in

, computed property names, shorthand methods/properties, optional chaining, nullish coalescing, exponentiation operator, async/await (parsed)Functionsβ€”function foo() {}

, closures with proper upvalue capture, generators (function*

/yield

/yield*

),async function

/await

(parser-level)Typesβ€”Symbol

with 13 well-known symbols,BigInt

with arbitrary precision (u32 limbs, signed),Promise

withthen

/catch

/finally

  • state machine,Iterator

protocol,Generator

as state machineBuilt-insβ€”Math

,JSON

,Array

(push

,pop

,map

,filter

,reduce

,forEach

,find

,findIndex

,includes

,slice

,splice

,flat

,flatMap

),String

(split

,replace

,match

,padStart

,padEnd

,trim

,trimStart

,trimEnd

,startsWith

,endsWith

,includes

,repeat

),Object

(keys

,values

,entries

,assign

,freeze

,fromEntries

),Reflect

(get

,set

,has

,deleteProperty

,ownKeys

),WeakMap

,WeakSet

,Map

,Set

,Proxy

Microtask queueβ€”Promise

reactions drained as microtasksDOM bindingsβ€”document.getElementById

,document.querySelector

/querySelectorAll

,console.log

,alert

,addEventListener

(basic)Event loop integrationβ€”setTimeout

,setInterval

,requestAnimationFrame

,fetch()

(returnsPromise<Response>

),XMLHttpRequest

, all driven by the event loop inweb_runtime/event_loop.rs

console.log(...)β€” prints to stderr** alert(msg)**β€” shows in the status bar

  • HTTP/1.1 fetch (via ureq

) - HTTP/2 parser ( http2.rs

) - Cookie jar ( cookies.rs

) with proper domain/path matching - Redirect handling ( redirect.rs

) with redirect-loop detection - Cache ( cache.rs

) β€” HTTP cache with conditional requests - WebSocket ( websocket.rs

) β€” frame parser, masking, ping/pong

fetch()

(fetch.rs

) β€” Promise-based, integrates with event loopXMLHttpRequest

(xhr.rs

) β€” sync + async modes- Event loop ( event_loop.rs

) β€” task queues, microtasks, RAF Promise

(promise.rs

) β€” state machine, then/catch/finally- WebGL ( webgl.rs

) β€” shader compilation, buffer management, draw calls (headless) - Video ( video.rs

) β€”<video>

element demux + decode stub - MSE ( mse.rs

) β€” Media Source Extensions - EME ( eme.rs

) β€” Encrypted Media Extensions - NDSD ( ndsd.rs

) β€” Native Device Service Discovery

Origin / SOP(origin.rs

) β€” Origin struct,is_same_origin

,is_same_site

,registrable_domain

(with 2-part TLD list),check_cors

(with credentials / wildcard handling),check_navigation

Multi-process / site isolation(process.rs

) β€” Process kinds (Browser / Renderer / GPU / Utility / Plugin), site-to-process map, ProcessPerSite / ProcessPerTab policies, crash recovery with max-restarts / sad-tab / fatal modesSandbox(sandbox.rs

) β€” seccomp-bpf filter (Linux), renderer allowlist (~30 syscalls), blocksexecve

/fork

/ptrace

/open

/socket

/connect

/mount

,PR_SET_NO_NEW_PRIVS

,drop_capabilities

CSP(csp.rs

) β€” directive map,default-src

fallback, source expression matching ('self'

,'none'

,'unsafe-inline'

,'unsafe-eval'

,data:

,blob:

, host,*.wildcard

,scheme:

), nonce/hash support,allows_inline_script

,allows_eval

,allows_javascript_url

,is_safe_attribute

(blocksonclick

,onerror

,javascript:

in href/src), violation reportsTLS certificates(cert.rs

) β€” Certificate struct, validity, hostname matching (with wildcards), TrustStore with Mozilla defaults,validate_chain

(chain building, signature check, hostname, EKU, path length), OCSP stub, HPKP pinning, Certificate TransparencyPermissions(permissions.rs

) β€” 20 permission types (Geolocation, Camera, Microphone, Notifications, ...), per-(origin, permission) state, pluggable prompt handler, iframe allow parsingExtensions(extensions.rs

) β€” Manifest V3, content scripts, match patterns (<all_urls>

,*://*.host/*

), glob matching, permissions, generate extension ID, ChromeApi enumDevTools protocol(devtools.rs

) β€” JSON value type, Request/Response/Event/RpcError, Inspector/Page/Runtime/DOM/Network/ Console methods, event subscribers, console message buffering

HTTP/HTTPS URLsβ€” fetched viaureq

β€” base64-encoded inline imagesdata:

URLsLocal filesβ€” relative paths resolved against the page URL** Formats**β€” PNG, JPEG, GIF (first frame), BMP (via theimage

crate)Sizingβ€”width

/height

HTML attributes take precedence, CSSwidth

/height

respected, default 300Γ—200px, nearest-neighbor scalingBroken imagesβ€” grey placeholder box with thealt

textCachingβ€” global cache by URL

  • The html::spec

,dom::spec

,css::spec

,tjs_ext/

,security/

modules arestructurally complete but not yet wired into the render pipeline. Falco still uses the legacyhtml

/dom

/css

modules for actual rendering. The new modules exist as the spec-compliant replacements and pass their own unit tests, but the renderer has not been switched over yet. - No CSS animations / transitions in the renderer (the data structures exist in css/spec/advanced.rs

, but the paint loop does not interpolate them). - No @media

query value matching in the renderer (queries are parsed; the cascade does not yet apply them conditionally). - No real DOM mutation from JS in the renderer ( element.innerHTML = ...

,element.style.color = ...

are stubs). - No HTML5 spec-compliant tree repair in the renderer (the algorithm exists in html/spec/tree_builder.rs

but the legacy parser is used).

Module Lines Description
html::spec
~4,900 WHATWG HTML5 tokenizer + tree builder + serializer + XML parser + encoding
html.rs
~540 Legacy HTML parser (still used in render pipeline)
dom::spec
~2,280 Spec-compliant DOM, MutationObserver, Shadow DOM, custom elements, a11y
dom.rs
~140 Legacy DOM (still used in render pipeline)
css::spec
~2,020 Selectors L4, cascade specificity, @-rules, animations, containment, filters
css/
~1,660 Legacy CSS parser + selector matching + color parsing
style/
~1,720 Style cascade + UA styles + inheritance + flex/grid properties
layout/
~1,950 Block / inline / flex / grid / table / float / absolute layout
paint/
~470 Canvas + font rasterizer + alpha compositing + gradients + shadows
svg/
~1,130 SVG parser + renderer (paths, shapes, gradients)
tjs/
~4,340 Custom JS VM: lexer, parser, interpreter, bytecode VM, JIT, value, builtins
tjs_ext/
~780 Symbol, BigInt, Promise, microtasks, Map/Set, WeakMap/WeakSet, Reflect
js_tjs.rs
~700 JS-to-DOM bindings (document, console, alert, onclick)
web_runtime/
~4,300 fetch, XHR, event loop, Promise, WebGL, video, MSE, EME, NDSD, HTTP/2
net/
~930 HTTP fetch, cookies, cache, websocket, redirect
security/
~3,590 SOP, multi-process, sandbox, CSP, certs, permissions, extensions, DevTools
window/
~1,110 Interactive window: scrolling, forms, navigation, history, address bar
image/
~200 Image (HTTP, data: URLs, local files) + cache + scaling
png/
~100 Hand-written PNG encoder (no flate2 dependency)
main.rs , lib.rs
~550 CLI parsing + library entry points
Total
~36,000
falco/
β”œβ”€β”€ .github/                  # CI, issue templates, contributing, security policy
β”‚   β”œβ”€β”€ workflows/
β”‚   β”‚   β”œβ”€β”€ ci.yml            # fmt + clippy + build + test on 3 OSes Γ— 2 toolchains
β”‚   β”‚   └── release.yml       # Build per-OS release binaries on tag push
β”‚   β”œβ”€β”€ ISSUE_TEMPLATE/       # bug_report.md, feature_request.md, config.yml
β”‚   β”œβ”€β”€ CONTRIBUTING.md
β”‚   β”œβ”€β”€ CODE_OF_CONDUCT.md
β”‚   β”œβ”€β”€ SECURITY.md
β”‚   β”œβ”€β”€ PULL_REQUEST_TEMPLATE.md
β”‚   β”œβ”€β”€ FUNDING.yml           # MonoBank donation link
β”‚   └── dependabot.yml
β”œβ”€β”€ docs/                     # Logo
β”‚   └── falco.svg             # project logo (by Sanya)
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.rs
β”‚   β”œβ”€β”€ lib.rs
β”‚   β”œβ”€β”€ html/spec/                # WHATWG HTML5 (tokenizer, tree builder, ...)
β”‚   β”œβ”€β”€ html.rs               # legacy HTML parser
β”‚   β”œβ”€β”€ dom/spec/                 # spec DOM (observer, shadow, custom elements, a11y)
β”‚   β”œβ”€β”€ dom.rs                # legacy DOM
β”‚   β”œβ”€β”€ css/spec/                 # selectors L4, cascade, @-rules
β”‚   β”œβ”€β”€ css/                  # legacy CSS parser
β”‚   β”œβ”€β”€ style/                # cascade + inheritance + UA styles
β”‚   β”œβ”€β”€ layout/               # block/inline/flex/grid/table/float/absolute
β”‚   β”œβ”€β”€ paint/                # canvas + fonts + compositing
β”‚   β”œβ”€β”€ svg/                  # SVG parser + renderer
β”‚   β”œβ”€β”€ tjs/                  # custom JS VM (lexer, parser, VM, JIT)
β”‚   β”œβ”€β”€ tjs_ext/              # Symbol, BigInt, Promise, ...
β”‚   β”œβ”€β”€ web_runtime/          # fetch, XHR, event loop, WebGL, video, MSE, EME
β”‚   β”œβ”€β”€ net/                  # HTTP, cookies, cache, websocket, redirect
β”‚   β”œβ”€β”€ security/             # SOP, sandbox, CSP, certs, permissions, DevTools
β”‚   β”œβ”€β”€ window/               # interactive window mode
β”‚   β”œβ”€β”€ image/                # image 
β”‚   └── png/                  # PNG encoder
β”œβ”€β”€ Cargo.toml
β”œβ”€β”€ Cargo.lock
β”œβ”€β”€ LICENSE
└── README.md

The next big pieces of work, roughly in priority order:

Wireβ€” switch off the legacyhtml::spec

+dom::spec

into the render pipelinehtml

+dom

modules. This unlocks spec-compliant tree repair, full MutationObserver, and real custom elements.Wireβ€” getcss::spec

into the cascade:is

/:where

/:has

working in real rendering, plus cascade layers and container queries.DOM mutation from JSβ€”element.innerHTML = ...

,element.style.color = ...

, full re-render on mutation.CSS animations / transitionsβ€” interpolate keyframes in the paint loop, run them through the event loop.** Wire**β€” SOP enforcement in DOM access, CSP in the script runner, certificate validation on HTTPS fetches, multi-process sandbox.security/

into the rendererβ€” apply queries conditionally based on viewport size.@media

query value matching

If Falco is useful to you, consider buying the author a coffee:

MIT β€” see LICENSE.

── more in #developer-tools 4 stories Β· sorted by recency
── more on @falco 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/falco-tiny-browser-e…] indexed:0 read:16min 2026-08-02 Β· β€”