From 06633d07ee5294294e0e6611320146d7aed13310 Mon Sep 17 00:00:00 2001 From: "Anthony Fu (via agent)" Date: Thu, 16 Jul 2026 00:20:57 +0000 Subject: [PATCH] refactor(oxc): relocate DevTools client into src/app to match rolldown/vite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the oxc Nuxt SPA from packages/oxc/client/ to packages/oxc/src/app so oxc shares the same layout as the other analyzer UIs and can be built with `nuxi ... src` + tsdown from a single package, dropping the nested client package.json. This is PR A of the oxc UI-stack migration (plan 018); it is a pure relocation and still runs on @nuxt/ui — the UnoCSS/@vitejs/devtools-ui swap follows in later PRs. Static output now lands in dist/public (from dist/client/public) and the node dts build is decoupled from the app-inclusive root tsconfig. Adds plan 018 documenting the full migration (PRs A/B/C) and the locked decisions behind it. --- packages/oxc/client/.oxfmtrc.json | 8 - packages/oxc/client/.oxlintrc.json | 25 --- packages/oxc/client/package.json | 13 -- packages/oxc/client/tsdown.config.ts | 16 -- packages/oxc/package.json | 7 +- .../oxc/{client => src}/app/app.config.ts | 0 packages/oxc/{client => src}/app/app.vue | 0 .../{client => src}/app/assets/css/main.css | 0 .../{client => src}/app/assets/icons/logo.svg | 0 .../app/assets/images/logo.png | Bin .../app/assets/images/oxc-bg.png | Bin .../{client => src}/app/components/Back.vue | 0 .../app/components/ColorModeButton.vue | 0 .../app/components/CongratState.vue | 0 .../app/components/EmptyState.vue | 0 .../app/components/ErrorTooltip.vue | 0 .../app/components/FileCard.vue | 0 .../app/components/LineError.vue | 0 .../app/components/LoadingState.vue | 0 .../{client => src}/app/components/Search.vue | 0 .../app/components/SessionCard.vue | 0 .../{client => src}/app/components/Shiki.vue | 0 .../app/components/SummaryCard.vue | 0 .../app/components/visual/Loading.vue | 0 .../app/composables/createShiki.ts | 0 .../{client => src}/app/composables/monaco.ts | 0 .../{client => src}/app/composables/rpc.ts | 0 .../app/composables/useFileUtils.ts | 0 .../{client => src}/app/pages/fmt/config.vue | 0 .../oxc/{client => src}/app/pages/index.vue | 0 .../{client => src}/app/pages/lint/config.vue | 0 .../app/pages/lint/report/[id].vue | 0 .../app/pages/lint/report/index.vue | 0 packages/oxc/src/dirs.ts | 4 +- packages/oxc/{client => src}/modules/rpc.js | 0 packages/oxc/{client => src}/nuxt.config.ts | 3 +- .../{client => src}/public/dot-grid-dark.png | Bin .../{client => src}/public/dot-grid-light.png | Bin .../oxc/{client => src}/public/favicon.svg | 0 packages/oxc/{client => src}/tsconfig.json | 0 packages/oxc/tsconfig.json | 10 +- packages/oxc/tsdown.config.ts | 3 +- plans/018-oxc-ui-unocss-migration.md | 184 ++++++++++++++++++ plans/README.md | 1 + 44 files changed, 202 insertions(+), 72 deletions(-) delete mode 100644 packages/oxc/client/.oxfmtrc.json delete mode 100644 packages/oxc/client/.oxlintrc.json delete mode 100644 packages/oxc/client/package.json delete mode 100644 packages/oxc/client/tsdown.config.ts rename packages/oxc/{client => src}/app/app.config.ts (100%) rename packages/oxc/{client => src}/app/app.vue (100%) rename packages/oxc/{client => src}/app/assets/css/main.css (100%) rename packages/oxc/{client => src}/app/assets/icons/logo.svg (100%) rename packages/oxc/{client => src}/app/assets/images/logo.png (100%) rename packages/oxc/{client => src}/app/assets/images/oxc-bg.png (100%) rename packages/oxc/{client => src}/app/components/Back.vue (100%) rename packages/oxc/{client => src}/app/components/ColorModeButton.vue (100%) rename packages/oxc/{client => src}/app/components/CongratState.vue (100%) rename packages/oxc/{client => src}/app/components/EmptyState.vue (100%) rename packages/oxc/{client => src}/app/components/ErrorTooltip.vue (100%) rename packages/oxc/{client => src}/app/components/FileCard.vue (100%) rename packages/oxc/{client => src}/app/components/LineError.vue (100%) rename packages/oxc/{client => src}/app/components/LoadingState.vue (100%) rename packages/oxc/{client => src}/app/components/Search.vue (100%) rename packages/oxc/{client => src}/app/components/SessionCard.vue (100%) rename packages/oxc/{client => src}/app/components/Shiki.vue (100%) rename packages/oxc/{client => src}/app/components/SummaryCard.vue (100%) rename packages/oxc/{client => src}/app/components/visual/Loading.vue (100%) rename packages/oxc/{client => src}/app/composables/createShiki.ts (100%) rename packages/oxc/{client => src}/app/composables/monaco.ts (100%) rename packages/oxc/{client => src}/app/composables/rpc.ts (100%) rename packages/oxc/{client => src}/app/composables/useFileUtils.ts (100%) rename packages/oxc/{client => src}/app/pages/fmt/config.vue (100%) rename packages/oxc/{client => src}/app/pages/index.vue (100%) rename packages/oxc/{client => src}/app/pages/lint/config.vue (100%) rename packages/oxc/{client => src}/app/pages/lint/report/[id].vue (100%) rename packages/oxc/{client => src}/app/pages/lint/report/index.vue (100%) rename packages/oxc/{client => src}/modules/rpc.js (100%) rename packages/oxc/{client => src}/nuxt.config.ts (97%) rename packages/oxc/{client => src}/public/dot-grid-dark.png (100%) rename packages/oxc/{client => src}/public/dot-grid-light.png (100%) rename packages/oxc/{client => src}/public/favicon.svg (100%) rename packages/oxc/{client => src}/tsconfig.json (100%) create mode 100644 plans/018-oxc-ui-unocss-migration.md diff --git a/packages/oxc/client/.oxfmtrc.json b/packages/oxc/client/.oxfmtrc.json deleted file mode 100644 index 90a61d709..000000000 --- a/packages/oxc/client/.oxfmtrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://unpkg.com/oxfmt/configuration_schema.json", - "semi": false, - "singleQuote": true, - "arrowParens": "avoid", - "quoteProps": "consistent", - "experimentalSortPackageJson": false -} diff --git a/packages/oxc/client/.oxlintrc.json b/packages/oxc/client/.oxlintrc.json deleted file mode 100644 index 06a062a8f..000000000 --- a/packages/oxc/client/.oxlintrc.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$schema": "https://unpkg.com/oxlint/configuration_schema.json", - "plugins": ["unicorn", "typescript", "oxc", "vue", "vitest"], - "categories": { - "correctness": "error", - "suspicious": "warn", - "perf": "warn" - }, - "rules": { - "no-console": "off", - "no-await-in-loop": "off", - "unicorn/no-array-sort": "off", - "no-restricted-globals": "error", - "typescript/consistent-type-imports": "off" - }, - "ignorePatterns": [ - ".output/**", - ".data/**", - ".nuxt/**", - ".nitro/**", - ".cache/**", - "dist/**", - "node_modules/**" - ] -} diff --git a/packages/oxc/client/package.json b/packages/oxc/client/package.json deleted file mode 100644 index 91c4d3bb0..000000000 --- a/packages/oxc/client/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "client", - "type": "module", - "private": true, - "scripts": { - "build": "nuxt build", - "dev": "nuxt dev", - "generate": "nuxt generate", - "preview": "nuxt preview", - "prepare": "nuxt prepare", - "prepack": "pnpm build" - } -} diff --git a/packages/oxc/client/tsdown.config.ts b/packages/oxc/client/tsdown.config.ts deleted file mode 100644 index 131941a1f..000000000 --- a/packages/oxc/client/tsdown.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { defineConfig } from 'tsdown' - -export default defineConfig({ - entry: { - index: 'node/index.ts', - dirs: 'dirs.ts', - }, - target: 'esnext', - dts: true, - clean: false, - inputOptions: { - experimental: { - resolveNewUrlToAsset: false, - }, - }, -}) diff --git a/packages/oxc/package.json b/packages/oxc/package.json index 3cbb33858..633953eff 100644 --- a/packages/oxc/package.json +++ b/packages/oxc/package.json @@ -33,10 +33,9 @@ "dist" ], "scripts": { - "build": "pnpm build:cli && pnpm build:client", - "build:cli": "tsdown", - "build:client": "pnpm -C client run build", - "dev": "pnpm -C client dev", + "build": "pnpm dev:prepare && nuxi build src && tsdown", + "dev": "nuxi dev src", + "dev:prepare": "nuxi prepare src", "lint": "oxlint && oxfmt --check", "lint:fix": "oxlint --fix && oxfmt", "play": "pnpm -C playground dev", diff --git a/packages/oxc/client/app/app.config.ts b/packages/oxc/src/app/app.config.ts similarity index 100% rename from packages/oxc/client/app/app.config.ts rename to packages/oxc/src/app/app.config.ts diff --git a/packages/oxc/client/app/app.vue b/packages/oxc/src/app/app.vue similarity index 100% rename from packages/oxc/client/app/app.vue rename to packages/oxc/src/app/app.vue diff --git a/packages/oxc/client/app/assets/css/main.css b/packages/oxc/src/app/assets/css/main.css similarity index 100% rename from packages/oxc/client/app/assets/css/main.css rename to packages/oxc/src/app/assets/css/main.css diff --git a/packages/oxc/client/app/assets/icons/logo.svg b/packages/oxc/src/app/assets/icons/logo.svg similarity index 100% rename from packages/oxc/client/app/assets/icons/logo.svg rename to packages/oxc/src/app/assets/icons/logo.svg diff --git a/packages/oxc/client/app/assets/images/logo.png b/packages/oxc/src/app/assets/images/logo.png similarity index 100% rename from packages/oxc/client/app/assets/images/logo.png rename to packages/oxc/src/app/assets/images/logo.png diff --git a/packages/oxc/client/app/assets/images/oxc-bg.png b/packages/oxc/src/app/assets/images/oxc-bg.png similarity index 100% rename from packages/oxc/client/app/assets/images/oxc-bg.png rename to packages/oxc/src/app/assets/images/oxc-bg.png diff --git a/packages/oxc/client/app/components/Back.vue b/packages/oxc/src/app/components/Back.vue similarity index 100% rename from packages/oxc/client/app/components/Back.vue rename to packages/oxc/src/app/components/Back.vue diff --git a/packages/oxc/client/app/components/ColorModeButton.vue b/packages/oxc/src/app/components/ColorModeButton.vue similarity index 100% rename from packages/oxc/client/app/components/ColorModeButton.vue rename to packages/oxc/src/app/components/ColorModeButton.vue diff --git a/packages/oxc/client/app/components/CongratState.vue b/packages/oxc/src/app/components/CongratState.vue similarity index 100% rename from packages/oxc/client/app/components/CongratState.vue rename to packages/oxc/src/app/components/CongratState.vue diff --git a/packages/oxc/client/app/components/EmptyState.vue b/packages/oxc/src/app/components/EmptyState.vue similarity index 100% rename from packages/oxc/client/app/components/EmptyState.vue rename to packages/oxc/src/app/components/EmptyState.vue diff --git a/packages/oxc/client/app/components/ErrorTooltip.vue b/packages/oxc/src/app/components/ErrorTooltip.vue similarity index 100% rename from packages/oxc/client/app/components/ErrorTooltip.vue rename to packages/oxc/src/app/components/ErrorTooltip.vue diff --git a/packages/oxc/client/app/components/FileCard.vue b/packages/oxc/src/app/components/FileCard.vue similarity index 100% rename from packages/oxc/client/app/components/FileCard.vue rename to packages/oxc/src/app/components/FileCard.vue diff --git a/packages/oxc/client/app/components/LineError.vue b/packages/oxc/src/app/components/LineError.vue similarity index 100% rename from packages/oxc/client/app/components/LineError.vue rename to packages/oxc/src/app/components/LineError.vue diff --git a/packages/oxc/client/app/components/LoadingState.vue b/packages/oxc/src/app/components/LoadingState.vue similarity index 100% rename from packages/oxc/client/app/components/LoadingState.vue rename to packages/oxc/src/app/components/LoadingState.vue diff --git a/packages/oxc/client/app/components/Search.vue b/packages/oxc/src/app/components/Search.vue similarity index 100% rename from packages/oxc/client/app/components/Search.vue rename to packages/oxc/src/app/components/Search.vue diff --git a/packages/oxc/client/app/components/SessionCard.vue b/packages/oxc/src/app/components/SessionCard.vue similarity index 100% rename from packages/oxc/client/app/components/SessionCard.vue rename to packages/oxc/src/app/components/SessionCard.vue diff --git a/packages/oxc/client/app/components/Shiki.vue b/packages/oxc/src/app/components/Shiki.vue similarity index 100% rename from packages/oxc/client/app/components/Shiki.vue rename to packages/oxc/src/app/components/Shiki.vue diff --git a/packages/oxc/client/app/components/SummaryCard.vue b/packages/oxc/src/app/components/SummaryCard.vue similarity index 100% rename from packages/oxc/client/app/components/SummaryCard.vue rename to packages/oxc/src/app/components/SummaryCard.vue diff --git a/packages/oxc/client/app/components/visual/Loading.vue b/packages/oxc/src/app/components/visual/Loading.vue similarity index 100% rename from packages/oxc/client/app/components/visual/Loading.vue rename to packages/oxc/src/app/components/visual/Loading.vue diff --git a/packages/oxc/client/app/composables/createShiki.ts b/packages/oxc/src/app/composables/createShiki.ts similarity index 100% rename from packages/oxc/client/app/composables/createShiki.ts rename to packages/oxc/src/app/composables/createShiki.ts diff --git a/packages/oxc/client/app/composables/monaco.ts b/packages/oxc/src/app/composables/monaco.ts similarity index 100% rename from packages/oxc/client/app/composables/monaco.ts rename to packages/oxc/src/app/composables/monaco.ts diff --git a/packages/oxc/client/app/composables/rpc.ts b/packages/oxc/src/app/composables/rpc.ts similarity index 100% rename from packages/oxc/client/app/composables/rpc.ts rename to packages/oxc/src/app/composables/rpc.ts diff --git a/packages/oxc/client/app/composables/useFileUtils.ts b/packages/oxc/src/app/composables/useFileUtils.ts similarity index 100% rename from packages/oxc/client/app/composables/useFileUtils.ts rename to packages/oxc/src/app/composables/useFileUtils.ts diff --git a/packages/oxc/client/app/pages/fmt/config.vue b/packages/oxc/src/app/pages/fmt/config.vue similarity index 100% rename from packages/oxc/client/app/pages/fmt/config.vue rename to packages/oxc/src/app/pages/fmt/config.vue diff --git a/packages/oxc/client/app/pages/index.vue b/packages/oxc/src/app/pages/index.vue similarity index 100% rename from packages/oxc/client/app/pages/index.vue rename to packages/oxc/src/app/pages/index.vue diff --git a/packages/oxc/client/app/pages/lint/config.vue b/packages/oxc/src/app/pages/lint/config.vue similarity index 100% rename from packages/oxc/client/app/pages/lint/config.vue rename to packages/oxc/src/app/pages/lint/config.vue diff --git a/packages/oxc/client/app/pages/lint/report/[id].vue b/packages/oxc/src/app/pages/lint/report/[id].vue similarity index 100% rename from packages/oxc/client/app/pages/lint/report/[id].vue rename to packages/oxc/src/app/pages/lint/report/[id].vue diff --git a/packages/oxc/client/app/pages/lint/report/index.vue b/packages/oxc/src/app/pages/lint/report/index.vue similarity index 100% rename from packages/oxc/client/app/pages/lint/report/index.vue rename to packages/oxc/src/app/pages/lint/report/index.vue diff --git a/packages/oxc/src/dirs.ts b/packages/oxc/src/dirs.ts index 6e226b216..e73398c2e 100644 --- a/packages/oxc/src/dirs.ts +++ b/packages/oxc/src/dirs.ts @@ -1,5 +1,3 @@ import { fileURLToPath } from 'node:url' -export const clientPublicDir: string = fileURLToPath( - new URL('../dist/client/public', import.meta.url), -) +export const clientPublicDir: string = fileURLToPath(new URL('../dist/public', import.meta.url)) diff --git a/packages/oxc/client/modules/rpc.js b/packages/oxc/src/modules/rpc.js similarity index 100% rename from packages/oxc/client/modules/rpc.js rename to packages/oxc/src/modules/rpc.js diff --git a/packages/oxc/client/nuxt.config.ts b/packages/oxc/src/nuxt.config.ts similarity index 97% rename from packages/oxc/client/nuxt.config.ts rename to packages/oxc/src/nuxt.config.ts index 1c3edebf8..e06b4f050 100644 --- a/packages/oxc/client/nuxt.config.ts +++ b/packages/oxc/src/nuxt.config.ts @@ -6,10 +6,11 @@ export default defineNuxtConfig({ compatibilityDate: '2024-11-01', devtools: { enabled: true }, ssr: false, + srcDir: 'app', nitro: { preset: 'static', output: { - dir: '../dist/client', + dir: '../dist', }, routeRules: { '/': { diff --git a/packages/oxc/client/public/dot-grid-dark.png b/packages/oxc/src/public/dot-grid-dark.png similarity index 100% rename from packages/oxc/client/public/dot-grid-dark.png rename to packages/oxc/src/public/dot-grid-dark.png diff --git a/packages/oxc/client/public/dot-grid-light.png b/packages/oxc/src/public/dot-grid-light.png similarity index 100% rename from packages/oxc/client/public/dot-grid-light.png rename to packages/oxc/src/public/dot-grid-light.png diff --git a/packages/oxc/client/public/favicon.svg b/packages/oxc/src/public/favicon.svg similarity index 100% rename from packages/oxc/client/public/favicon.svg rename to packages/oxc/src/public/favicon.svg diff --git a/packages/oxc/client/tsconfig.json b/packages/oxc/src/tsconfig.json similarity index 100% rename from packages/oxc/client/tsconfig.json rename to packages/oxc/src/tsconfig.json diff --git a/packages/oxc/tsconfig.json b/packages/oxc/tsconfig.json index 70d2b7233..99e6e8b5e 100644 --- a/packages/oxc/tsconfig.json +++ b/packages/oxc/tsconfig.json @@ -4,5 +4,13 @@ "composite": true, "lib": ["esnext", "dom"] }, - "include": ["src", "bin"] + "include": [ + "src/index.ts", + "src/vite.ts", + "src/dirs.ts", + "src/commands", + "src/node", + "src/types", + "bin" + ] } diff --git a/packages/oxc/tsdown.config.ts b/packages/oxc/tsdown.config.ts index 6b0a2ae32..91d297798 100644 --- a/packages/oxc/tsdown.config.ts +++ b/packages/oxc/tsdown.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from 'tsdown' export default defineConfig({ entry: ['src/index.ts', 'src/types/index.ts', 'src/vite.ts'], + tsconfig: '../../tsconfig.base.json', dts: true, - clean: true, + clean: false, }) diff --git a/plans/018-oxc-ui-unocss-migration.md b/plans/018-oxc-ui-unocss-migration.md new file mode 100644 index 000000000..f03203c14 --- /dev/null +++ b/plans/018-oxc-ui-unocss-migration.md @@ -0,0 +1,184 @@ +# Plan 018: Migrate the oxc DevTools UI onto `@vitejs/devtools-ui` + UnoCSS + +> **Executor instructions**: Follow step by step; verify each step. Honor STOP +> conditions. Update this plan's row in `plans/README.md` when done. +> +> **Drift check (run first)**: `git diff --stat main..HEAD -- packages/oxc packages/ui` +> Compare "Current state" against live code first — PR A (below) may already be landed. + +## Status + +- **Priority**: P3 +- **Effort**: L (split across three PRs) +- **Risk**: MED +- **Depends on**: — (relates to 017; not blocked by it) +- **Category**: tech-debt / architecture / design +- **Planned at**: 2026-07-16 + +## Why this matters + +`@vitejs/devtools-oxc` is the **only** UI package in the repo not on the shared stack. +`packages/rolldown` and `packages/vite` are both Nuxt 4 SPAs styled by UnoCSS via +`presetDevToolsUI` from `@vitejs/devtools-ui`, consuming shared components, semantic +shortcuts, dark-mode, fonts and the dotted-grid background. oxc instead ships a Nuxt 4 +SPA on **`@nuxt/ui` v4 + Tailwind v4**, borrowing only a banner from the shared package. +Because of that divergence the root `AGENTS.md` keeps oxc **out of the turbo +build/typecheck/lint/export-snapshot gates** "pending a UI-stack decision". + +This plan **is** that decision: move oxc onto UnoCSS + `@vitejs/devtools-ui`, align its +look and feel to the other analyzers, and bring it into the CI gates. + +## Locked decisions (from planning interview) + +1. **Scope = minimal stack swap.** Keep oxc's existing top-nav + `container mx-auto` + page layout. "Align to rolldown" here means shared *tokens, fonts, dark-mode, + dotted-grid background, severity ramp, icons* — **not** adopting rolldown's + `PanelSideNav` shell or glass slide-over detail panels. +2. **Directory layout = `src/app`.** Restructure the client from `packages/oxc/client/` + to `packages/oxc/src/app` and run `nuxi … src`, mirroring rolldown/vite. **(PR A — done.)** +3. **New primitives live upstream in `@vitejs/devtools-ui`.** `@nuxt/ui` gave oxc + overlays/forms/containers with no shared equivalent; build the reusable replacements + (`Card`, `Modal`, `Checkbox`, `EmptyState`) in `packages/ui` so every analyzer benefits. +4. **Wire CI gates + set brand color** as part of the migration. Derive the oxc + `primary` scale from the `BannerOxcDevTools` accent (today it is `cyan`). + +## Reference implementations to copy + +- **Plumbing** (uno.config, nuxt.config, scripts, global.css import, floating-vue plugin, + monaco composable, dark-mode) → `packages/vite` (minimal) and `packages/rolldown`. +- **Look & feel tokens** → `@vitejs/devtools-ui/unocss/shared-shortcuts` + + `unocss/shortcuts` (already provide `bg-dots`, `color-scale-*`, `bg-base`/`color-base`/ + `border-base`/`bg-glass`, `btn-action`, `badge-color-*`). + +## The `@nuxt/ui` → shared/local mapping (drives PR C) + +| `@nuxt/ui` used | Where | Replacement | +|---|---|---| +| `UApp` / `UMain` | `app.vue` | drop; plain shell like rolldown `app.vue` | +| `UCard` | index, SessionCard, FileCard, SummaryCard | new shared `Card` | +| `UButton` | Back, ErrorTooltip, index | `btn-action`/`btn-action-sm` or shared `DisplayIconButton` | +| `UBadge` | SessionCard, FileCard, index | shared `DisplayBadge`/`DisplayNumberBadge` + `badge-color-*` | +| `UModal` | SummaryCard (config viewer) | new shared `Modal` | +| `UTooltip` | LineError, SummaryCard | `floating-vue` `v-tooltip` | +| `UInput` | Search | shared `DataSearchPanel` or styled `input` | +| `UCheckbox` | lint/report ("Hide Passed") | new shared `Checkbox` | +| `UEmpty` | lint/report | new shared `EmptyState` | +| `UIcon` | throughout | `i-ph-*` / `i-carbon-*` classes | +| `useColorMode()` | ColorModeButton, config pages | shared `isDark`/`toggleDark` (storageKey `vite-devtools-color-scheme`) | + +Delete-not-migrate (already in shared layer): oxc's local `.bg-dots` and +`.color-scale-*` in `app/assets/css/main.css`; hand-rolled duration coloring in +`SummaryCard` (use shared `DisplayDuration`); the `.shiki { … var(--ui-bg) }` override +(rewrite against `bg-code`/`bg-base`). + +## PR breakdown + +### PR A — directory restructure (DONE in this branch) + +Pure move, still on `@nuxt/ui`; the package builds identically from the new location. + +- `git mv packages/oxc/client/{app,modules,public,nuxt.config.ts,tsconfig.json}` → `packages/oxc/src/…` +- Removed `client/{package.json,tsdown.config.ts,.oxlintrc.json,.oxfmtrc.json}` + (client oxc-configs were byte-identical to the package-root ones; the empty nested + `package.json` only carried scripts now replaced). +- `src/nuxt.config.ts`: `srcDir: 'app'`; `nitro.output.dir` `'../dist/client'` → `'../dist'` + (static preset now emits to `dist/public`). +- `src/dirs.ts`: `clientPublicDir` `'../dist/client/public'` → `'../dist/public'`. +- `package.json` scripts: `build` → `pnpm dev:prepare && nuxi build src && tsdown`; + `dev` → `nuxi dev src`; add `dev:prepare` → `nuxi prepare src`; drop `build:cli`/`build:client`. +- `tsdown.config.ts`: `clean: true` → `false` (so tsdown does not wipe the nuxi-built + `dist/public`); `tsconfig: '../../tsconfig.base.json'` (decouple node dts from the + app-inclusive root tsconfig). +- `tsconfig.json`: narrow `include` from `["src","bin"]` to node-only paths so `vue-tsc` + does not try to typecheck the Nuxt app without its generated context. + +All app→node relative imports (`../../../src/types`, `../../../src/node/rpc`) and the dev +module's `../vite`/`../../src/vite` import survive unchanged, because `client/**` and +`src/**` sit at the same depth under `packages/oxc`. + +**Verified**: `pnpm turbo run build --filter=@vitejs/devtools-oxc` → client prerendered to +`dist/public` (favicon + index.html present), node entries emitted by tsdown; git status is +history-preserving renames + 4 deletions + 4 config edits; build artifacts gitignored. + +### PR B — upstream primitives into `@vitejs/devtools-ui` + +Add Wind4 components + per-file exports (`./components/*`), styled only with shared +shortcuts so they stay safe for both the Wind4 (Nuxt) and Wind3 (webcomponents) surfaces: + +- `Card.vue` — `bg-base border-base rounded` with `header`/`body`/`footer` slots; defaults + port oxc's old `app.config.ts` card slots. +- `Modal.vue` — teleport overlay + `bg-glass` panel + backdrop/`Escape` close. +- `Checkbox.vue` — styled `v-model` checkbox. +- `EmptyState.vue` — icon + title/description (oxc's local one is a dead 0-byte file). + +Add tests where trivial; update any component export snapshot. **Verify**: +`pnpm -C packages/ui exec vitest run`, `pnpm build`, `pnpm typecheck` green; components +render in rolldown/vite dev servers (they must not regress existing consumers). + +### PR C — the actual swap + look-and-feel + CI gates + +Depends on PR A + PR B. + +1. **Plumbing**: `package.json` — remove `@nuxt/ui`, `tailwindcss`; add `unocss`, + `@unocss/nuxt`, `floating-vue`, `theme-vitesse` (`catalog:*`). Add `src/uno.config.ts` + (copy vite's) with a local font processor **and** an oxc `primary` scale derived from + the `BannerOxcDevTools` accent. `nuxt.config.ts`: modules `@unocss/nuxt` + `@vueuse/nuxt` + (drop `@nuxt/ui`); add `unocss.configFile`; keep `htmlAttrs.class='bg-dots'`, base, port; + drop the `ui:` block. Delete `app.config.ts`. Rewrite `assets/css/main.css` to + `@import '@vitejs/devtools-ui/styles/global.css'` + local-only overrides (Monaco; + `.shiki` → `bg-code`/`bg-base`; floating-vue). Add `plugins/floating-vue.ts` (copy + rolldown's). In `app.vue` drop `UApp`/`UMain`, keep the `container mx-auto` shell, add + the side-effect `import '@vitejs/devtools-ui/composables/dark'`. +2. **Component/page migration**: apply the mapping table above page-by-page (Back, Search, + ColorModeButton, SessionCard → index → lint/report/index + FileCard/SummaryCard → + lint/report/[id]); replace every inline `dark:` pair with shared semantic shortcuts. +3. **Bespoke, logic-heavy**: `LineError.vue` (preserve the ASCII underline math; `UTooltip` + → `v-tooltip`), `ErrorTooltip.vue`, `Shiki.vue`; `lint/config.vue` + `fmt/config.vue` + (keep the momoa JSON5→docs mapping; align Monaco theme to `isDark`, move Monaco CSS to + the global overrides — copy rolldown's `composables/monaco.ts` + `styles/cm.css` pattern). +4. **Look & feel pass**: side-by-side vs rolldown (light + dark) via `agent-browser` — DM + Sans/Mono, Phosphor duotone icons, dotted-grid bg, severity ramp, `op-fade`/`op-mute`, + scrollbar tokens, `bg-glass` on the config Modal. +5. **CI gates + cleanup**: add oxc to `tsconfig.json` references (`./packages/oxc/src/tsconfig.json`) + and remove the `../../../oxc/**/*` exclude in rolldown/vite nuxt typecheck config; wire + oxc into the turbo `typecheck`/`lint`/export-snapshot tasks (build task already exists); + update root `AGENTS.md` (drop "pending a UI-stack decision" / "out of the gates" notes). + Remove any now-dead components (`LoadingState`/`CongratState` if unused). + +## Commands you will need + +| Purpose | Command | Expected | +|---|---|---| +| Build oxc (+deps) | `pnpm turbo run build --filter=@vitejs/devtools-oxc` | exit 0 | +| Dev (visual, bind host) | `pnpm -C packages/oxc dev` (Nuxt dev server, port 4448) | renders | +| ui tests | `pnpm -C packages/ui exec vitest run` | pass | +| Full gates | `pnpm lint && pnpm test && pnpm typecheck && pnpm build` | exit 0 | + +## Done criteria + +ALL must hold: +- [ ] (PR A) client lives under `packages/oxc/src/app`; package builds from the new layout +- [ ] (PR B) `Card`/`Modal`/`Checkbox`/`EmptyState` in `@vitejs/devtools-ui`, existing consumers unaffected +- [ ] (PR C) no imports of `@nuxt/ui` / `tailwindcss` / `useColorMode` remain in oxc +- [ ] oxc styled by `presetDevToolsUI`; primary color derived from the oxc banner; dark + toggle uses the shared storage key +- [ ] Monaco config viewers still map cursor→docs (momoa) and follow dark mode; + `LineError` underline art still aligns per column +- [ ] oxc passes all four CI gates and is no longer excluded in `AGENTS.md` + +## STOP conditions + +Stop and report if: +- A `@nuxt/ui` feature has no clean shared/local replacement without a redesign that + exceeds "minimal stack swap" (note it, propose the smallest local component). +- Promoting a primitive to `packages/ui` would regress rolldown/vite (Wind3 vs Wind4 + token divergence) — keep it local to oxc and note why. +- Wiring oxc into the shared Nuxt typecheck surfaces a large pre-existing error backlog — + land the UI swap first, gate-wiring in a follow-up, and record the backlog. + +## Maintenance notes + +- After this lands, new oxc UI should build on `@vitejs/devtools-ui` + UnoCSS, never + `@nuxt/ui`. Update `AGENTS.md`'s package table entry for oxc accordingly. +- This removes the last "pending UI-stack decision" caveat and makes a future shared + analyzer shell (relates to plan 017) cheaper. diff --git a/plans/README.md b/plans/README.md index baba72800..aa5248d4a 100644 --- a/plans/README.md +++ b/plans/README.md @@ -29,6 +29,7 @@ self-contained — it does not assume you saw the audit or the other plans. | 015 | Consolidate triplicated `color`/`format`/`filepath` utils into `packages/ui` | P3 | S–M | 001 | DONE | | 016 | Break up the `RolldownEventsReader` god class | P3 | L | 014 | TODO | | 017 | Deduplicate the parallel Rolldown/Vite Nuxt apps into `packages/ui` | P3 | L | 015 | TODO | +| 018 | Migrate the oxc DevTools UI onto `@vitejs/devtools-ui` + UnoCSS | P3 | L | — | IN PROGRESS (PR A landed: `src/app` restructure) | Status values: TODO | IN PROGRESS | DONE | BLOCKED (one-line reason) | REJECTED (one-line rationale)