# Work on the frontend reconstruction

> frontend/ is a Vite design workspace; packaged UI stays the patched shipped renderer unless GROK_BOT_RENDERER_SOURCE overrides it.

- Repository: sashimikun/grok-bot-0.18-reconstructed
- GitHub: https://github.com/sashimikun/grok-bot-0.18-reconstructed
- Human docs: https://grok-wiki.com/public/docs/sashimikun-grok-bot-0-18-reconstructed-c774cc9a5c15
- Complete Markdown: https://grok-wiki.com/public/docs/sashimikun-grok-bot-0-18-reconstructed-c774cc9a5c15/llms-full.txt

## Source Files

- `frontend/README.md`
- `frontend/vite.config.ts`
- `frontend/src/recovered/features/settings/overlay/router.ts`
- `frontend/src/recovered/features/settings/overlay/view.tsx`
- `scripts/recover-frontend.mjs`
- `scripts/lib/router-renderer-patch.mjs`

---

---
title: "Work on the frontend reconstruction"
description: "frontend/ is a Vite design workspace; packaged UI stays the patched shipped renderer unless GROK_BOT_RENDERER_SOURCE overrides it."
---

`frontend/` is a Vite 8.2.1 React/TypeScript workspace. `npm run package` does **not** ship that tree. The default macOS app keeps the checksum-pinned 0.18.0 renderer from hydrated `src/app/dist/renderer`, then applies an exact-once Settings Router extension. Set `GROK_BOT_RENDERER_SOURCE` only when you intentionally replace staged `dist/renderer` before that patch.

<Warning>
`frontend/README.md` says the Vite renderer is selected by the default macOS package. `scripts/package-macos.mjs` and `scripts/build.mjs` do the opposite: they call `buildFidelityReconstructedAsar()` and log `Renderer mode: checksum-pinned upstream 0.18.0 payload`.
</Warning>

## Two UIs, one repo

| Surface | Path | What it is | What ships |
| --- | --- | --- | --- |
| Vite workspace | `frontend/` | Readable reconstruction, typecheck, `frontend:build` | Nothing, unless you override |
| Hydrated shipped renderer | `src/app/dist/renderer` (gitignored) | Exact 0.18.0 payload from `npm run bootstrap` | Default packaged UI, after the Router patch |
| Expanded inspection copy | `recovered/frontend/` (gitignored) | `npm run frontend:recover` unminifies JS/CSS | Never packaged |
| Clean-source renderer builder | `scripts/renderer-production-build.mjs` | Separate Vite production graph rooted at `frontend/src/main.tsx` | Only when renderer mode is `clean-source`, not the default package |

```mermaid
flowchart TB
  subgraph workspace["frontend/ workspace"]
    SRC["frontend/src/main.tsx"]
    VITE["vite.config.ts base ./"]
    SHELL[".build/frontend-shell"]
    SRC --> VITE --> SHELL
  end
  subgraph hydrate["bootstrap hydration"]
    ASAR["pinned app.asar"]
    DIST["src/app/dist/renderer"]
    ASAR --> DIST
  end
  subgraph package["npm run package"]
    STAGE["staged dist/renderer"]
    PATCH["applyOriginalRendererRouterPatch"]
    EXT["dist/renderer-router-extension.json"]
    APP["Grok Bot 0.18 Reconstructed.app"]
    STAGE --> PATCH --> EXT --> APP
  end
  DIST --> STAGE
  ENV["GROK_BOT_RENDERER_SOURCE"] -.->|"replaces staged renderer; must still contain original Settings anchors"| STAGE
```

Default package composition for the renderer is `checksum-pinned-artifact-runtime` (`fidelityRuntimeComposition`). Overlay of compiled `source/` runtimes does **not** replace `dist/renderer` in that mode.

## Prerequisites

- `npm ci` and a Node `>=26.5.0 <27` toolchain.
- `npm run bootstrap` so `src/app/dist/renderer/index.html` exists. The Vite server plugin reads that file at startup. `frontend:recover` copies the same tree.
- Do not commit `.build/`, `src/app/dist/`, `recovered/`, or `dist/`.

## Commands

There is no `frontend:dev` script. Use the root scripts and Vite directly.

<CodeGroup>

```sh title="Typecheck and Vite build"
npm run typecheck
npm run frontend:build
```

```sh title="Vite dev server"
npx vite --config frontend/vite.config.ts
```

```sh title="Expand the shipped renderer for inspection"
npm run frontend:recover
```

