Theme marketplaceAuthoring guide

🎨 Theme authoring guide

Learn the ForcedSkin theme JSON schema and palette field rules—design palettes for any site and submit them for the community.

Quick start

Choose a mode

Decide whether the theme runs in light (light palettes) or dark (dark palettes).

Fill in colors

Follow the field specification below — at minimum all required keys must be present in your JSON.

Submit for review

On the Themes page click “Submit Theme”. Admins approve before it appears for everyone.

Color fields

All palette entries must be hex (#RRGGBB) strings or CSS rgba(...) values.

backgroundRequired

Primary page background-light themes lean near white, dark themes near deep neutrals. CSS var: --color-background

Example: #F8FFF8 / #101410

foregroundRequired

Primary text-readably contrasted against background. CSS var: --color-foreground

Example: #2C3E2C / #E0E0E0

surfaceRequired

Card/panel/container fill-slightly lifted from background. CSS var: --color-surface

Example: #F0FFF0 / #1E221E

surfaceMutedOptional

Muted hovers/sub-containers stepped from surface. CSS var: --color-surface-muted

Example: #F5FDF5 / #161816

borderRequired

Hairlines & dividers-typically low saturation grays/semi-transparent tones. CSS var: --color-border

Example: #D8E8D8 / #333633

mutedRequired

De-emphasized copy & placeholders. CSS var: --color-muted

Example: #6C7E6C / #A0A0A0

primaryRequired

Primary brand ramp for buttons/links/focus-can be single color or ramp (50–950). Requires at least shades 500/600/700. Maps to CSS variables --color-primary- plus shade tokens (50–950)

Example: { "500": "#4CAF50", "600": "#43A047", "700": "#388E3C" }

secondaryOptional

Secondary accent ramps for chips/ghost buttons-structure matches primary-maps to --color-secondary- plus shade tokens

Example: { "500": "#AAA", ... }

accentOptional

Highlights,badges,spotlight colors-structure matches primary-maps to --color-accent- plus shade tokens

Example: { "500": "#FFEB3B", ... }

varsOptional

Arbitrary CSS custom properties-keys omit “--”; values applied verbatim on :root

Example: { "custom-radius": "8px" }

Color ramps

The JSON keys primary, secondary, and accent each accept either authoring style below:

Compact (three core shades)

{
  "primary": {
    "500": "#4CAF50",
    "600": "#43A047",
    "700": "#388E3C"
  }
}

The engine promotes shade 500 as the default hue; 600/700 cover hover/active affordances.

Full ramp (50 → 950, eleven stops)

{
  "primary": {
    "50":  "#E8F5E9",
    "100": "#C8E6C9",
    ...
    "500": "#4CAF50",
    ...
    "950": "#0F3D12"
  }
}

Publishing the complete ramp yields smoother tonal transitions everywhere.

Tip: Shade IDs follow Tailwind-style ramps: 50 is lightest, 950 is darkest. Light themes mainly use 500/600/700; dark themes often lean on 400/500/600.

Full samples

🌿 Light sample (light-mint)

{
  "background": "#F8FFF8",
  "foreground": "#2C3E2C",
  "surface": "#F0FFF0",
  "surfaceMuted": "#F5FDF5",
  "border": "#D8E8D8",
  "muted": "#6C7E6C",
  "primary": {
    "50": "#E8F5E9",
    "100": "#C8E6C9",
    "200": "#A5D6A7",
    "300": "#81C784",
    "400": "#66BB6A",
    "500": "#4CAF50",
    "600": "#43A047",
    "700": "#388E3C",
    "800": "#2E7D32",
    "900": "#1B5E20",
    "950": "#0F3D12"
  },
  "secondary": {
    "500": "#AAAAAA",
    "600": "#999999",
    "700": "#777777"
  },
  "accent": {
    "500": "#FFEB3B",
    "600": "#FDD835",
    "700": "#FBC02D"
  }
}

🌑 Dark sample (dark-forest)

{
  "background": "#101410",
  "foreground": "#E0E0E0",
  "surface": "#1E221E",
  "surfaceMuted": "#161816",
  "border": "#333633",
  "muted": "#A0A0A0",
  "primary": {
    "500": "#4A9B6B",
    "600": "#3F855C",
    "700": "#346F4D"
  }
}

Custom variables (vars)

If default tokens fall short, add extra CSS vars under a vars node—omit the -- prefix in each key.

{
  "background": "#101010",
  "foreground": "#E0E0E0",
  ...
  "vars": {
    "radius-card": "16px",
    "shadow-card": "0 2px 12px rgba(0,0,0,0.4)"
  }
}

Slug rules (name)

  • Only lowercase ASCII letters, digits, and hyphen ( a-z 0-9 - ).
  • Prefer concise “mode-style” pairs such as “dark-ocean” or “light-sakura”.
  • Slugs must be globally unique—they cannot change after publishing, so double-check beforehand.
  • Maximum length 50 characters.

Submission & review

🔐 Sign in before submitting.

⏳ Submissions queue for review-staff typically respond within 1-3 working days.

✅ Approved themes appear in the marketplace for everyone to favorite.

❌ Invalid colors, conflicting names, or policy breaches will be rejected-delete and submit a corrected version.

🚫 No malicious code, hate content, or obviously infringing palettes.

Ready? Head to the theme marketplace and publish your palette.

🎨 Submit a theme