Browser Core
Tech Preview45/45 testsRequest early access →
Realtime document runtime

Not another PDF editor.A browser-native runtime engine.

Local-first. Realtime. Deterministic. The document engine that renders, edits and replays entirely in the browser.

Conceptual runtime visualization
Edit operationMove text spanPage 412.42:18.102applied

Contract Agreement

Text LayerAnnotationsVector ObjectsRaster LayerTilesBase Raster
Command stream (live)Live
12.42.18.095setTextStyleid:3921
12.42.18.096moveTextSpanid:3921
12.42.18.097invalidateRegionpage:4
12.42.18.098buildRenderGraphnodes:1842
12.42.18.099generateTilesdirty:8
12.42.18.100drawTextRunruns:584
12.42.18.101compositeFrametime:16.7ms
Resolver trace

Pointer (1024, 768)

1Text Span (id:3921)score: 0.98
2Annotation (id:221)score: 0.32
3Image (id:88)score: 0.11
Owner: Text Span (id:3921)
No backend roundtrip

Local-first by design

Textless tile rendering

No white-mask hacks

Deterministic replay

Every operation tracked

GPU ready

WebGL → WebGPU roadmap

Production verified

45/45 tests passing

Runtime pipeline

The browser runtime, end to end

Every edit flows through a deterministic, local-first pipeline.
Zero roundtrips for preview. Full fidelity. Realtime.

01PDF bytesActive source bytes enter local runtime.Source

Active PDF bytes enter the browser runtime as the source of truth.

What this solves

Feeds PDFium, workers and textless rendering from the same byte source.

Restored documents can rehydrate bytes from backend export into local cache.

Technical details

Active PDF bytes helper returns memory-hit / indexeddb-hit / indexeddb-miss

Restored documents can hydrate bytes from backend export into browser cache

Worker requests receive a transferable ArrayBuffer copy

Debug exposes pdfBytesAvailable and pdfByteLength

02IndexedDB cacheLocal stores keep sessions warm.Persistence

Document bytes, session metadata, rasters, textless tiles and operation logs persist locally.

What this solves

Refresh can restore page raster and operation replay without waiting for backend preview.

Cache misses are visible instead of silently degrading the runtime.

Technical details

Document/session metadata opens during browser core bootstrap

pageRasterBitmaps persists PNG Blob page rasters for refresh restore

textlessTileBitmaps persists dirty tile PNG Blobs

documentOperationLogs stores replayable local edits

03PDFium WASMWASM rasterizes pages in browser.Renderer

PDFium renders page rasters in-browser through the provider pipeline.

What this solves

Moves page raster production into the browser runtime.

Keeps Python core and preview-image as explicit fallbacks.

Technical details

WASM asset served locally from /vendor/pdfium/pdfium.wasm

Renderer URL can be npm:pdfium using @embedpdf/pdfium

Lifecycle states: disabled, missing-url, loading, loaded, load-failed

PdfPageRasterRenderer.renderPageRaster(input) is the binding boundary

04Text indexWorker maps chars and objects.Index

Worker opens PDFium page/textPage and builds char and text object indexes.

What this solves

Textless tiles can match dirty rects to actual PDF text objects.

Warm page/text cache avoids rescanning the same page on later tiles.

Technical details

Progress waits for PDFium runtime, document, page and text page readiness

Char index and text object index are counted in toolbar status

Worker keeps PDFium document/page/textPage session warm per PDF fingerprint and page

Provider debug reports matched chars and matched text objects

05Render graphDirty nodes compile into buffers.Structure

Operations compile into dirty nodes, dirty regions and command buffers.

What this solves

React sends commands; Browser Core decides what invalidates and redraws.

Debug snapshots expose dirty/final buffers instead of hiding render state.

Technical details

Render graph forms dirty nodes and dirty regions from setTextStyle/moveLayer ops

Dirty command buffer is separate from graph command buffer

Final composite command buffer is the production draw path

Frame Debug exports status, operation log, render graph and command buffers

06Textless tileClean tiles remove source text.Raster

Worker renders dirty tiles without original PDF text using the provider fallback policy.

What this solves

Removes original PDF text without white-mask overlays.

Fallback reasons and quality metadata stay visible in debug.

Technical details

Worker request type is render:textless-tile

Fallback policy: pdfium-wasm -> pdf-layer -> synthetic-background

PDFium toggles matched text objects inactive before rasterizing the tile

Quality metadata includes provider, method, attempts, timings and matched char count

07Final compositeLayers merge into final preview.Composite

Production preview composites base raster tiles and replacement text into the final frame.

What this solves