```sh title="Package the default patched shipped UI"
npm run package
```

```sh title="Package a replacement renderer directory"
GROK_BOT_RENDERER_SOURCE=.build/frontend-shell npm run package
```

</CodeGroup>

| Command | Behavior |
| --- | --- |
| `npm run typecheck` | `tsc --project frontend/tsconfig.json` (`noEmit`, `strict`, `jsx: react-jsx`) |
| `npm run frontend:build` | `vite build --config frontend/vite.config.ts` → `.build/frontend-shell` with `base: "./"` and `sourcemap: true` |
| `npm run frontend:recover` | Unminify JS/CSS from `src/app/dist/renderer` into `recovered/frontend/app` plus reports |
| `npm run check` | Renderer typecheck + `source/` typecheck + `tests/*.test.mjs`. Does **not** run `frontend:build` |
| `npm run package` | `check` then fidelity hybrid ASAR, Router patch, reconstructed identity, ad-hoc sign, verify |

<Note>
`CONTRIBUTING.md` requires `npm run frontend:build` before sharing a change even though `check` does not run it. `vite.config.ts` comments mention `package:recovered-frontend`; that script is not in `package.json`.
</Note>

## Vite workspace layout

:::files
frontend/
  index.html                 # module entry /src/main.tsx, file-relative CSP
  vite.config.ts             # root frontend/, base ./, outDir ../.build/frontend-shell
  tsconfig.json
  manifests/                 # checked-in asset and evidence catalogs
  src/
    main.tsx                 # ProductionRenderer + health POST
    production/              # clean-source production graph
    recovered/               # evidence-backed feature reconstruction
    dev/DevShell.tsx         # inspection overlay (not the current entry)
    upstream.ts              # loads /__reconstructed_manifest + /upstream assets
:::

`frontend/index.html` uses `script-src 'self'` (no Vite HMR eval). `base: "./"` keeps every emitted script, stylesheet, font, and lazy chunk relative to `index.html` so a later copy into Electron `file://` does not need an HTTP origin.

### Dev server endpoints

The Vite plugin `serve-bootstrapped-upstream` binds `127.0.0.1:5173` (`strictPort: false`).

| Method | Path | Behavior |
| --- | --- | --- |
| `GET` | `/__reconstructed_manifest` | JSON `{ entry, styles }` rewritten to `/upstream/...` from the bootstrapped `index.html` |
| `GET` | `/__reconstructed_health` | `200` with last posted JSON, or `503` `{ ready: false }` |
| `POST` | `/__reconstructed_health` | Stores JSON body; `204` on success, `400` on invalid JSON, `405` otherwise |
| static | `/upstream/*` | `sirv` of `src/app/dist/renderer` |
| proxy | `/__sand_control/*` | `http://127.0.0.1:${SAND_DEV_CONTROL_PORT}` (default `62150`) |

<ParamField body="SAND_DEV_CONTROL_PORT" type="string" default="62150">
Loopback port for the Vite `/__sand_control` proxy and Electron `resolveDevControlPort`. Invalid or missing values fall back to `62150`.
</ParamField>

`frontend/src/main.tsx` posts health once after the first animation frame. The payload includes `cleanEntrypoint: "frontend/src/main.tsx"`, `recoveredEntrypoints: 5`, `upstreamEntry: false`, and `viteClient: import.meta.hot != null`. The POST is ignored when the reconstruction host is not running.

`DevShell` and `bootRecoveredRenderer()` exist for overlaying recovered views on the shipped bundle. They are **not** imported from `main.tsx`; the current Vite entry mounts `ProductionRenderer`.

## Recovered feature map

`frontend/src/recovered/runtime/entrypoints.ts` lists five recovered surfaces. `frontend/manifests/renderer-bootstrap.json` requires `expectedFeatureSurfaces: 5` and `expectedShippedRoutes: 11`.

| id | Name | productionChunk | recovery |
| --- | --- | --- | --- |
| `overlay:computer` | Computer | `view-ChG-6rmU.js` | `exact-placeholder` (view returns `null`) |
| `overlay:hidden-chats` | Hidden Chats | `view-Cbx1-ckK.js` | `semantic-model` |
| `view:org-chart` | Org Chart | `view-D0otXpJy.js` | `semantic-model` |
| `overlay:plugins` | Plugins | `view-B5Ug8wEm.js` | `semantic-model` |
| `overlay:settings` | Settings | `view-BRftG-LF.js` | `named-upstream-module` |

