Time for the app: apps/web, a second Worker that renders pages with Remix 3 and talks to the agent through a service binding. The browser only ever talks to the web app; the web app talks to the agent, Worker to Worker, with no public internet in between.
Verified remix 3.1.0wrangler 4.157.0typescript 5.9.3
Start from d-04 on GitHub. Starting here, or behind? Get the code at that tag:
git clone https://github.com/ryanyogan/klippy cd klippy git checkout d-04
1. The prompt
Fresh session, plan mode first (claude --permission-mode plan):
Goal: add apps/web, a Remix 3 app on Workers that renders a home page and calls the agent through a service binding, so the browser never talks to the agent directly. Use the remix skill: read node_modules/remix/INDEX.md, then guides 02, 03 (the Workers entry) and 04 first. Use the cloudflare skill for service bindings and static assets. Constraints: - Only apps/web/** and the root package.json. remix 3.1.0, wrangler 4.157.0, typescript 5.9.3, exact versions. - No remix/assets asset server (it needs Node). Static files from Workers Static Assets in apps/web/public. - Binding AGENT → service "klippy". The home page shows the agent's reply to GET /. - Styles: one stylesheet, public/styles.css, from the tokens in docs/ui-brief.md. No CSS framework, no React. Plan first: list the files and steps, then wait for my go-ahead. Done when pnpm typecheck and remix doctor pass, and with `pnpm dev:web` running, curl localhost:8802 shows the agent's words. Report the files, both command outputs and the curl output.
The goal names the security reason: no browser-to-agent traffic.
Skills and named guides: Remix 3 is newer than the model's memory.
"No remix/assets asset server" saves a detour.
remix newmakes a Node app whose asset server reads files from disk at request time, which a Worker can't. We ran it in a scratch folder to copy its layout (app/routes.ts,app/router.ts,app/actions/), and left the Node parts out.Plan first: this step touches about ten files.
2. What to expect: the parts worth reading
About eight files under apps/web, a stylesheet, and a dev:web script in the root package.json. Our plan had one change: the agent wanted to run remix new in place; we kept its layout, not its Node files.
The binding is two lines of config:
And it's called like fetch:
env comes from cloudflare:workers, so no plumbing is needed to reach a binding. The Worker entry is just router.fetch(request).
3. The one stylesheet
This is the one place in the build-along where a big file arrives whole. It's written from the brief's tokens, with a dark theme, a visible focus ring, 44px targets, reduced motion, and the classes later lessons use (chat, tool card, notes). Read the tokens at the top; skim the rest.
4. Run both Workers
The web app's binding needs the agent running too. pnpm dev:web runs both in one wrangler process (wrangler dev -c wrangler.jsonc -c ../agent/wrangler.jsonc, port 8802): the first config is served, the second makes AGENT resolve.
The agent's words, through the binding. Wrangler prints env.AGENT (klippy) Worker local [not connected] before the second Worker starts; the page proves it connected.
We took the advice ("engines": { "node": ">=24.3.0" }) and it came back 0 warnings, 0 advice. The agent's routes are unchanged: / on the agent is public, /agents/* still needs the token. The next lesson adds it, on the server side of the binding.
5. Review it
No
react,react-dom,@remix-run/reactorreact-routeranywhere (grep -r "react" apps/web/app).tsconfig.jsonhas"jsxImportSource": "remix/component". Routes live inapp/routes.ts, actions inapp/actions/.wrangler.jsonc:AGENT→klippy,assets.directoryispublic, no secrets.Exact versions in
apps/web/package.json: no^, nolatest.Reject:
remix/assetsorcreateAssetServerin the Worker, a CSS framework, inline styles.
Steer prompts for the usual misses:
You imported createAssetServer from remix/assets. It reads files from disk, which a Worker can't. Remove it and serve public/ with Workers Static Assets, as the constraints say.The page says 'React is not defined'. Add jsx: react-jsx and jsxImportSource: remix/component to apps/web/tsconfig.json, then restart wrangler dev (it doesn't watch tsconfig).You copied remix new's dev script (node --watch server.ts). This app runs on Workers: use wrangler dev.Your repo matches tag d-05 (changes from d-04).