Successful preview path no longer depends on drawRect masking.

Operation replay rebuilds the same final composite after refresh.

Technical details

Final composite uses drawBaseRasterTile and drawTextRun

drawSelection stays out of production composite

drawRect remains graph/dirty debug only, not final output

Replay rebuilds render graph, pending textless tile requests and final composite

PDF bytes

Source

Active PDF bytes enter the browser runtime as the source of truth.

What this solves

Feeds PDFium, workers and textless rendering from the same byte source.

Restored documents can rehydrate bytes from backend export into local cache.

PDF bytesIndexedDB session cachePDFium WASM rasterText page indexRender graphTextless tile workerFinal composite

Technical details

Active PDF bytes helper returns memory-hit / indexeddb-hit / indexeddb-miss
Restored documents can hydrate bytes from backend export into browser cache
Worker requests receive a transferable ArrayBuffer copy
Debug exposes pdfBytesAvailable and pdfByteLength
Same bytes feed page raster and textless tile providers
PDF bytes status is included in tileCacheStatus snapshots
type ActivePdfBytesResult = {
  status: 'memory-hit' | 'indexeddb-hit' | 'indexeddb-miss';
  pdfBytes?: ArrayBuffer;
  byteLength?: number;
}

IndexedDB session cache

Persistence

Document bytes, session metadata, rasters, textless tiles and operation logs persist locally.

What this solves

Refresh can restore page raster and operation replay without waiting for backend preview.

Cache misses are visible instead of silently degrading the runtime.

PDF bytesIndexedDB session cachePDFium WASM rasterText page indexRender graphTextless tile workerFinal composite

Technical details

Document/session metadata opens during browser core bootstrap
pageRasterBitmaps persists PNG Blob page rasters for refresh restore
textlessTileBitmaps persists dirty tile PNG Blobs
documentOperationLogs stores replayable local edits
Cache-hit restores bitmap into memory without re-synthesis
DB schema versions are explicit for raster and textless stores
IndexedDB stores:
  documentSessions
  pageRasterBitmaps
  textlessTileBitmaps
  documentOperationLogs

PDFium WASM raster

Renderer

PDFium renders page rasters in-browser through the provider pipeline.

What this solves

Moves page raster production into the browser runtime.

Keeps Python core and preview-image as explicit fallbacks.

PDF bytesIndexedDB session cachePDFium WASM rasterText page indexRender graphTextless tile workerFinal composite

Technical details

WASM asset served locally from /vendor/pdfium/pdfium.wasm
Renderer URL can be npm:pdfium using @embedpdf/pdfium
Lifecycle states: disabled, missing-url, loading, loaded, load-failed
PdfPageRasterRenderer.renderPageRaster(input) is the binding boundary
Provider order: memory, indexeddb, pdfium-wasm, python-core, worker, preview-image
Provider attempts record provider:status:durationMs:reason
resolvePageRaster(input)
  -> memory
  -> indexeddb
  -> pdfium-wasm
  -> python-core
  -> worker
  -> preview-image

Text page index

Index

Worker opens PDFium page/textPage and builds char and text object indexes.

What this solves

Textless tiles can match dirty rects to actual PDF text objects.

Warm page/text cache avoids rescanning the same page on later tiles.

PDF bytesIndexedDB session cachePDFium WASM rasterText page indexRender graphTextless tile workerFinal composite

Technical details

Progress waits for PDFium runtime, document, page and text page readiness
Char index and text object index are counted in toolbar status
Worker keeps PDFium document/page/textPage session warm per PDF fingerprint and page
Provider debug reports matched chars and matched text objects
Cache hit avoids reopening PDF and rescanning all character boxes
Readiness fields include Text layer chars, objects, cache and error
PDFium text layer readiness:
  runtime loaded
  document opened
  page loaded
  text page loaded
  char index built
  text object index counted

Render graph

Structure

Operations compile into dirty nodes, dirty regions and command buffers.

What this solves

React sends commands; Browser Core decides what invalidates and redraws.

Debug snapshots expose dirty/final buffers instead of hiding render state.

PDF bytesIndexedDB session cachePDFium WASM rasterText page indexRender graphTextless tile workerFinal composite

Technical details

Render graph forms dirty nodes and dirty regions from setTextStyle/moveLayer ops
Dirty command buffer is separate from graph command buffer
Final composite command buffer is the production draw path
Frame Debug exports status, operation log, render graph and command buffers
Debug rows include dirty nodes, dirty regions, final composite and layer viewer
React stays command layer only; Browser Core owns invalidation
Render Graph
  -> Render Nodes
  -> Render Commands
  -> Command Buffer
  -> Canvas/WebGL/WebGPU Surface

