Documentation index: /llms.txt. Each page is also available as Markdown by adding .md to its URL.

Skip to content
Brief

Visual Customization

Customize logos, colors, typography, layout, icons, and components.

Global Configuration#

Edit brief/config/visuals.ts to customize Brief's appearance.

brief/config/visuals.ts

Branding#

logo.lightRequired
string
Logo shown in light mode. Required when logo is set; otherwise Brief displays the site name. Put the image in public/ and use its public path.
logo.darkRequired
string
Logo shown in dark mode. Required when logo is set; can use the same image as logo.light.
logo.hrefDefault undefined
string
Link destination when readers click the logo. If omitted, the logo links to /.

Colors#

Built-in palettes include blue, cyan, violet, zinc, and slate. Brief selects shades for light and dark mode automatically.

tokens.colors.accentDefault "blue"
string
Palette for links, active controls, and highlights.
tokens.colors.baseDefault "zinc"
string
Palette for neutral backgrounds and borders.
tokens.colors.textDefault tokens.colors.base
string
Palette for text and neutral icons. Defaults to tokens.colors.base.
tokens.colors.positiveDefault "green"
string
Palette for positive states.
tokens.colors.negativeDefault "red"
string
Palette for negative states.
colors.<name>Default BUILT_IN_COLOR_SCALES[name]
ColorScale
Custom palette, referenced by name in tokens and content. Existing names use BUILT_IN_COLOR_SCALES from @brief/ui/palette; new names default to undefined. Supply CSS colors for shades 50, 100 through 900, 925, and 950.

Background#

tokens.canvas.lightDefault "var(--color-base-50)"
string
Page background CSS color in light mode. Supply both canvas colors when overriding.
tokens.canvas.darkDefault "var(--color-base-950)"
string
Page background CSS color in dark mode.
backgroundDefault undefined
Component
React component rendered behind the page content. Keep it decorative, without interactive controls.

Typography#

Import bundled fonts from @brief/ui/fonts.

tokens.typography.<role>Default undefined
TextStyle
Fonts, sizes, weights, and spacing for body, h1 through h4, code, ui, uiCompact, uiSmall, button, or shortcut. Each role accepts settings such as family, size, and weight. Omitted overrides use Brief's role defaults: Inter for body and interface text, Roboto Mono for code. Headings inherit the body font.

Borders and Shadows#

tokens.radiusDefault "medium"
"none" | "small" | "medium" | "large"
Corner rounding.
tokens.borderWidthDefault "medium"
"none" | "thin" | "medium" | "thick"
Border thickness.
tokens.shadowDefault "small"
"none" | "small" | "medium" | "large"
Shadow depth.

Navigation#

layout.sidebar.placementDefault "content"
"content" | "page"
Place the sidebar alongside the content or at the page edge.
layout.sidebar.variantDefault "tracker-line"
"simple" | "tracker-line" | "tracker-dot" | "tracker-background" | "threads"
Sidebar item decoration and active-page indicator.
layout.toc.variantDefault "simple"
"simple" | "tracker-line" | "tracker-dot" | "tracker-background" | "threads"
Table-of-contents item decoration and active-section indicator.
layout.topBar.desktopDefault "gradient-blur"
"gradient-blur" | "opaque" | "transparent-blur" | "none"
Desktop top bar appearance. none moves its controls into the sidebar.
layout.topBar.mobileDefault "gradient-blur"
"gradient-blur" | "opaque" | "transparent-blur"
Mobile top bar appearance.

Component-Specific Styles#

components.button.variantDefault "outline"
"outline" | "soft"
Default button appearance.
components.callout.variantDefault "quote"
"quote" | "card" | "quote-card"
Default callout presentation.
components.divider.variantDefault "solid"
"solid" | "gradient" | "dotted"

Divider appearance.

Solid and gradient dividers use border widths of 1px, 1px, 1.5px, and 2px for tokens.borderWidth values of none, thin, medium, and thick, respectively. Browsers snap border widths to device pixels. Dotted dividers use a fixed 2px pattern.

components.overlay.backdropDefault "blurred"
"blurred" | "opaque"
Backdrop behind overlays.
components.card.frameDefault "none"
"none" | "debossed" | "embossed"
Frame around cards on desktop.
components.image.frameDefault "none"
"none" | "debossed" | "embossed"
Frame around images on desktop.
components.code.frameDefault "none"
"none" | "debossed" | "embossed"
Frame around code blocks and terminals on desktop.

Icons#

There are two sets of icons in the application:

  1. Interface icons are used for icons baked into Brief's layout like the theme toggle or the generic copy icon across all components.
  2. Content icons can be used by in-page components like Icon, Badge, and Callout.

Interface Icons#

Customize interfaceIcons to set the interface icons. Make your own bundle of icons or choose from one of the default bundles.

Content Icons#

Content icons are SVG components that forward their SVG props and use currentColor.

Register content icons in the icons map in brief/config/visuals.ts. Each icon's key can then be referenced and used in authors' pages.

brief/config/visuals.ts

You can then start using it in certain components across all pages.

Individual Page Customization#

Pages have individual settings that can be customized via their frontmatter.

content_widthDefault "medium"
"small" | "medium" | "large"
Width of the page content.
tocDefault true
boolean
Set to false to hide the table of contents. Useful for pages with wide custom components.

Custom Components#

For a rendered component with authored attributes, use these registration fields:

componentRequired
Component
React component renderer that receives the validated attributes as props.
schemaRequired
ZodSchema
Validates authored attributes and supplies defaults.
searchDefault undefined
(input: ComponentBuildInput<Props>) => ComponentSearchResult<Record<never, never>>
Supplies text generated by the component for use in search. Return { text } for a label derived from its attributes, or false to exclude the component and its children from search entirely.
markdownDefault undefined
(input: ComponentBuildInput<Props>, children: readonly Node[]) => readonly Node[]
Converts the component to portable Markdown nodes for agent-facing .md pages. children contains its already-converted child nodes.

You can then start using the registered component: