From fac42033e03fa2488f3ddfc7be8eb695fdfebca2 Mon Sep 17 00:00:00 2001 From: "Anthony Fu (via agent)" Date: Fri, 21 Aug 2026 22:53:10 +0000 Subject: [PATCH 1/2] feat(core): allow hosts to override DevTools branding --- docs/guide/index.md | 20 +++++++++++++ packages/core/src/node/plugins/index.ts | 16 ++++++++++- packages/core/src/node/ui.ts | 37 ++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/docs/guide/index.md b/docs/guide/index.md index 4546ecac4..df4590add 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -132,6 +132,26 @@ export default defineConfig({ }) ``` +The `branding` option re-skins the client — product name, logo, wordmark, primary color, tagline, favicon, and window title. Each field is merged over the built-in Vite DevTools defaults, so a host embedding Vite DevTools (such as Nuxt DevTools) can supply its own identity while inheriting anything it leaves unset. The asset fields (`logo`, `wordmark`, `favicon`) take URL strings the host serves. + +```ts [vite.config.ts] twoslash +import { DevTools } from '@vitejs/devtools' +import { defineConfig } from 'vite' + +export default defineConfig({ + plugins: [ + DevTools({ + branding: { + productName: 'Nuxt DevTools', + primaryColor: '#00dc82', + logo: '/my-assets/nuxt-logo.svg', + windowTitle: 'Nuxt DevTools', + }, + }), + ], +}) +``` + #### Projects without an HTML entry For apps where Vite doesn't serve the HTML (JS-only entries, backend integration, middleware mode), import the client injector from a browser entry instead. One entry per visibility mode — import whichever one you want: diff --git a/packages/core/src/node/plugins/index.ts b/packages/core/src/node/plugins/index.ts index 0d3b4f5cf..044827638 100644 --- a/packages/core/src/node/plugins/index.ts +++ b/packages/core/src/node/plugins/index.ts @@ -15,6 +15,19 @@ export interface DevToolsOptions { */ builtinDevTools?: boolean + /** + * Override the branding handed to the DevTools client (`@devframes/hub-ui`) + * — product name, logo, wordmark, primary color, tagline, favicon, and + * window title. + * + * Each field is merged over the built-in Vite DevTools defaults, so a host + * embedding Vite DevTools (e.g. Nuxt DevTools) can re-skin the client while + * inheriting any field it leaves unset. Asset fields + * (`logo`/`wordmark`/`favicon`) take URL strings the host is responsible for + * serving. + */ + branding?: ViteDevToolsUiOptions['branding'] + /** * How the embedded floating dock reveals itself on a fresh page. * @@ -63,11 +76,12 @@ export async function DevTools(options: DevToolsOptions = {}): Promise const { builtinDevTools = true, build, + branding, embeddedVisibility = 'normal', dockPreferences, } = options - const ui = { embeddedVisibility, dockPreferences } + const ui = { branding, embeddedVisibility, dockPreferences } const plugins = [ DevToolsInjection(), diff --git a/packages/core/src/node/ui.ts b/packages/core/src/node/ui.ts index 6b5b113df..f7dd7f597 100644 --- a/packages/core/src/node/ui.ts +++ b/packages/core/src/node/ui.ts @@ -4,6 +4,18 @@ import { createUi } from '@devframes/hub-ui' import { DEVTOOLS_ASSETS_BASE } from '../dirs' export interface ViteDevToolsUiOptions { + /** + * Override the Vite DevTools branding handed to `@devframes/hub-ui` + * (`ConnectionMeta.configs.ui.branding`) — product name, logo, wordmark, + * primary color, tagline, favicon, and window title. + * + * Each field is merged over the built-in Vite DevTools defaults + * ({@link viteDevToolsBranding}), so a host such as Nuxt DevTools can + * re-skin the client while inheriting any field it leaves unset. Asset + * fields (`logo`/`wordmark`/`favicon`) take URL strings; a host serving its + * own marks is responsible for hosting them. + */ + branding?: DevframeBranding /** * How the embedded floating dock reveals itself on a fresh page. Seeds a * user-overridable preference published as @@ -41,11 +53,34 @@ export function viteDevToolsBranding(): DevframeBranding { * that serves the DevTools client. Hands the reference viewer + embedded * bootstrap to `initHub({ ui })` (dev serve) or is copied out by the static * build. + * + * A host embedding Vite DevTools (e.g. Nuxt DevTools) can re-skin the client + * via `options.branding`, which is shallow-merged field-by-field over the + * built-in {@link viteDevToolsBranding} defaults. */ export function createViteDevToolsUi(options: ViteDevToolsUiOptions = {}): DevframeHubUi { return createUi({ - branding: viteDevToolsBranding(), + branding: resolveBranding(options.branding), embeddedVisibility: options.embeddedVisibility, dockPreferences: options.dockPreferences, }) } + +/** + * Merge a host's branding overrides over the Vite DevTools defaults. Only keys + * the host actually sets win; an explicit `undefined` is ignored so a partial + * override never clobbers a default with a hole. + */ +function resolveBranding(overrides?: DevframeBranding): DevframeBranding { + const branding = viteDevToolsBranding() + if (!overrides) { + return branding + } + for (const key of Object.keys(overrides) as (keyof DevframeBranding)[]) { + const value = overrides[key] + if (value !== undefined) { + branding[key] = value as never + } + } + return branding +} From d57d6a9f51908fad5d072568f696b439cbd8ef5d Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Sat, 22 Aug 2026 07:59:42 +0900 Subject: [PATCH 2/2] Discard changes to docs/guide/index.md --- docs/guide/index.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/docs/guide/index.md b/docs/guide/index.md index df4590add..4546ecac4 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -132,26 +132,6 @@ export default defineConfig({ }) ``` -The `branding` option re-skins the client — product name, logo, wordmark, primary color, tagline, favicon, and window title. Each field is merged over the built-in Vite DevTools defaults, so a host embedding Vite DevTools (such as Nuxt DevTools) can supply its own identity while inheriting anything it leaves unset. The asset fields (`logo`, `wordmark`, `favicon`) take URL strings the host serves. - -```ts [vite.config.ts] twoslash -import { DevTools } from '@vitejs/devtools' -import { defineConfig } from 'vite' - -export default defineConfig({ - plugins: [ - DevTools({ - branding: { - productName: 'Nuxt DevTools', - primaryColor: '#00dc82', - logo: '/my-assets/nuxt-logo.svg', - windowTitle: 'Nuxt DevTools', - }, - }), - ], -}) -``` - #### Projects without an HTML entry For apps where Vite doesn't serve the HTML (JS-only entries, backend integration, middleware mode), import the client injector from a browser entry instead. One entry per visibility mode — import whichever one you want: