Skip to content

Themes overview

Themes change Carbon itself: colors, glass surfaces, the Windows backdrop (Mica), optional sidebar icons, and optional live canvas / WebGL behind the UI. They do not patch Roblox client files. For in-game assets, use mods.

Built-in themes ship in project/frontend/core/src/themes/. Community themes install as folders under Skeleton/Themes/<theme-id>/. The folder name is the theme id. Carbon discovers disk themes at startup and lists them next to built-ins in Settings → Appearance.

  1. Discover: Built-in themes are bundled with the app. The backend scans Skeleton/Themes/* for theme.yaml or manifest.json.
  2. Select: You pick a theme in Settings. The choice is persisted (AppSettings style id + local storage fallback).
  3. Load stylesheet: Carbon injects compiled CSS into #carbon-custom-theme on :root (data-theme on <html>).
  4. Backdrop: On Windows (Tauri), configuration.backdrop drives Mica / acrylic unless a backdrop-layer JS theme is active (then Mica is skipped so your canvas shows through).
  5. Optional JavaScript: If javascript.enabled, the host validates dist/theme.js, mounts a sandboxed iframe, and runs CarbonTheme.mount(function (ctx) { … }).
  6. Switch / teardown: Changing themes sends destroy, removes the iframe, and applies the next token pack.
Shape What you ship Examples
Token pack SCSS or CSS that sets --crbn-* on :root Carbon Dark, Polaris, Neon District
Token pack + icons Stylesheet + icons/*.svg overrides Carbon Light
Token pack + JS Stylesheet + bundled javascript.entry Frosted, Slipstream, Deep Lattice

JavaScript is optional. Most themes are stylesheet-only.

Carbon’s UI reads design tokens (--crbn-bg, --crbn-primary, …), not utility class names from your theme file.

Format Supported at load time Notes
.scss / .sass Yes Disk themes: Dart Sass compiles the single configuration.source entry when loaded. Repo built-ins compile via Vite (partials and @use work there).
.css Yes Loaded as-is. Good for output from your own build pipeline.
Tailwind CSS Not at load time Carbon does not run PostCSS or Tailwind when applying a theme. Use Tailwind (or any tool) while authoring to emit plain .css (usually :root { --crbn-*: … }) and point configuration.source at that file. Do not put @tailwind directives in a file you expect Carbon to compile with Sass only, they will not expand.

SCSS is the usual choice in the repo: variables, nesting, and shared color math in one my-theme.scss. For disk themes with many partials, either keep one entry file or precompile SCSS/Tailwind to dist/theme.css in your package script (same idea as bundling dist/theme.js).

Interactive themes run in an iframe (sandbox="allow-scripts", strict CSP). You get ctx.canvas (2D), ctx.root (extra DOM / WebGL canvas), ctx.tokens, host events (init, resize, pause, …), and a 256 KB cap on the bundle. WebGL works by creating a canvas on ctx.root (see Deep Lattice in the repo).

Backdrop vs in front of the UI (“frontdrop”)

Section titled “Backdrop vs in front of the UI (“frontdrop”)”

Carbon does not use a manifest value named frontdrop. You choose where the iframe draws with javascript.layer:

layer Where it draws Typical use
backdrop (default) Behind the Carbon shell (z-index: 0) Particles, aurora, WebGL void behind glass panels
overlay In front of the shell (z-index: 9000) Full-screen effects, vignettes, or visuals on top of the UI
javascript:
enabled: true
entry: dist/theme.js
layer: overlay # “frontdrop”: manifest keyword is overlay, not frontdrop

Mica / window backdrop: when layer is backdrop, Carbon skips Windows Mica so your canvas is visible. When layer is overlay, configuration.backdrop (Mica, acrylic, etc.) can still apply behind everything.

The iframe stays pointer-events: none by default so clicks reach the app. Optional javascript.interactive: true (read by the desktop frontend) forwards pointer events to your theme via host app events, useful for overlay experiments; most shipped themes leave it off.

Details: Authoring and Manifest reference.

Themes Mods
Target Carbon desktop shell Roblox client content
Manifest theme.yaml / manifest.json mod.yaml
Install path Skeleton/Themes/<id>/ User mods folder (app UI)
Animation Optional sandboxed JS / WebGL N/A

UI texture packs such as ingame-menu-pack are mods, not themes.

Every item under Themes in the docs sidebar has a dedicated page:

Sidebar label Page Contents
Overview Themes Lifecycle, SCSS/Tailwind, JS layers, mods vs themes
Authoring Authoring Folders, SCSS/Tailwind build, JS/WebGL, Bun bundles
Engine architecture Architecture Backend discovery, iframe host, bridge, lifecycle
theme.yaml reference Reference Manifest fields, ctx API, guard rules, tokens
Built-in themes Built-in Shipped themes in the repo