Files
traefik-llmgateway/webui/README.md
T
lukaszraczylo bb4fa4420e refactor(webui): rename Overview tab to Providers
Mechanical rename: OverviewView.vue -> ProvidersView.vue (file, component
import, tab label/value in App.vue), plus doc-comment/README references
across webui/ that named the view by its old tab label.

The backend GET /admin/api/overview endpoint, adminOverviewResponse type,
and the frontend AdminOverviewResponse/dashboard.overview field all keep
their original names unchanged (API surface) -- only the UI tab label and
the component/file that renders it changed. No behavior or layout change
to the view itself.
2026-08-21 13:17:11 +01:00

103 lines
5.3 KiB
Markdown

# Admin panel (webui)
Source for the traefik-llmgateway read-only admin dashboard: Vue 3 +
TypeScript + Pinia + Tailwind v4 + shadcn-vue + Chart.js, built with Vite.
See the repo root [README.md's Admin section](../README.md#admin) for what
the dashboard shows and how its API/auth works, and the
[Development section](../README.md#development) for `make admin-ui` — the
only way this directory's output (`../admin_assets_gen.go`) is meant to be
regenerated. Nothing here runs at request time: the plugin serves the
built, baked-in output, never `webui/` itself.
## Warning: `shadcn-vue add`/`init` regressions
`components.json` has no `iconLibrary` or `font` key. **Do not add them
back.** Their omission is the fix, not an oversight — read on before you
"helpfully" restore either one.
Earlier revisions of this file set `"iconLibrary": "lucide"` and
`"font": "inter"`, both wrong for this project (FontAwesome only, per
the `vue-web-development` house skill; no external font at all). Both
`npx shadcn-vue init` and `npx shadcn-vue add <component>` read those two
fields and, when set, rewrite `src/assets/main.css` — hit twice in this
project's own history, `init` then a later `add`, both re-adding a
`@import url('https://fonts.googleapis.com/...')` line and switching the
dark-mode `@custom-variant` back to a `.dark`-class toggle.
The actual shadcn-vue config schema
(`node_modules/shadcn-vue/dist/schema/index.js`'s `rawConfigSchema`)
declares both fields as `z.string().optional()` — not an enum, contrary
to an earlier, incorrect claim in this project's own review notes that
the CLI schema forced one of five fixed values. The CLI's `init --font`/
`--icon-library` flags do offer five fixed choices each, but that is a
flag-parsing constraint, not a `components.json` schema constraint.
Deleting both keys leaves them `undefined` after parse, a valid state:
verified empirically, running `npx shadcn-vue add badge -o -y` against a
`components.json` with both keys removed left `src/assets/main.css`
byte-for-byte unchanged.
That verification also surfaced a narrower, remaining trap: the same run
still added `@lucide/vue` back to `package.json`'s dependencies (Badge
itself does not use it — some components' registry entries list an icon
package regardless of `iconLibrary`). So after any future `shadcn-vue
add`/`init` call:
1. **Check `git diff webui/package.json`** for a re-added
`lucide-vue-next`/`@lucide/vue` dependency, and remove it
(`npm uninstall`) if nothing in `src/` imports from it.
2. **Check the new component's own file** for a
`lucide-vue-next`/`@lucide/vue` import and swap it for the
FontAwesome equivalent (see `src/components/ui/select/Select*.vue`
for the pattern already applied there).
3. **Diff `src/assets/main.css` anyway** before committing, in case a
future shadcn-vue release starts reading a different config key for
the same font-injection step.
## Local development
```sh
npm ci
npm run dev # Vite dev server — /admin/api/* calls need a real
# gateway to fetch from; point one at the same origin or
# accept the "refresh failed" state while iterating on
# layout/styling alone.
npm run build # what `make admin-ui` runs, plus webui/generate.mjs
```
## Structure
- `src/stores/` — Pinia: `auth` (the sessionStorage key gate), `dashboard`
(Providers/Usage, 5s poll), `history` (Charts, fetch-on-selection + 30s
refresh).
- `src/components/` — `AuthGate`, `ProvidersView` (the "Providers" tab —
named for its UI label; it still fetches GET /admin/api/overview, whose
own name is unchanged API surface), `UsageView`,
`ChartsView`/`UsageChart`, `UsageTable`, `DataTable` (the shared
sortable-table wrapper — shadcn-vue's DataTable pattern, `@tanstack/
vue-table`, generic over row type), `SearchInput` (the shared search-box
— icon + shadcn `Input` + shadcn `Button` clear button — every search
filter in the panel renders); `ui/` holds the shadcn-vue primitives this
panel actually uses (Accordion, Card, Table, Tabs, Button, Input, Alert,
Select, Badge) — nothing installed and unused. Providers and Groups
(Usage) render as a real Accordion — expanding a group shows its
member users' own usage rows, a client-side join on
`AdminUsageEntryView.groupName`.
- `src/composables/` — `useThemeColors` (Chart.js axis/grid/legend colors
off the current design tokens), `useSearchQuery` (the shared
`query`/`normalized`/`hasQuery` state every `SearchInput` pairs with).
- `src/lib/` — `api.ts` (the `/admin/api/*` fetch wrapper), `format.ts`,
`key-storage.ts`, `chart-setup.ts`, `search-expand.ts` (search-aware
expand state, adapted to drive Accordion's v-model — shared by
ProvidersView's providers and UsageView's groups), `usage-search.ts`
(shared user/group query-matching helpers, used by UsageView and
ChartsView), `usage-columns.ts` (shared `ColumnDef`s for every usage
table).
- `src/types/api.ts` — TypeScript mirrors of admin.go's JSON response
shapes (`adminOverviewResponse`, `adminUsageResponse`,
`usageHistoryResponse`) — these keep their backend names; only the
frontend tab label/component changed (see `ProvidersView` above).
- `generate.mjs` — reads `dist/` after `vite build` and writes
`../admin_assets_gen.go`; see its own header comment for why every
asset is base64-encoded rather than embedded as a raw string literal.