Textless tile worker

Raster

Worker renders dirty tiles without original PDF text using the provider fallback policy.

What this solves

Removes original PDF text without white-mask overlays.

Fallback reasons and quality metadata stay visible in debug.

PDF bytesIndexedDB session cachePDFium WASM rasterText page indexRender graphTextless tile workerFinal composite

Technical details

Worker request type is render:textless-tile
Fallback policy: pdfium-wasm -> pdf-layer -> synthetic-background
PDFium toggles matched text objects inactive before rasterizing the tile
Quality metadata includes provider, method, attempts, timings and matched char count
Successful PDFium tile reports placeholder:false and synthetic:false
Attempt debug includes load, cache, match, toggle, render, encode and total timings
type BrowserCoreWorkerRequest =
  | { type: 'render:textless-tile';
      tileId: string;
      rect: RenderRect;
    }

Final composite

Composite

Production preview composites base raster tiles and replacement text into the final frame.

What this solves

Successful preview path no longer depends on drawRect masking.

Operation replay rebuilds the same final composite after refresh.

PDF bytesIndexedDB session cachePDFium WASM rasterText page indexRender graphTextless tile workerFinal composite

Technical details

Final composite uses drawBaseRasterTile and drawTextRun
drawSelection stays out of production composite
drawRect remains graph/dirty debug only, not final output
Replay rebuilds render graph, pending textless tile requests and final composite
Save Span / Save changes marks local operations committed
Committed ops are removed from future replay after save
finalCompositeBuffer = [
  drawBaseRasterTile(tileBitmap),
  drawTextRun(replacementSpan)
];
Local-first by design

No backend roundtrips for preview or edits.

Deterministic pipeline

Same inputs, same outputs. Every time.

Realtime performance

60 FPS target with predictable frame times.

Textless rendering

Source-level text suppression for perfect selection.

Replayable operations

Every edit is logged and replayable.

Private & offline

Your documents never leave your device.

No backend roundtrip for every edit

The local runtime previews text style and move operations before authoritative save/export.

No white-mask replacement story

The core is moving toward real textless tile composition with PDFium WASM and provider fallbacks.

State is replayable

Operation replay, compaction and committed state make the preview feel recoverable instead of temporary.

Deep tech. Built different.

Purpose-built runtime technology, not legacy editor layers. Engineered for performance, determinism and full control in the browser.

Render graph

Core runtime

Layer and node based rendering with deterministic dirty invalidations.

Textless tiles

Rendering

PDFium-powered source suppression instead of error-prone overlay hacks.

Operation replay

Reliability

Local edits can survive refresh and compact into committed state.

Interaction runtime

Performance

Layer focus, spatial index, ownership and worker resolve path.

GPU-first target

Acceleration

Canvas now, WebGL compositor next, WebGPU-ready structure.

SDK potential

Platform

A possible runtime layer for document SaaS, legal tools and e-signature products.

Local-first by design

Preview locally. Commit authoritatively.

Edits visible before backend save
IndexedDB document/session cache
Deterministic operation log
Refresh recovery and replay
Hybrid local + backend export
Honest early-access positioning

Operation replay

Replayed ops128
Committed ops94
Pending ops34

Proof panel

We build in the open. No hidden magic. Make it the credibility layer.

View test results
45/45browser-core tests passing
3/3production move E2E verified
3/3production edit E2E verified
PDFiumWASM parser and textless provider activeActive
Replaydeterministic operation replay and compactionEnabled
Early accessWebGL/WebGPU compositor still roadmapRoadmap

Honest roadmap

Make the unfinished parts visible. That is stronger than pretending this is a finished generic SaaS.

01
Operation Inspector

Show operation log, compacted ops, committed ops and replay source in a dedicated view.

02
Tile latency tuning

Measure warm-cache PDFium textless rendering and optimize matching / encode path.

03
WebGL compositor

Move final composite toward GPU layer pipeline and texture cache.

04
Font atlas / SDF

Better text rendering path for speed, clarity and consistent previews.

05
Export equivalence

Compare optimistic preview against final authoritative PDF export.

Built for teams building the future of documents

SaaS platforms

Embed low-latency PDF interaction into web products.

Legal tech

Contract editing, review and annotation workflows.

eSignature

Faster flows with realtime visual feedback.

Automation

Document transformations with deterministic operations.

Developers

Potential SDK/runtime layer for custom tools.

Show the engine before it is “finished”.

Position it honestly as an early technology preview and collect serious interest from people who understand document runtimes.