Creator guide · 3 of 3
Design a VibeFuse styling pack — theme.json, orb.json, and shell effects
A styling pack reskins the whole VibeFuse desktop shell without touching agent logic: background layers, panels, accent, text, strokes, the terminal palette, canvas particles, border and overlay effects, and the voice-dock orb. It is three JSON files in a folder under C:\vibefuse\styling. This guide builds a complete pack called Midnight Ember, renders it live below with the same engine the marketplace uses, and takes it through publish.
What a pack controls
- theme.json
- Color tokens, terminal ANSI palette, shell particles, border / overlay effects, optional CSS
- orb.json
- Voice-dock orb colors (style) and motion (animation)
- manifest.json
- Identity, swatches for the catalog card, default accent
- Applies to
- Menubar, sidebar, canvas, session tabs, settings, widget chrome, voice dock
Users pick a pack in Settings → Appearance → Styling packs, next to the nine built-in themes. Choosing a built-in theme turns the pack off; choosing the pack turns it back on. Marketplace saves sync into the styling folder on next launch.
Settings → Appearance: built-in themes, styling packs, accent
Dark Snow — a shipped pack, tokens from its theme.json
Prerequisites
- VibeFuse for Windows signed in with your
VF-key. - A text editor and a color tool you like. Hex and
rgba()are all you need. - A direction in one sentence (“deep navy, ember accents, warm orb”). Packs with a point of view sell; “default but blue” does not.
- To sell (optional): seller profile + Stripe Connect.
C:\vibefuse\styling, rename it, change the id, and edit colors from there.Package anatomy
All three files are required at publish time. The folder name becomes the local package slug (the marketplace prefixes it with style-).
| Rule | Detail |
|---|---|
| Allowed file types | json, css, svg, md, txt (html/js are accepted by the uploader but the shell reads JSON only) |
| Size limits | 750 KB per file · ~2.5 MB per package |
| Images | Not part of the package. Card / banner / screenshots are uploaded on the listing page. |
Step 1 — manifest.json
{
"id": "com.yourname.styling.midnight-ember",
"name": "Midnight Ember",
"version": "1.0.0",
"description": "Deep navy workspace with ember-orange accents, drifting embers on the canvas, a soft glow border, and a warm frosted orb.",
"author": "Your Name",
"license": "MIT",
"icon": "palette",
"category": "styling",
"kind": "marketplace",
"entry": "theme.json",
"tags": ["appearance", "orb", "dark", "warm"],
"swatches": ["#070a12", "#111827", "#ff7a3d"],
"defaultAccent": "#ff7a3d",
"light": false
}
| Field | Required | What it does |
|---|---|---|
id | Yes | Unique, reverse-DNS. Convention: com.yourname.styling.<slug>. 3–128 chars of letters, numbers, . _ -. Never change after launch. |
name | Yes | Shown on the Appearance card, catalog, and listing. |
version | No | Semver, default 1.0.0. Bump per release. |
description | No | One or two sentences. Appears on the Appearance card and catalog. |
icon | No | Default palette. |
entry | No | Default theme.json; the file must exist. |
swatches | No | 3–5 hex colors shown on cards and the listing hero. Pick background, surface, accent. |
defaultAccent | No | Fallback accent when --accent is missing from tokens. |
light | No | true for light-background packs. Flags the pack as a light theme in the catalog. |
category / kind | No | Normalized to styling / marketplace on publish. |
Step 2 — theme.json: tokens
Tokens are CSS custom properties applied to the shell root while the pack is active. Every built-in surface reads from these names, so a consistent set here restyles everything at once. The full example:
{
"defaultAccent": "#ff7a3d",
"light": false,
"tokens": {
"--bg-0": "#070a12",
"--bg-1": "#0b1020",
"--bg-2": "#111827",
"--surface": "rgba(14, 20, 36, 0.72)",
"--surface-strong": "rgba(9, 13, 24, 0.94)",
"--panel": "rgba(14, 20, 36, 0.7)",
"--panel-strong": "rgba(8, 11, 20, 0.9)",
"--chrome-bg": "rgba(8, 11, 20, 0.88)",
"--overlay-bg": "rgba(5, 7, 14, 0.68)",
"--input-bg": "rgba(255, 122, 61, 0.05)",
"--accent": "#ff7a3d",
"--accent-2": "#ffa46b",
"--accent-deep": "#b8451a",
"--accent-rgb": "255, 122, 61",
"--gold": "#f2b866",
"--gold-rgb": "242, 184, 102",
"--purple": "#6b7bd6",
"--violet": "#8b7bd6",
"--text": "#f4f1ec",
"--text-dim": "#a8a49c",
"--text-faint": "#6b6862",
"--stroke": "rgba(255, 122, 61, 0.14)",
"--stroke-strong": "rgba(255, 122, 61, 0.32)",
"--glow": "rgba(255, 122, 61, 0.22)",
"--shadow": "0 22px 60px rgba(0, 0, 0, 0.6)",
"--ambient-a": "#2a1a12",
"--ambient-b": "#070a12",
"--ambient-opacity": "0.18",
"--ambient-vignette": "rgba(0, 0, 0, 0.7)",
"--ok": "#7fe2a2",
"--warn": "#f2b866",
"--danger": "#ff6b7a",
"--danger-rgb": "255, 107, 122",
"--orb-spin": "1.05",
"--orb-breathe": "2.6",
"--orb-ring-ms": "2.6s"
},
"terminal": {
"background": "#0b1020",
"foreground": "#f4f1ec",
"cursor": "#ff7a3d",
"cursorAccent": "#070a12",
"selectionBackground": "rgba(255, 122, 61, 0.3)",
"black": "#070a12",
"red": "#ff6b7a",
"green": "#7fe2a2",
"yellow": "#f2b866",
"blue": "#6b9bd6",
"magenta": "#c58bd6",
"cyan": "#7ad0d6",
"white": "#f4f1ec"
},
"shell": {
"particles": {
"canvas": { "preset": "embers", "count": 26, "speed": 0.8, "size": 1.3, "opacity": 0.55, "direction": "up", "color": "#ff9a5c" },
"sidebar": "none",
"stage": "none"
},
"effects": {
"border": "glow",
"overlay": "film-grain"
},
"customCss": ".widget-window { box-shadow: 0 0 0 1px rgba(255,122,61,0.18), 0 18px 48px rgba(0,0,0,0.55); }"
}
}
Token reference
| Token | Controls | Tip |
|---|---|---|
--bg-0 --bg-1 --bg-2 | Background layers: window base, canvas, elevated regions | Three steps of the same hue, each 4–8% lighter |
--surface --surface-strong | Widget bodies, cards (translucent → opaque) | Use rgba() at 0.7 / 0.94 so particles show through |
--panel --panel-strong --chrome-bg | Sidebar, menubar, settings panels, widget title bars | Slightly darker than surface |
--overlay-bg --input-bg | Modal backdrops, text inputs | Input tinted with accent at 5% alpha reads as “themed” |
--accent --accent-2 --accent-deep --accent-rgb | Buttons, focus rings, active tabs, links; lighter and darker variants; r, g, b for alpha math | Keep --accent-rgb in sync with --accent |
--gold --gold-rgb --purple --violet | Secondary highlights used by badges, ranks, and some widgets | Can equal the accent for a monochrome pack |
--text --text-dim --text-faint | Primary, secondary, disabled text | Check contrast on --surface: aim ≥ 7:1 for --text |
--stroke --stroke-strong | Borders and dividers | Accent-tinted at 14% / 32% alpha is the house style |
--glow --shadow | Focus glow, elevated shadows | Accent at ~22% alpha for glow |
--ambient-a --ambient-b --ambient-opacity --ambient-vignette | Slow ambient gradient behind the canvas and its edge vignette | Opacity 0.12–0.2; more is distracting |
--ok --warn --danger --danger-rgb | Status colors | Keep green/amber/red recognizable |
--orb-spin --orb-breathe --orb-ring-ms | Orb motion defaults when orb.json omits them | Usually mirrored in orb.json → animation |
Unknown tokens are passed through, so you may add your own (--my-pack-stripe) and reference them from shell.customCss. The marketplace preview reads --bg-*, --surface*, --accent*, --text*, --stroke*, --gold, and --panel to paint its stages.
Step 3 — Terminal palette
The terminal object themes every PTY widget (Terminal, Claude, Codex, Gemini, Cursor, Qwen). Keys follow the xterm.js theme convention.
"terminal": {
"background": "#0b1020",
"foreground": "#f4f1ec",
"cursor": "#ff7a3d",
"cursorAccent": "#070a12",
"selectionBackground": "rgba(255, 122, 61, 0.3)",
"black": "#070a12", "red": "#ff6b7a", "green": "#7fe2a2", "yellow": "#f2b866",
"blue": "#6b9bd6", "magenta": "#c58bd6", "cyan": "#7ad0d6", "white": "#f4f1ec"
}
- Match
backgroundto--bg-1so terminals sit flush with the canvas. - Keep the eight ANSI colors distinguishable — agents print a lot of green/yellow/red diffs.
brightBlack…brightWhiteare optional; omit them to derive from the base eight.
Step 4 — Shell effects & particles
The shell object adds motion and atmosphere. Everything here is optional — a pack can be tokens only.
"shell": {
"particles": {
"canvas": { "preset": "embers", "count": 26, "speed": 0.8, "size": 1.3, "opacity": 0.55, "direction": "up", "color": "#ff9a5c" },
"sidebar": "none",
"stage": "snow"
},
"effects": {
"border": "glow",
"overlay": "film-grain"
},
"customCss": ".widget-window { box-shadow: 0 0 0 1px rgba(255,122,61,0.18), 0 18px 48px rgba(0,0,0,0.55); }",
"customJs": ""
}
Particles
Three regions — canvas (behind widgets), sidebar (left rail), stage (full window). Each takes a preset name string or an object:
| Key | Default | Meaning |
|---|---|---|
preset | — | snow · rain · embers · fireflies · dust · stars · bubbles · confetti · petals · matrix · aurora · mist · spark · geometric · lightning · none |
count | 28 | Number of particles. 16–40 is the comfortable range. |
speed | 1 | Multiplier. 0.6 is calm, 1.5 is lively. |
size | 1.2 | Multiplier on the preset's base size. |
opacity | 0.5 | 0–1. |
direction | down | down, up, left, right. |
color | preset default | Any CSS color. Leave blank to use the preset's own tint. |
enabled | true | Set false to ship a region switched off but configured. |
Effects
| Key | Values | Where it shows |
|---|---|---|
border | glow · neon · pulse · rainbow · scan · shimmer · none | Animated edge on widget windows and the shell frame |
overlay | film-grain · scanlines · crt · vignette-pulse · aurora-veil · none | Full-window atmosphere layer above the canvas |
Custom CSS / JS
customCssis injected while the pack is active. Target shell classes such as.widget-window; prefer adjusting shadows, radii, and borders over layout.customJsruns in the shell while active. Keep it tiny and idempotent (it may run more than once). Anything that reaches the network or the file system is grounds for removal.- Both are listed on the marketplace page as “Custom shell CSS / JS” so buyers know they exist.
Reduce-motion users: VibeFuse's Reduce motion switch slows or stops particles and effects. Your pack should still look complete with them off — that is why tokens do the heavy lifting.
Step 5 — orb.json
The orb is the voice-dock indicator (idle, listening, speaking) and shows in the status bar. style paints it; animation moves it.
{
"style": {
"id": "ember-core",
"label": "Ember Core",
"preset": "frost",
"coreTop": "#fff1e6",
"coreMid": "#ff7a3d",
"coreDeep": "#5a2410",
"rim": "#ffa46b",
"frost": "rgba(255, 200, 160, 0.5)",
"glyph": "#1a0c06",
"chrome": "#ffa46b"
},
"animation": {
"id": "ember-drift",
"label": "Ember Drift",
"preset": "particles",
"particleRgb": "255, 154, 92",
"particleCount": 22,
"particleSize": 1.4,
"spin": 1.05,
"breathe": 2.6,
"ringMs": 2.6
}
}
| Key | Meaning |
|---|---|
style.preset | classic (solid gradient core) or frost (translucent frosted core with a visible rim). |
style.coreTop / coreMid / coreDeep | Three-stop radial gradient from highlight to depth. |
style.rim | Edge ring color; usually your accent or accent-2. |
style.frost | Semi-transparent haze over the core (frost preset). |
style.glyph | Color of the center glyph / microphone mark — dark on light cores, light on dark cores. |
style.chrome | Tint for the pill and ring chrome around the orb. |
animation.preset | classic (breathe + rings) or particles (adds orbiting particles). |
animation.particleRgb / particleCount / particleSize | Particle tint as r, g, b, count (8–28), size multiplier. |
animation.spin / breathe / ringMs | Rotation speed multiplier, breathe period in seconds, ring pulse period in seconds. |
id / label | Free text shown on the listing (“Ember Core”, “Ember Drift”). |
Orb activity pill in the shell status bar
Rendered preview — Midnight Ember, from the JSON above
This block is generated from the three example files on this page by the same code that renders marketplace styling pages. Change a token, republish, and this is what buyers see.
Midnight Ember
Deep navy workspace with ember-orange accents, drifting embers on the canvas, a soft glow border, and a warm frosted orb.
Desktop shell
Workspace preview
Menubar, sidebar, canvas, and voice dock tinted with this pack's tokens.
Compare with live packs: Jarvis-Pro (violet, frost orb, particles) · Dark Snow (monochrome, snow particles) · LSU Death Valley (two-color brand pack).
Design guidance
Color
- One hue family for backgrounds, one accent, one secondary. That is the whole palette.
- Derive strokes, glow, input tints from
--accent-rgbat low alpha — cohesive for free. - Test
--text-dimon--panel: it is the most-read color in the app. - Light packs: set
"light": true, invert the bg ladder (bg-0 lightest), and darken the accent for contrast.
Motion
- One particle region is plenty. Canvas particles behind translucent widgets is the classic look.
- Slow beats fast: speed 0.6–0.9, opacity ≤ 0.6, count ≤ 30 for an all-day workspace.
- Pick either a border effect or an overlay for subtle packs; both for showpieces.
- Match orb
breatheto your ambient feel — 2.4s energetic, 3.2s calm.
Built-in theme cards your pack sits beside in Settings → Appearance
Step 6 — Test locally
-
01
Create the folder
C:\vibefuse\styling\Midnight-Ember\withmanifest.json,theme.json,orb.json. The folder is listed in Settings → Marketplace → Local styling packs (use Reveal folder). -
02
Apply it
Open Settings → Appearance. The pack appears under Styling packs with your swatches. Click it — the shell recolors immediately.
-
03
Load a busy canvas
Open a Terminal, a Claude or Codex widget, a Browser, and the Vibe Agent. Run a command with colored output. Open Settings and a modal. This is what buyers will stare at for hours.
-
04
Check the orb
Hold to talk or trigger Jarvis — watch idle, listening, and speaking states. Adjust
rim/frostif the glyph disappears. -
05
Iterate
Edit the JSON, then re-select the pack (or toggle to a built-in theme and back) to reload tokens. Fix contrast before you touch particles.
-
06
Test Reduce motion
Toggle it in Appearance. Tokens alone should still read as a finished theme.
Step 7 — Publish from Settings → Marketplace
-
01
Confirm your license is linked
The tab header shows your seller profile with an active
VF-key. Otherwise copy one from Account → Product Keys. -
02
Find the pack under Local styling packs
Each folder in
C:\vibefuse\stylingshows as a card with Not on marketplace, Uploaded · unpublished, or Live on marketplace. -
03
List on marketplace
VibeFuse validates
id+name, requirestheme.jsonandorb.json, checks file types and sizes, then uploads. Your profile name is stamped as author and the package slug gets astyle-prefix. -
04
Publish
Click Publish on the card (or Publish all). The listing goes live at
/marketplace/styling/style-<slug>and appears under Styling on the marketplace.
Settings → Marketplace → Local styling packs
Step 8 — The listing page
Your pack page is generated from the JSON, so most of the work is already done. It shows:
- Hero — name, description, version, saves, swatches, orb preview, and a widget window painted with your tokens
- Pack breakdown — token count, particle regions, effects, orb style / motion, custom CSS / JS flags
- Workspace preview — menubar, sidebar, canvas with your particles, two widgets, status bar with the mini orb
- Showcase stages — terminal palette, orb, particles, border effect, overlay, background ladder
- About + creator card — your description, avatar, follower count
Add a card image and banner in Account → Marketplace if you want a photo-real screenshot on the catalog card; otherwise the swatches carry it.
Step 9 — Ship an update
- Edit tokens, bump
versioninmanifest.json, then Update listing on the card. Sameid→ same listing; saves carry over. - Users pick up the new files on their next launch sync and see them the next time the pack is applied.
- Unpublish hides the page; installed copies keep working.
Pre-publish checklist
manifest.jsonhas a uniquecom.yourname.styling.*id, name, description, 3–5 swatches,defaultAccenttheme.jsondefines the full bg / surface / panel ladder, accent set with--accent-rgb, text trio, strokes, status colorsterminal.backgroundmatches--bg-1; ANSI colors distinguishableorb.jsonhas bothstyleandanimation; glyph visible on the core- Particles ≤ 30 count, opacity ≤ 0.6; at most one overlay
- Contrast checked on a busy canvas and with Reduce motion on
customJsempty or reviewed line by line; no network, no storage- All three files are valid JSON (no trailing commas, no comments)
Troubleshooting
| Symptom | Fix |
|---|---|
| Pack not in Settings → Appearance | Folder must be directly inside C:\vibefuse\styling with a valid manifest.json. Validate the JSON — a trailing comma silently drops the pack. |
| “Pack must include theme.json / orb.json” | Both files are required at publish. Names are exact and lowercase. |
| Colors apply but look like the default theme | Tokens must start with -- and live under "tokens". Check for typos such as --acccent. |
| Orb is a grey ball | orb.json is missing or style keys are misspelled. coreMid falls back to the accent; coreDeep to #222. |
| Particles do not show | Region key must be canvas, sidebar, or stage; preset must be one of the listed names; enabled not false; Reduce motion off. |
| Terminal text unreadable | Set terminal.foreground and background explicitly; do not rely on defaults when your bg ladder is unusual. |
| “already listed by another creator” | Change your id to your own namespace. |
FAQ
Can I ship a light theme?
Yes. Set "light": true in both manifest and theme, make --bg-0 the lightest layer, use dark text tokens, and darken the accent to keep button text readable.
Do packs change my widgets' content?
No. A pack themes the shell chrome around widgets. Marketplace iframe widgets keep their own interior styling; built-in widgets (terminal, settings) follow the tokens.
Can one pack contain multiple themes?
One pack = one theme today. Publish variants as separate packs (Midnight Ember, Midnight Ember Light) and cross-link them in the descriptions.
Can I include a wallpaper image?
Binary files are not packaged. Use CSS gradients via tokens (--ambient-a/b) or a data-URI SVG in customCss.
Will my pack break on VibeFuse updates?
Token names are stable; new surfaces read existing tokens. Only customCss that targets internal class names may need a touch-up — keep it minimal.
Next guides
Related: Settings → Appearance · Styling catalog · Styling pack creator overview