/** * Browser-safe brand contract, defaults, and LLM serialization helpers. * * Asset values are intentionally strings: they may be relative file paths, * package exports, data URLs, or network URLs depending on the consumer. * * @module */ import { z } from "zod"; const nonBlankString = z.string().trim().min(1); const color = z.string().regex(/^#(?:[\da-f]{3}|[\da-f]{6}|[\da-f]{8})$/i, "Expected a hex color."); /** Package asset references used when a brand context supplies no custom artwork. */ export const DEFAULT_BRAND_ASSETS = { icon: { light: "@dbx-tools/ui/branding/assets/icon-light.svg", dark: "@dbx-tools/ui/branding/assets/icon-dark.svg", }, logo: { light: "@dbx-tools/ui/branding/assets/logo-light.svg", dark: "@dbx-tools/ui/branding/assets/logo-dark.svg", }, favicon: "@dbx-tools/ui/branding/assets/icon-light.svg", } as const; /** Validates light and optional dark variants for one visual asset. */ export const BrandAssetSetSchema = z .object({ light: nonBlankString.describe("Asset for light surfaces."), dark: nonBlankString.optional().describe("Asset for dark surfaces; light is the fallback."), }) .strict() .describe("Theme-aware references to one visual asset."); /** Strict brand palette whose omitted colors resolve to the dbx tools defaults. */ export const BrandColorsSchema = z .object({ primary: color.default("#1B3139").describe("Primary action and identity color."), primaryHover: color.default("#0E538B").describe("Primary hover or pressed color."), accent: color.default("#00A972").describe("Secondary accent color."), foreground: color.default("#1B3139").describe("Default text and mark color."), background: color.default("#FFFFFF").describe("Default page background."), surface: color.default("#F9F7F4").describe("Secondary surface background."), muted: color.default("#618794").describe("Muted text color."), border: color.default("#E4E2DD").describe("Default border color."), }) .strict() .prefault({}); /** Strict audience, tone, principle, and avoidance lists with practical defaults. */ export const BrandVoiceSchema = z .object({ audience: z .array(nonBlankString) .default(["Databricks developers", "application engineers", "AI agents"]), tone: z.array(nonBlankString).default(["direct", "practical", "technical", "approachable"]), principles: z .array(nonBlankString) .default([ "Lead with the useful outcome.", "Prefer concrete examples and accurate technical language.", "Keep product claims specific and defensible.", ]), avoid: z .array(nonBlankString) .default(["unsupported superlatives", "vague AI claims", "unnecessary jargon"]), }) .strict() .prefault({}); /** * Strict portable brand contract that fills identity, assets, colors, * typography, voice, links, and extension defaults during parsing. */ export const BrandContextSchema = z .object({ schemaVersion: z.literal("1").default("1"), name: nonBlankString.default("dbx tools").describe("Canonical display name."), shortName: nonBlankString.default("dbx").describe("Compact name for constrained UI."), tagline: nonBlankString .optional() .describe("Optional product line suitable for a header or metadata."), description: nonBlankString .default( "Companion packages for Databricks developers building apps, agents, data workflows, and reusable UI.", ) .describe("Plain-language product description."), assets: z .object({ icon: BrandAssetSetSchema.default(DEFAULT_BRAND_ASSETS.icon), logo: BrandAssetSetSchema.default(DEFAULT_BRAND_ASSETS.logo), favicon: nonBlankString.default(DEFAULT_BRAND_ASSETS.favicon), }) .strict() .default(DEFAULT_BRAND_ASSETS), colors: BrandColorsSchema, typography: z .object({ sans: nonBlankString.default("'DM Sans', ui-sans-serif, system-ui, sans-serif"), mono: nonBlankString.default("'DM Mono', ui-monospace, SFMono-Regular, Menlo, monospace"), }) .strict() .prefault({}), voice: BrandVoiceSchema, links: z .object({ website: z.string().url().default("https://dbx.tools"), repository: z.string().url().optional(), documentation: z.string().url().default("https://docs.dbx.tools/"), }) .strict() .prefault({}), extensions: z .record(nonBlankString, z.unknown()) .default({}) .describe("Namespaced consumer-specific values that do not belong in the portable core."), }) .strict() .describe("Portable identity, visual, and voice context for UI, libraries, and LLMs."); /** Fully validated brand context after every schema default has been applied. */ export type BrandContext = z.output; /** Input accepted by {@link BrandContextSchema}, before defaults are materialized. */ export type BrandContextInput = z.input; /** Theme-aware light and optional dark references for one brand asset. */ export type BrandAssetSet = z.output; /** Validate input and fill every dbx tools default. */ export function parseBrandContext(input: unknown = {}): BrandContext { return BrandContextSchema.parse(input); } /** Canonical dbx tools brand context with all schema defaults resolved. */ export const defaultBrandContext: BrandContext = parseBrandContext({ tagline: "Practical tools for Databricks builders.", }); /** JSON Schema representation suitable for structured-output and tool definitions. */ export function brandContextJsonSchema(): Record { return z.toJSONSchema(BrandContextSchema) as Record; } /** Stable prompt block for an LLM that needs to write or design in this brand. */ export function brandContextPrompt(context: BrandContext = defaultBrandContext): string { return [ `Use the following ${context.name} brand context for names, visual choices, and writing voice.`, "Treat explicit task instructions as higher priority than this context.", "", JSON.stringify(context, null, 2), ].join("\n"); }