Skip to content

Theming

CaretCMS includes one admin-interface theme, studio. Your site design remains in your Astro components and styles.

Studio chrome—the surrounding interface, such as backgrounds, buttons, and labels—controls the appearance of /admin and /admin/cms. Its neutral defaults are intended to work alongside different site designs.

Tokens are CSS variables used by Studio. Override the ones you want to change:

astro.config.mjs
import { defineConfig } from 'astro/config';
import caret from '@caretcms/core';
export default defineConfig({
integrations: [
caret({
theme: {
tokens: {
'--color-theme-accent': '#9333ea',
'--font-theme-body': '"IBM Plex Sans", system-ui, sans-serif',
},
},
}),
],
});

Tokens cascade on top of the studio defaults — anything you don’t set keeps its default value.

/* Surface */
--color-theme-bg-deep
--color-theme-surface
--color-theme-surface-elevated
--color-theme-surface-muted
/* Border */
--color-theme-border-subtle
--color-theme-border
/* Accent */
--color-theme-accent
--color-theme-accent-soft
--color-theme-accent-strong
--color-theme-on-accent
/* Text */
--color-theme-text
--color-theme-text-muted
--color-theme-text-dim
/* State */
--color-theme-success
--color-theme-danger
--color-theme-info
--color-theme-warning
/* Type */
--font-theme-body
--font-theme-heading

The full default values live in packages/core/src/runtime/themes/preset-tokens.ts.

Brand identity is separate from chrome tokens:

caret({
brand: {
name: 'Acme Studio',
logo: '/logo.svg',
faviconUrl: '/favicon.ico',
},
})

This shows up in the studio header and the login screen.

The look of your site (not the admin UI) lives in your Astro project’s components, CSS, and content. Core has no opinion about it.

Start from the public repository’s examples/starter or examples/content-site, then adapt its components and styles. The core package does not include an installable portfolio or blog site theme.

Choose the bundled English (en) or Spanish (es) dictionary and override individual messages where your editorial terminology differs:

caret({
locale: 'es',
dictionary: {
'nav.studio': 'Mi contenido',
'collection.searchPlaceholder': 'Buscar contenido…',
},
});

These settings translate supported Studio messages, not your site’s content. The exported StudioDictionary and StudioMessageKey types describe supported keys. They do not provide a multilingual content model or translate entries.