From 13c30415b9621e7354e7bf0653401330be72e0e7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 9 Jul 2026 18:01:22 +0000 Subject: [PATCH 1/4] perf: minify production browser bundles --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cb46616..b7dde7a 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,8 @@ "dev:mock-resend": "bun ./wrangler-env.ts dev --local --config mock-servers/resend/wrangler.jsonc", "dev:mock-ai": "bun ./wrangler-env.ts dev --local --config mock-servers/ai/wrangler.jsonc", "deploy": "bun run build && bun ./wrangler-env.ts deploy", - "build:mcp-apps": "esbuild client/mcp-apps/calculator-widget.ts --bundle --format=esm --target=es2022 --outdir=public/mcp-apps --platform=browser", - "build:client:web": "esbuild client/entry.tsx --bundle --format=esm --target=es2022 --outdir=public --entry-names=client-entry --chunk-names=assets/[name] --asset-names=assets/[name] --jsx=automatic --jsx-import-source=#client/remix-ui-compat", + "build:mcp-apps": "esbuild client/mcp-apps/calculator-widget.ts --bundle --format=esm --target=es2022 --outdir=public/mcp-apps --platform=browser --minify", + "build:client:web": "esbuild client/entry.tsx --bundle --format=esm --target=es2022 --outdir=public --entry-names=client-entry --chunk-names=assets/[name] --asset-names=assets/[name] --jsx=automatic --jsx-import-source=#client/remix-ui-compat --minify", "build:client": "bun run build:client:web && bun run build:mcp-apps", "build": "bun run build:client && bun ./wrangler-env.ts build", "lint": "oxlint .", From bb98925a105a0d2ec10672580f383cde099d79a3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 9 Jul 2026 18:01:28 +0000 Subject: [PATCH 2/4] feat: adopt Remix Beta 5 UI entrypoints --- client/entry.tsx | 2 +- client/routes/admin-agents.tsx | 3 +++ client/routes/login.tsx | 2 ++ server/auth-session.ts | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/client/entry.tsx b/client/entry.tsx index 3cd4ede..8302040 100644 --- a/client/entry.tsx +++ b/client/entry.tsx @@ -3,7 +3,7 @@ import { App } from './app.tsx' const rootElement = document.getElementById('root') ?? document.body if (rootElement.childNodes.length > 0) { - // Remix alpha.3 auto-hydrates non-empty containers. We render from scratch. + // Remix UI auto-hydrates non-empty containers. We render from scratch. rootElement.replaceChildren() } createRoot(rootElement).render() diff --git a/client/routes/admin-agents.tsx b/client/routes/admin-agents.tsx index 1b4d8ea..524f61a 100644 --- a/client/routes/admin-agents.tsx +++ b/client/routes/admin-agents.tsx @@ -1,4 +1,5 @@ import { type Handle } from 'remix/ui' +import checkbox from 'remix/ui/checkbox' import { createNotifications } from '#client/notifications.tsx' import { colors, @@ -611,6 +612,7 @@ export function AdminAgentsRoute(handle: Handle) { handleCheckboxInput('isActive', event), }} @@ -624,6 +626,7 @@ export function AdminAgentsRoute(handle: Handle) { handleCheckboxInput('makeDefault', event), diff --git a/client/routes/login.tsx b/client/routes/login.tsx index 61dd24b..9d3927d 100644 --- a/client/routes/login.tsx +++ b/client/routes/login.tsx @@ -1,4 +1,5 @@ import { type Handle } from 'remix/ui' +import checkbox from 'remix/ui/checkbox' import { buildAuthLink } from '#client/auth-links.ts' import { navigate } from '#client/client-router.tsx' import { fetchSessionInfo, type SessionStatus } from '#client/session.ts' @@ -227,6 +228,7 @@ export function LoginRoute(handle: Handle) { Date: Thu, 9 Jul 2026 18:01:34 +0000 Subject: [PATCH 3/4] docs: record Remix Beta 5 adoption audit --- docs/agents/remix/beta-5-adoption-audit.md | 118 +++++++++++++++++++++ docs/agents/remix/index.md | 27 ++--- docs/agents/remix/remix.md | 80 ++++---------- docs/agents/remix/update.md | 15 ++- docs/agents/typescript-setup.md | 3 +- 5 files changed, 160 insertions(+), 83 deletions(-) create mode 100644 docs/agents/remix/beta-5-adoption-audit.md diff --git a/docs/agents/remix/beta-5-adoption-audit.md b/docs/agents/remix/beta-5-adoption-audit.md new file mode 100644 index 0000000..dc35128 --- /dev/null +++ b/docs/agents/remix/beta-5-adoption-audit.md @@ -0,0 +1,118 @@ +# Remix v3 Beta 5 adoption audit + +Audited against `remix@3.0.0-beta.5` and the upstream +[Beta 5 release](https://github.com/remix-run/remix/releases/tag/remix%403.0.0-beta.5). + +## Current state + +- `package.json` pins `remix` to `3.0.0-beta.5`; `bun.lock` resolves the same + version. +- Client runtime imports already use `remix/ui` and `remix/ui/jsx-runtime`. The + compatibility runtime in `client/remix-ui-compat/jsx-runtime.ts` preserves the + existing `css` and `on` JSX props while they are migrated incrementally to + native `mix` composition. +- Server routing already uses `remix/fetch-router`, and the data layer uses the + Beta 5-compatible `remix/data-table` API. + +## Prioritized recommendations + +### High + +1. **Minify production browser bundles — implemented.** `package.json` now + passes `--minify` to the production esbuild commands for both + `client/entry.tsx` and `client/mcp-apps/calculator-widget.ts`. The + development watchers remain unminified. This adopts the relevant production + asset improvement from the Beta 5 `remix new` template without replacing this + app's esbuild and Wrangler pipeline. +2. **Adopt `remix/ui/checkbox` for the existing checkbox controls — + implemented.** `client/routes/login.tsx` and `client/routes/admin-agents.tsx` + now apply the first-party checkbox mixin to all three checkboxes. These + controls have native semantics already, so the change adds consistent focus, + disabled, checked, and mixed-state styling without changing form behavior. +3. **Keep active framework guidance on the Beta 5 entrypoints — implemented.** + The active Remix index and TypeScript setup notes now describe `remix/ui` + rather than the removed `remix/component` entrypoint. The one direct + `@remix-run/cookie` application import in `server/auth-session.ts` now uses + the supported umbrella export, `remix/cookie`. + +### Medium + +1. **Create app-branded button mixins on top of `remix/ui/button`.** Native + buttons repeat similar primary, neutral, ghost, and destructive styles in + `client/routes/chat.tsx`, `client/routes/admin-agents.tsx`, + `client/routes/login.tsx`, `client/routes/oauth-authorize.tsx`, + `client/routes/reset-password.tsx`, `client/app.tsx`, + `client/notifications.tsx`, and `client/editable-text.tsx`. A small app-owned + mixin layer could compose the first-party focus, disabled, and default button + behavior with the tokens in `client/styles/tokens.ts`. Adopting the stock + visual tones directly would replace the pea brand colors, so this needs a + focused visual design pass rather than a mechanical swap. +2. **Adopt `remix/ui/input` in auth and admin forms.** + `client/routes/login.tsx`, `client/routes/reset-password.tsx`, and + `client/routes/admin-agents.tsx` repeat input frame and focus styles. Start + with one complete form and verify focus, autofill, validation, and disabled + states before expanding. +3. **Evaluate `remix/ui/select` for the admin model picker.** + `client/routes/admin-agents.tsx` has the only native select. The first-party + Select would add a consistent popover, keyboard navigation, and typeahead, + but the current disabled visual divider and the untested admin workflow need + explicit coverage before changing behavior. +4. **Centralize canonical-origin resolution.** + `server/handlers/password-reset.ts` prefers `APP_BASE_URL`, while OAuth/MCP + metadata and redirects mostly use `request.url`. If another ingress or + canonical domain is added, use one helper that prefers `APP_BASE_URL` and + otherwise falls back to the native request origin. + +### Low or deferred + +1. **Do not replace `client/agent-multi-select-combobox.tsx` wholesale.** It is + a multi-select with a minimum-one selection rule, search, keyboard + navigation, and chat-specific labels. Beta 5's high-level Combobox and Select + are single-value controls. A future change could adopt only + `remix/ui/popover` and lower-level listbox primitives while retaining the + app-owned multi-select state, but this is not a drop-in simplification. +2. **Retire the JSX compatibility runtime only as a dedicated migration.** + `client/remix-ui-compat/jsx-runtime.ts` supports hundreds of existing + `css`/`on` props. Converting all call sites to native `mix` in this audit + would create a broad, low-signal diff. +3. **Do not add unused primitives.** Accordion, breadcrumbs, menu, radio, tabs, + and toggle have no matching UI in the current app. The calculator MCP app is + server-rendered HTML plus vanilla browser code, so Remix UI primitives do not + apply to it. + +## `trustProxy` + +`trustProxy` is not useful in the current deployment topology. It configures +`createRequest()` and `createRequestListener()` from `remix/node-fetch-server` +when a Node HTTP server is reachable only through a trusted reverse proxy. This +app instead enters through `worker/index.ts` as a Cloudflare Worker and passes +the runtime's native `Request` directly through `server/handler.ts` to +`remix/fetch-router`. + +The Worker-specific handling should remain: + +- `server/audit-log.ts` prefers Cloudflare's `CF-Connecting-IP`. +- `server/auth-session.ts` uses the forwarded protocol only to determine the + cookie's `Secure` attribute. +- `APP_BASE_URL` provides a canonical origin for password-reset links. + +Revisit `trustProxy` only if a Node server using `remix/node-fetch-server` is +added and clients cannot bypass a proxy that overwrites forwarded headers. + +## Beta 5 template comparison + +The default `remix new` template is a Node application using `remix/assets`, +`remix/node-fetch-server`, server/client frame resolution, and a `start` script. +Pea is intentionally different: Wrangler starts the Cloudflare Worker, the +Workers `ASSETS` binding serves static files, and esbuild creates the browser +bundles. + +The template improvements map as follows: + +| Beta 5 template improvement | Pea action | +| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| Production `NODE_ENV=production` | Not needed for the Workers runtime; application code does not branch on `NODE_ENV`. | +| Minified browser assets | Adopted in the production esbuild commands. | +| Client/server `Frame` resolution | Not applicable because pea does not render Remix UI `Frame` components. | +| Dev-server watcher instead of asset-server watcher | Not applicable; `cli.ts` already runs dedicated esbuild watchers with Wrangler. | +| Node production `start` script | Not applicable; `bun run deploy` builds and deploys `worker/index.ts`, and Cloudflare starts Worker isolates. | diff --git a/docs/agents/remix/index.md b/docs/agents/remix/index.md index 6171d6c..d8b6a82 100644 --- a/docs/agents/remix/index.md +++ b/docs/agents/remix/index.md @@ -18,7 +18,8 @@ Docs for every package in https://github.com/remix-run/remix/tree/main/packages. ## Start here -- Building UI with Remix Component: [component](./component/index.md) +- Building UI with Remix UI: [Beta 5 adoption audit](./beta-5-adoption-audit.md) + and the installed `@remix-run/ui` README - Routing and request handling: [fetch-router](./fetch-router/index.md) + [route-pattern](./route-pattern.md) - Sessions and cookies: [session](./session/index.md) + @@ -39,27 +40,22 @@ Docs for every package in https://github.com/remix-run/remix/tree/main/packages. ## pea adoption snapshot - Primary runtime packages in active use: - - `remix/component` + - `remix/ui` - `remix/fetch-router` - `remix/data-schema` - `remix/data-table` - D1 integration uses `remix/data-table` with a repository adapter (`worker/d1-data-table-adapter.ts`) instead of `remix/data-table-sqlite`. -- Package coverage audit against installed `remix@3.0.0-alpha.3` top-level - exports: no missing Remix package docs in this index. +- The installed framework version and relevant Beta 5 adoption opportunities are + recorded in the [Beta 5 adoption audit](./beta-5-adoption-audit.md). ## UI and components -- [component](./component/index.md) - - [Getting started](./component/getting-started.md) - - [Components](./component/components.md) - - [Styling basics](./component/styling-basics.md) - - [Animate basics](./component/animate-basics.md) - - [Testing](./component/testing.md) -- [interaction](./interaction/index.md) - - [Event listeners and interactions](./interaction/listeners.md) - - [Containers and disposal](./interaction/containers-and-disposal.md) - - [Custom interactions and typed targets](./interaction/custom-interactions.md) +- [Beta 5 adoption audit](./beta-5-adoption-audit.md) +- The `remix/ui` runtime and first-party components are documented in the + installed `node_modules/@remix-run/ui/README.md`. +- `component/` and `interaction/` contain historical alpha documentation and are + not current Beta 5 API guidance. ## Routing and requests @@ -144,7 +140,7 @@ Docs for every package in https://github.com/remix-run/remix/tree/main/packages. | Package | Focus | Docs | | -------------------------- | ------------------------------------------ | ------------------------------------------------------------- | | async-context-middleware | AsyncLocalStorage context for fetch-router | [async-context-middleware](./async-context-middleware.md) | -| component | Remix Component UI system | [component](./component/index.md) | +| ui | Runtime and first-party UI components | [Beta 5 audit](./beta-5-adoption-audit.md) | | compression-middleware | Response compression for fetch-router | [compression-middleware](./compression-middleware/index.md) | | cookie | Cookie parsing, signing, and serialization | [cookie](./cookie.md) | | data-schema | Runtime validation and schema parsing | [data-schema](./data-schema.md) | @@ -161,7 +157,6 @@ Docs for every package in https://github.com/remix-run/remix/tree/main/packages. | fs | Lazy file system utilities | [fs](./fs.md) | | headers | Header parsing and helpers | [headers](./headers/index.md) | | html-template | Safe HTML template tag | [html-template](./html-template.md) | -| interaction | Event helpers and interactions | [interaction](./interaction/index.md) | | lazy-file | Streaming File/Blob implementation | [lazy-file](./lazy-file.md) | | logger-middleware | Request/response logging | [logger-middleware](./logger-middleware.md) | | method-override-middleware | HTML form method override | [method-override-middleware](./method-override-middleware.md) | diff --git a/docs/agents/remix/remix.md b/docs/agents/remix/remix.md index 30fc7d9..78c8311 100644 --- a/docs/agents/remix/remix.md +++ b/docs/agents/remix/remix.md @@ -10,72 +10,36 @@ See [remix.run](https://remix.run) for framework docs. ## Installation +This repository pins the Beta 5 release: + ```sh -npm i remix +bun add remix@3.0.0-beta.5 --exact ``` -## Package usage in Remix 3 alpha +## Package usage in Remix 3 Beta 5 The `remix` package is used through subpath imports. - ✅ `import { createRouter } from 'remix/fetch-router'` - ✅ `import { route } from 'remix/fetch-router/routes'` -- ✅ `import { createRoot } from 'remix/component'` -- ❌ `import { ... } from 'remix'` (root import removed in `3.0.0-alpha.3`) - -## Subpath export surface (`3.0.0-alpha.3`) - -Top-level package exports currently include: - -- `remix/async-context-middleware` -- `remix/component` -- `remix/compression-middleware` -- `remix/cookie` -- `remix/data-schema` -- `remix/data-table` -- `remix/fetch-proxy` -- `remix/fetch-router` -- `remix/file-storage` -- `remix/file-storage-s3` -- `remix/form-data-middleware` -- `remix/form-data-parser` -- `remix/fs` -- `remix/headers` -- `remix/html-template` -- `remix/interaction` -- `remix/lazy-file` -- `remix/logger-middleware` -- `remix/method-override-middleware` -- `remix/mime` -- `remix/multipart-parser` -- `remix/node-fetch-server` -- `remix/response` -- `remix/route-pattern` -- `remix/session` -- `remix/session-middleware` -- `remix/session-storage-memcache` -- `remix/session-storage-redis` -- `remix/static-middleware` -- `remix/tar-parser` - -Plus adapter/data helper subpaths and utility subpaths: - -- `remix/data-schema/checks`, `remix/data-schema/coerce`, - `remix/data-schema/lazy` -- `remix/data-table-mysql`, `remix/data-table-postgres`, - `remix/data-table-sqlite` -- `remix/fetch-router/routes` -- `remix/component/jsx-runtime`, `remix/component/jsx-dev-runtime`, - `remix/component/server` -- `remix/interaction/form`, `remix/interaction/keys`, - `remix/interaction/popover`, `remix/interaction/press` -- `remix/response/compress`, `remix/response/file`, `remix/response/html`, - `remix/response/redirect` -- `remix/route-pattern/specificity` -- `remix/session/cookie-storage`, `remix/session/fs-storage`, - `remix/session/memory-storage` -- `remix/file-storage/fs`, `remix/file-storage/memory` -- `remix/multipart-parser/node` +- ✅ `import { createRoot } from 'remix/ui'` +- ✅ `import checkbox from 'remix/ui/checkbox'` +- ❌ `import { ... } from 'remix'` (there is no root API entrypoint) +- ❌ `import { ... } from 'remix/component'` (replaced by `remix/ui`) + +The installed `remix/package.json` is the source of truth for the complete +export list. Entry points used by pea include: + +- UI: `remix/ui`, `remix/ui/jsx-runtime`, and focused `remix/ui/*` component + modules +- Routing: `remix/fetch-router` and `remix/fetch-router/routes` +- Data: `remix/data-schema`, `remix/data-table`, and `remix/data-table/sqlite` +- Responses: `remix/html-template` and `remix/response/html` +- Cookies: `remix/cookie` + +See the [Beta 5 adoption audit](./beta-5-adoption-audit.md) for repository- +specific recommendations, the `trustProxy` assessment, and the default-template +comparison. ## Navigation diff --git a/docs/agents/remix/update.md b/docs/agents/remix/update.md index 2528c50..309b878 100644 --- a/docs/agents/remix/update.md +++ b/docs/agents/remix/update.md @@ -26,19 +26,18 @@ Keep each Markdown file to roughly 200 lines or fewer. If a README grows beyond that, split it into multiple files and update the package `index.md` to link the new chunks. -## 3) Refresh component docs +## 3) Refresh UI docs -`component` is the only package with a `docs` directory. Sync every file from: +Remix Beta 5 replaced the alpha `component` and `interaction` entrypoints with +`ui`. Refresh the current package README from: ``` -https://github.com/remix-run/remix/tree/main/packages/component/docs +https://github.com/remix-run/remix/tree/main/packages/ui ``` -Update the split files in `docs/agents/remix/component/` to match upstream. Keep -all docs: `animate`, `components`, `composition`, `context`, `events`, -`getting-started`, `handle`, `interactions`, `patterns`, `spring`, `styling`, -`testing`, `tween`. If any single doc exceeds roughly 200 lines, split it into -multiple files and add links in `component/index.md`. +Keep `docs/agents/remix/beta-5-adoption-audit.md` focused on this repository's +usage. The existing `component/` and `interaction/` directories are historical +alpha references; do not present them as current API guidance. ## 4) Keep the index current diff --git a/docs/agents/typescript-setup.md b/docs/agents/typescript-setup.md index 30ce8ba..0137feb 100644 --- a/docs/agents/typescript-setup.md +++ b/docs/agents/typescript-setup.md @@ -13,7 +13,8 @@ We have **three** distinct TypeScript environments, each with its own - **Config**: `types/tsconfig-client.json` - **Files**: `client/**/*.ts`, `client/**/*.tsx` -- **Environment**: browser (`DOM`, `DOM.Iterable`) + JSX (`remix/component`) +- **Environment**: browser (`DOM`, `DOM.Iterable`) + JSX (`remix/ui` through + `client/remix-ui-compat`) ### Tools From f9f6b9d8be9ac79a20eef64bc1a6fd145e8ee121 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 9 Jul 2026 18:03:15 +0000 Subject: [PATCH 4/4] test: tolerate minified calculator bundle --- mcp/mcp-server-e2e.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/mcp/mcp-server-e2e.test.ts b/mcp/mcp-server-e2e.test.ts index ec6b80c..d8bf3aa 100644 --- a/mcp/mcp-server-e2e.test.ts +++ b/mcp/mcp-server-e2e.test.ts @@ -625,9 +625,7 @@ test( calculatorWidgetResponse.headers.get('access-control-allow-origin'), ).toBe('*') const calculatorWidgetSource = await calculatorWidgetResponse.text() - expect(calculatorWidgetSource).toContain('createWidgetHostBridge') expect(calculatorWidgetSource).toContain('Calculator result:') - expect(calculatorWidgetSource).toContain('sendUserMessageWithFallback') expect(calculatorWidgetSource).toContain('ui/initialize') expect(calculatorWidgetSource).toContain('ui/message')