The default export of `frontend/src/recovered/features/settings/overlay/view.tsx` is `SettingsOverlaySourceBoundary`, which returns `null`. The reconstructed Settings UI lives in `SettingsModalShell` plus `desktop-surface.tsx` / `panels.tsx`. Comments starting with `@evidence` name byte or symbol anchors in the bootstrapped renderer; they are provenance notes, not imports.

### Settings reconstruction (workspace)

`SETTINGS_SECTIONS`: `general`, `router`, `usage`, `beta`. `settingsSectionsForUsage` drops `usage` when `showUsage` is false.

Router provider ids in `frontend/src/recovered/features/settings/overlay/router.ts`:

| id | label | usageSource |
| --- | --- | --- |
| `cursor` | Cursor | `cursor` |
| `claude-code` | Claude Code | `external` |
| `codex` | Codex | `external` |
| `openrouter` | OpenRouter | `external` |

<ParamField body="settings.router-provider.v1" type="string">
Workspace persistence key used by `loadRouterProvider` / `saveRouterProvider` through `bridge.agent.clientPersistence`. Payload is `{ schemaVersion: 1, provider }`. Invalid JSON or unknown ids fall back to `cursor`.
</ParamField>

Unknown ids throw `Unknown router provider.` on save. This client-persistence key is **not** what the packaged Settings Router uses.

## What `npm run package` actually injects

`scripts/lib/router-renderer-patch.mjs` edits the staged shipped chunks in place.

1. Find exactly one JS file containing the original `wDn` Settings registry (`general`, `usage`, `beta`) and insert `{id:"router",label:"Router",icon:"git-branch"}`.
2. Find exactly one JS file containing `function Sa(s){` plus the `general` and `usage` panel switches. Insert `RRouterPanel`, `RBoxRuntime`, `RRouterUsage`, and related helpers, then route `x==="router"` and replace the usage panel with `RRouterUsage`.
3. Write `dist/renderer-router-extension.json` (`schemaVersion: 1`, `mode: "original-renderer-settings-extension"`).

Injected UI talks to `window.desktop.agent.getInferenceRouter` / `setInferenceRouter`, `getBoxRuntime` / `setBoxRuntime`, and `window.desktop.secrets.list` / `upsert`. Provider values are `cursor`, `claude-code`, `codex`, `openrouter`. Features recorded in provenance: `settings-router-provider`, `settings-local-docker-vm`, `usage-current-provider`.

Missing or duplicate anchors throw `Original renderer <label> anchor is missing or ambiguous.` or `Expected one original Settings registry and panel chunk, found …`. `npm run verify` rejects packaged renderer `.map` files.

<Warning>
The workspace Settings surface writes `settings.router-provider.v1`. The packaged patch does not. Tests in `tests/publication-packaging.test.mjs` assert the patch source does **not** contain `settings.router-provider.v1`. Changing recovered `router.ts` does not change the packaged Settings Router until you change `router-renderer-patch.mjs` or ship a full renderer override that still carries the original anchors.
</Warning>

## Override the packaged renderer

<ParamField body="GROK_BOT_RENDERER_SOURCE" type="string">
Path resolved from the repository root. `scripts/lib/build-asar.mjs` requires `<path>/index.html`, deletes staged `dist/renderer`, and copies the directory. Logs `Renderer override: <abs path>`.
</ParamField>

Fidelity packaging still runs `applyOriginalRendererRouterPatch` after the copy. A Vite `frontend:build` output is therefore not a drop-in replacement unless it still contains the exact `wDn` registry and `function Sa(s){` panel anchors. The Vite build also emits source maps; `npm run verify` fails if any `dist/renderer/**/*.map` remains.

`npm run package:diagnostic` is a separate fidelity diagnostic app. It still uses the checksum-pinned renderer path, not the Vite workspace.

The unused-by-default clean-source builder (`buildProductionRenderer`) is a different Vite invocation: `configFile: false`, `sourcemap: false`, minify on, banner `"Deterministic clean-source renderer: frontend/src/main.tsx";`, and a required lazy-entry list from `renderer-bootstrap.json`. Default `npm run package` does not call it.

## Expand shipped chunks for inspection

`npm run frontend:recover` (`scripts/recover-frontend.mjs`):

