Skip to content

feat(playground): run the engine in the browser, on a public repo - #13

Merged
maxgfr merged 1 commit into
mainfrom
feat/browser-playground
Aug 1, 2026
Merged

feat(playground): run the engine in the browser, on a public repo#13
maxgfr merged 1 commit into
mainfrom
feat/browser-playground

Conversation

@maxgfr

@maxgfr maxgfr commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Adds site/playground/: paste a public GitHub repository and index it entirely client-side — the same walk, the same tree-sitter grammars, the same link-graph, compiled for the browser and run in a Web Worker.

The engine source is untouched

Node builtins are redirected at resolution time to shims in src/browser/ (an in-memory VFS, a synchronous SHA-1, a Buffer covering readText's four decode paths). Everything spawn-based degrades along fallbacks the engine already ships and already tests: sh() reports its binary missing, so git.ts returns no commit and grep.ts uses its pure-JS backend.

scripts/engine.mjs, engine.d.mts and cli.mjs are byte-identical to before.

Walk decides what is downloaded

A file list carries paths and sizes, and sizes alone satisfy lstatSync — so the tree is mounted with no contents, the real walk() runs on it, and its keep-list is the download list. No ignore rule, size cap or capped flag is reimplemented in the UI. pruneUnfetched() drops whatever was listed but never fetched, so a file can never reach the index as a phantom empty one.

Source ordering is measured, not assumed

jsDelivr's branch manifest is a snapshot rather than the branch head. On t3-oss/create-t3-turbo it listed 125 files of which 37 no longer existed (404 on raw too, so genuinely deleted). The GitHub trees API listed 141 blobs and all 141 fetched. So GitHub is primary, jsDelivr is the fallback for when the 60/hour API limit runs out, and the caveat is shown rather than hidden — 88 → 132 files indexed on that repo.

Verified

repo measured in headless Chrome
gin-gonic/gin@master 129 files, 1 613 symbols, tier AST · go, 185 ms
t3-oss/create-t3-turbo@main 132 files, 183 symbols, tier AST · javascript, tsx, typescript, 48 ms
  • tests/browser-build.test.ts indexes three fixtures through the VFS and asserts graph.json / symbols.json are byte-identical to the Node build — with the grammars asserted loaded, so the comparison cannot pass vacuously.
  • Shim behaviour is checked against the real node: modules; the whole palette runs against a real index; the fetch pipeline has an opt-in live test (CODEINDEX_PLAYGROUND_E2E=1).
  • pnpm test 1 119 passing, typecheck clean, check:build holds the committed bundle byte-reproducible.

Note on the build

Built by scripts/build-browser.mjs rather than a third tsup target: tsup registers its own node-protocol plugin ahead of user plugins and resolves node:fs to an external bare "fs" — which no browser can load, and which Node quietly satisfies from the real disk (a silent failure under test).

Adds site/playground/: paste a public GitHub repository and index it
entirely client-side. Not a mockup and not a precomputed index — the same
walk, the same tree-sitter grammars, the same link-graph, compiled for the
browser and run in a Web Worker.

The engine source is untouched. Node builtins are redirected at resolution
time to shims in src/browser/ (an in-memory VFS, a synchronous SHA-1, a
Buffer covering readText's four decode paths), and everything spawn-based
degrades along the fallbacks the engine already ships and already tests:
sh() reports its binary missing, so git.ts returns no commit and grep.ts
uses its pure-JS backend. scripts/engine.mjs, engine.d.mts and cli.mjs are
byte-identical to before.

WALK DECIDES WHAT IS DOWNLOADED. A file list carries paths and sizes, and
sizes alone satisfy lstatSync — so the tree is mounted with no contents,
the real walk() runs on it, and its keep-list IS the download list. No
ignore rule, size cap or `capped` flag is reimplemented in the UI, and
pruneUnfetched() drops whatever was listed but never fetched so a file can
never reach the index as a phantom empty one.

Source ordering is measured, not assumed. jsDelivr's branch manifest is a
snapshot rather than the branch head: on t3-oss/create-t3-turbo it listed
125 files of which 37 no longer existed (404 on raw too, so genuinely
deleted). The GitHub trees API listed 141 blobs and all 141 fetched. So
GitHub is primary and jsDelivr is the fallback for when the 60/hour API
limit runs out, with the caveat shown rather than hidden — 88 -> 132 files
indexed on that repo.

The palette exposes the 24 commands that mean something here and lists the
seven that do not with their reason, because a command that needs git
history returning an empty result reads like a bug.

Built by scripts/build-browser.mjs rather than a third tsup target: tsup
registers its own node-protocol plugin ahead of user plugins and resolves
node:fs to an external bare "fs", which no browser can load and which Node
quietly satisfies from the real disk — a silent failure under test.

Verified: tests/browser-build.test.ts indexes three fixtures through the
VFS and asserts graph.json and symbols.json are byte-identical to the Node
build, with the grammars asserted loaded so the comparison cannot pass
vacuously. Shim behaviour is checked against the real node: modules,
the whole palette runs against a real index, and the fetch pipeline has an
opt-in live test (CODEINDEX_PLAYGROUND_E2E=1). check:build holds the
committed bundle byte-reproducible.
@maxgfr
maxgfr merged commit 6cd2dec into main Aug 1, 2026
1 check passed
@maxgfr
maxgfr deleted the feat/browser-playground branch August 1, 2026 08:06
github-actions Bot pushed a commit that referenced this pull request Aug 1, 2026
# [2.23.0](v2.22.1...v2.23.0) (2026-08-01)

### Features

* **playground:** run the engine in the browser, on a public repo ([#13](#13)) ([6cd2dec](6cd2dec))
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.23.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant