Artifacts Platform
Agent DocsAppschatgpt-app

Theming

CSS variable system matching ChatGPT's design palette for artifact rendering

ChatGPT Theme System

CSS variable system that matches ChatGPT's design system palette for artifact rendering.

Table of Contents


Overview

Artifacts in ChatGPT must match the platform's visual design system. The theme system provides CSS variables scoped to artifact containers using the data-artifact-container-chatgpt attribute.

Architecture:

  • Theme file: app/artifact/artifact-theme.css - Defines ChatGPT palette via CSS variables
  • Scope selector: [data-artifact-container-chatgpt] - Scopes variables to artifact containers
  • Theme detection: useTheme() hook applies dark class to <body> element
  • CSS cascading: .dark [data-artifact-container-chatgpt] overrides for dark mode

Key constraint: Variables are scoped to containers with data-artifact-container-chatgpt attribute. Components outside this scope use default browser/system colors.

CSS Variable Palette

All variables are defined under [data-artifact-container-chatgpt] selector.

Layout & Surface:

  • --background - Primary background color
  • --foreground - Primary text color
  • --card - Card background
  • --card-foreground - Card text
  • --popover - Popover/dropdown background
  • --popover-foreground - Popover text
  • --muted - Muted background (subtle areas)
  • --muted-foreground - Muted text
  • --secondary - Secondary surface background
  • --secondary-foreground - Secondary text
  • --accent - Accent background
  • --accent-foreground - Accent text

Interactive Elements:

  • --border - Border color
  • --input - Input field background
  • --ring - Focus ring color
  • --primary - Primary button/action color
  • --primary-foreground - Text on primary
  • --destructive - Destructive action color
  • --destructive-foreground - Text on destructive

Chart Colors:

  • --chart-1 through --chart-5 - Sequential chart colors

Light mode values: White backgrounds (#ffffff), dark text (#0d0d0d), blue primary (#0285ff)

Dark mode values: Dark backgrounds (#212121, #303030, #414141), light text (#ffffff, #cdcdcd), same blue primary (#0285ff)

See app/artifact/artifact-theme.css for complete value definitions.

Implementation Pattern

Required steps:

  1. Wrap content in container with data-artifact-container-chatgpt attribute
  2. Call useTheme() hook to sync dark class with ChatGPT theme
  3. Use CSS variables in component styles (automatically scoped)

Example from ArtifactViewer:

import { useTheme } from '../hooks';

export function ArtifactViewer() {
  useTheme(); // Syncs dark class with ChatGPT theme

  return (
    <div data-artifact-container-chatgpt>
      {/* Content uses CSS variables automatically */}
      <Card className="bg-background text-foreground">
        {/* ... */}
      </Card>
    </div>
  );
}

Why this pattern:

  • Scoped variables prevent theme leakage to non-artifact content
  • data-artifact-container-chatgpt clearly marks artifact boundaries
  • useTheme() ensures theme stays in sync with ChatGPT's preference
  • CSS variables enable automatic dark/light mode switching

Important: useTheme() applies dark class to <body>, not <html>, to avoid Next.js attribute stripping.

Integration Points

Theme file location: app/artifact/artifact-theme.css

Import chain:

  1. app/globals.css imports @chatgpt-artifacts/chatgpt-app/artifact-theme.css
  2. Package exports defined in package.json under "./artifact-theme.css"
  3. Styles available globally via CSS import, variables scoped by attribute selector

Hook integration:

  • app/hooks/use-theme.ts - Subscribes to ChatGPT theme via useOpenAIGlobal('theme')
  • Applies dark class to document.body when theme is 'dark'
  • Component calls useTheme() to trigger synchronization

Component usage:

  • app/artifact/artifact-viewer.tsx - Wraps all content in data-artifact-container-chatgpt divs
  • All artifact widgets must follow this pattern for theme consistency

Storybook Alignment

Storybook previews sync ChatGPT theme CSS to match production behavior.

Sync mechanism:

  1. apps/storybook/src/styles.css imports @chatgpt-artifacts/chatgpt-app/artifact-theme.css
  2. ChatGPTPreview component's syncWidgetStyles callback mirrors all styles from Storybook document to widget iframe
  3. Copies <style> and <link rel="stylesheet"> elements into widget iframe head
  4. Mirrored styles tagged with data-chatgpt-mirror="true" for cleanup on updates

Result: Storybook previews use identical CSS variables as production, ensuring visual parity.

See apps/storybook/.agents/docs/chatgpt-preview-system.md for Storybook preview architecture details.

Color Source

CSS variable values match ChatGPT Apps SDK design guidelines:

  • Light mode: White backgrounds, dark text (#0d0d0d), ChatGPT blue (#0285ff)
  • Dark mode: Dark gray backgrounds (#212121), light text, same blue accents

Values intentionally align with platform design system for visual consistency across all ChatGPT widgets.

Upstream reference:

ChatGPT Apps SDK Design Guidelines Contains: Official color system specification (light/dark mode values), typography, spacing, component design patterns Read when: Verifying color values, understanding design system rationale, or implementing new visual components

On this page