Brewser Docs

Engine Status

The remaining gaps in Brewser's from scratch HTML, CSS and DOM engine

There is no browser to borrow from on the Switch. Brewser's DOM tree, CSS cascade, and layout engine are reimplemented from scratch in TypeScript (~26K lines) running on top of the nx.js/V8 + Skia foundation (see Architecture). Overall, that from scratch engine (DOM, HTML, CSS) covers roughly 83% of the "real-world app" surface.

This page is the honest list of what's not done yet — the gap lists double as the contribution roadmap. The last two pillars, WebGL and Audio & Video, are bridge-backed rather than reimplemented, so they stand higher and their detail lives on their own pages. If an app or library breaks for you, file an issue with its name — real-world breakage reports directly shape what gets built next.

DOM (~84%)

  • children still includes text / comment nodes (spec is elements-only); the element-only accessors (firstElementChild / nextElementSibling / childElementCount …) are the correct-behaving alternative
  • outerHTML has no setter; document / window-level capture listeners aren't wired
  • dialog.showModal() has no focus trap or Esc-to-close; setPointerCapture doesn't reroute events

HTML (~80%)

  • No spec tokenizer / insertion modes: no <template> content model, no implicit <html> / <head> / <body> synthesis, comments and doctype are discarded (the parser is otherwise a tolerant tag-soup subset with error recovery)
  • No multipart/form-data request bodies (binary file upload); urlencoded GET + POST work. No <datalist> chrome
  • Inline SVG has no SMIL animation and only a filter subset (feGaussianBlur / feColorMatrix / feOffset / feDropShadow); filter-graph primitives (feComposite / feMerge / feTurbulence / feImage), gradientTransform / patternTransform, and spreadMethod reflect/repeat aren't modelled (<use> / <image> / patterns / markers / masks, shapes / paths / <text> / gradients / transform / viewBox are covered)
  • <video> has no subtitle (<track>) tracks; poster isn't loaded (a first-frame preview stands in)
  • iframe sandbox / CSP attributes are parsed but not enforced (treated as same-origin)

CSS (~84%)

  • Cascade: no @supports / @import / @layer / @container; ::placeholder / ::marker / ::selection pseudo-elements unsupported
  • Layout: vertical margin collapsing is contained — adjacent siblings, and a parent with its first / last in-flow block child through an open edge, collapse correctly (empty blocks self-collapse too), but a collapsed child margin never propagates out to become the parent's own outer margin, and clearance isn't modelled; grid has no grid-auto-flow: dense packing, named grid lines, or subgrid; tables support border-collapse: collapse (shared borders, pixel-exact for uniform widths — full width/style conflict resolution and border-spacing for the separate model are approximated / not modelled) but no nested-table promotion; position: sticky is vertical + page-level only (not inside nested scroll containers)
  • Visual: transform covers 2D (translate / rotate / scale), skew / matrix(), and 3D functions flattened to 2D (rotateX / rotateY foreshorten by cos θ, translate3d / scale3d use x,y, matrix3d uses its affine slice) — but no true 3D perspective / z-sorting (Canvas2D can't project), and transform-origin is fixed at the box centre. transition doesn't cover geometric properties (width / height / offsets) or transform: translate (those need per-frame relayout), and doesn't interpolate skew / matrix. CSS @keyframes animation interpolates translate (px + %), rotate / scale, opacity and colours (background / text), with animation-delay, animation-direction (normal / reverse / alternate) and timing functions — but not geometric box properties, animation-fill-mode, or comma-separated multi-animation lists. No clip-path. On rounded boxes the 3D border styles (groove / ridge / inset / outset) render as a solid stroke; backdrop-filter on moving (fixed / sticky) elements applies blur only (colour functions are skipped there to hold 60fps) and its backdrop excludes lower fixed / modal / scroll-container layers

WebGL 1 & 2 (~88%)

Bridge-backed, running straight on the Switch's Tegra X1 GPU — not a software reimplementation. WebGL 1 sits ~92% (the safest target), WebGL 2 ~85% and under active conformance hardening. Remaining gaps are exhaustive extension coverage and layered / 3D-texture sampling (GPU-driver-limited). Full extension lists and proof points: Graphics.

Audio & Video (~80%)

Bridge-backed: Web Audio on a hardware-backed graph (~70%), <audio> / <video> decode in software via FFmpeg (~85%). Remaining gaps are the Web Audio effect nodes (filter / convolver / delay / compressor), subtitle tracks, and hardware video decode. Full node list and codec matrix: Audio & Media.

Summary

AreaCompleteBiggest missing pieces
DOM~84%children elements-only, outerHTML setter, document/window capture listeners, dialog focus trap
HTML~80%spec parser (insertion modes / <template>), multipart form uploads, advanced SVG (SMIL animation / filter-graph primitives), iframe sandbox enforcement
CSS~84%3D-perspective transforms + transform-origin, geometric transitions / keyframes, clip-path, @supports / @layer
WebGL 1~92%exhaustive extension coverage
WebGL 2~85%layered / 3D-texture sampling (GPU-driver-limited), full conformance hardening
Audio & Video~80%Web Audio effect nodes (filter / convolver / delay / compressor), subtitle tracks, hardware video decode

Last updated for Brewser v0.1.116, September 2026. Percentages are honest estimates of real-world surface coverage, not spec-section counts.

On this page