1. Deletes and recreates `recovered/frontend/app` and `recovered/frontend/reports`.
2. Walks `src/app/dist/renderer`. JS/CSS go through esbuild (`minify: false`, `treeShaking: false`, external `.map`). Other files copy byte-for-byte.
3. Writes `reports/manifest.json` (per-file SHA-256 of **source** bytes), `imports.tsv`, `candidate-ui-strings.txt`, and `react-component-candidates.tsv` from `assets/index-UbX-y3il.js`.
4. Logs `Recovered <n> JavaScript/CSS assets out of <m> renderer files.`

The recovered tree is gitignored. Publication tests require `frontend/src/recovered/**` to stay addable and `/recovered/` to stay ignored.

## Evidence rule

The immutable 0.18.0 renderer is the product specification. Recovered UI may only express behavior with an inspectable artifact anchor. Do not invent screens, routes, labels, or interactions to fill gaps. Incomplete evidence stays unmapped (`return null` placeholders such as Computer overlay and `SettingsOverlaySourceBoundary`). Passing `typecheck` / `frontend:build` is not provenance.

Checked-in catalogs under `frontend/manifests/` (`renderer-bootstrap.json`, `renderer-runtime-assets.json`, `ui-evidence-anchors.json`, and related locks) are the small files the auditors and verify path consume. Do not rewrite them to match a speculative UI.

## Edit loop

<Steps>
<Step title="Hydrate the shipped renderer">
Run `npm run bootstrap` so `src/app/dist/renderer` exists. Vite and `frontend:recover` both fail without it.
</Step>
<Step title="Change recovered TypeScript, not generated payloads">
Edit `frontend/src/recovered/` or `frontend/src/production/`. Keep `@evidence` comments accurate. Do not check in `recovered/frontend/` or `src/app/dist`.
</Step>
<Step title="Typecheck and build the workspace">
Run `npm run typecheck` and `npm run frontend:build`. Confirm `.build/frontend-shell/index.html` uses relative `./assets/` URLs.
</Step>
<Step title="Decide which UI you are changing">
Workspace-only: stop here. Packaged Settings Router / local Docker toggle: edit `scripts/lib/router-renderer-patch.mjs` and keep the exact anchors. Full replacement UI: set `GROK_BOT_RENDERER_SOURCE` and accept that the Router patch and `verify` source-map rule still run.
</Step>
<Step title="Package and verify on macOS">
Run `npm run package` then `npm run verify`. Expected default renderer mode remains `checksum-pinned-artifact-runtime` with `dist/renderer-router-extension.json` present.
</Step>
</Steps>

## Failure modes

| Symptom | Cause | Fix |
| --- | --- | --- |
| Vite start throws `Bootstrapped renderer index.html has no module entry` | Missing or unexpected `src/app/dist/renderer/index.html` | `npm run bootstrap` |
| `frontend:recover` cannot read `index-UbX-y3il.js` | Hydration incomplete or renderer identity drifted | Re-bootstrap; do not invent a new main chunk name |
| Package: `Original renderer … anchor is missing or ambiguous` | Staged renderer is not the 0.18.0 Settings chunks, or `GROK_BOT_RENDERER_SOURCE` replaced them | Restore shipped renderer, or keep those exact strings in the override |
| Package: `Expected one original Settings registry and panel chunk` | Zero or multiple matching JS files | Do not split or duplicate the shipped Settings chunks |
| Verify: `Packaged renderer contains source maps` | Override or stage left `.map` files | Strip maps; default Vite `frontend:build` emits them |
| Packaged Router does not follow recovered `router.ts` | Different persistence and injection path | Patch `router-renderer-patch.mjs` or use a full override that still patches |

## Next

<CardGroup>
<Card title="Reconstruction boundary" href="/reconstruction-boundary">
Compiled `source/` runtimes, checksum-pinned renderer, reconstructed bundle id, ignored `src/app/dist`.
</Card>
<Card title="Package the macOS app" href="/package-macos-app">
`npm run package` compiles runtimes, patches Settings Router, replaces `app.asar`, signs, verifies.
</Card>
<Card title="Evidence and provenance" href="/evidence-and-provenance">
Pinned 0.18.0 identities and the evidence-only UI rule.
</Card>
<Card title="Environment variables" href="/environment-variables">
`GROK_BOT_RENDERER_SOURCE`, `SAND_DEV_CONTROL_PORT`, and related overrides.
</Card>
<Card title="Packaging failures" href="/packaging-failures">
Missing renderer patch anchors, codesign retry, verify ASAR entries.
</Card>
<Card title="npm scripts" href="/npm-scripts">
Exact `package.json` commands including `frontend:build` and `frontend:recover`.
</Card>
</CardGroup>
