Core Understanding
The essence of a MusicFree theme package is a CSS Custom Properties override layer。
The app includes a default dark theme (defined in global.scss within :root , with about 150+ CSS variables). Theme packages selectively override these variables via index.css in :root {} to achieve skinning. Variables that are not overridden automatically inherit the default dark values.
Code of Conduct
The following rules apply throughout the entire theme development processat all times:
- Visual output cannot be previewed: AI cannot see the actual rendered effect of the theme, so every important decision must be confirmed with the user. Do not judge on your own what "looks good"
- Confirm before acting: Key decisions such as the color palette, variable override scope, and background style must be clearly described and approved by the user before generating code
- Explain technical terms: The user may be a community contributor with zero foundation, so all technical concepts must be explained in plain language
- Minimal override principle: Only override the CSS variables that need to change. Do not override all variables for the sake of "completeness"
- Exception for light themes: Light themes must override all Background / Fill / Text / Border category variables, otherwise dark remnants will appear
- Asset size first: Images must be compressed (WebP recommended); avoid unnecessary large files
Roles and Collaboration Mode
- AI (you): Provide color scheme suggestions, write CSS/HTML code, generate config.json, package the theme
- User: Provide creative direction, choose options, install and test the theme, provide visual feedback
Difference from plugin-dev
A theme package is avisual output, unlike plugins, which can be verified for correctness through test scripts. Therefore this Skill adopts the "AI suggests → user judges → iterate and fine-tune" loop mode, rather than plugin-dev's "AI-led" mode. Expect 2-3 rounds of iteration.
Principles for Interacting with the User
- Provide 2-3 options each time, letting the user choose or mix them
- When describing colors, give both the color value and an intuitive description (e.g., "rgb(52, 211, 153) — emerald green, similar to Spotify's green")
- When user action is needed, giveprecise step-by-step instructions
- When unsure of the user's intent, ask first, then act
Workflow
1. 需求采集 → 2. 风格定调 → 3. 调色板生成 → 4. CSS 变量映射
→ 5. 增强层(可选) → 6. 打包与测试 → 7. 迭代优化
→ 8.(可选)提交到主题市场
Phase 1: Requirements Gathering
Collect the following information (ask for it all at once; do not ask in multiple fragmented rounds):
Must collect:
- Theme name
- Basic direction: dark / light / AMOLED pure black / other
- The user's creative intent (any of the following forms is fine):
- Mood/atmosphere keywords (such as "warm", "cyberpunk", "fresh and natural")
- Reference color value (e.g. "I want a pink palette")
- Reference app/website (e.g. "Spotify-like dark green")
- Reference image (user directly pastes an image)
- Fully custom detailed description
Optional collection:
- Author name
- Description
- Whether a dynamic iframe background is needed
- Whether there are custom image assets (such as background images, preview images)
Stage 2: Style Direction
Based on user input, provide 2-3 style directionsas text descriptions (no code is written at this stage).
Each direction includes:
- Brand color value + intuitive description
- Light/dark tone
- Atmosphere keywords
- Background style (solid color / gradient / image / dynamic)
The user chooses one direction, or mixes elements from multiple directions.
If the user is already very clear — for example, they directly provided color values or a complete description, this stage can be skipped and you can go directly to Stage 3.
Stage 3: Palette Generation
Based on the selected direction, derive the complete palette. Refer to the color paradigms in references/color-paradigms.md .
Show the derivation results to the user, grouped by category:
- Brand color (brand)
- Background color hierarchy (base → sidebar → player → surface → ...)
- Text color hierarchy (primary → secondary → muted → ...)
- Border color hierarchy
- Status colors (if customization is needed)
Wait for user confirmation before proceeding to the next stage.
Stage 4: CSS Variable Mapping
Map the confirmed palette to MusicFree's semantic CSS variables.
Refer to references/css-variable-reference.md for the complete variable list and override rules.
Three-level classification of variable overrides:
| Category | Description |
|---|---|
| Must override | Variables that define the theme's core visual identity; not overriding them is equivalent to not changing the skin at all |
| Recommended to override | The theme is only complete after overriding; if a light theme does not override them, dark remnants will appear |
| Must not override | Structural tokens (z-index / typography / spacing / layout / control sizes / icon sizes / motion); changing them will break layout or functionality |
Special categories:
- Shadow / Blur: Stylistic token. Flat/AMOLED themes can set it to
none; glassmorphism themes can increase the blur value - Radius: Not overridden by default. It may only be adjusted when the user explicitly requests an extreme style (such as pure angular cyberpunk), and the user must be informed that this may cause visual abnormalities in some components
- Background Image (
--bg-image): Belongs to the enhancement layer; whether to override it is determined by the theme style
Generate the index.css file, with the format referring to the built-in themes:
/*
* 主题名称
*/
:root {
/* ── Background ── */
--color-bg-base: ...;
/* ... */
/* ── Fill ── */
--color-fill-brand: ...;
/* ... */
}
Stage 5: Enhancement Layer (Optional)
Depending on the theme style, enhancement effects can optionally be added:
5a. Background gradient (--bg-image)
Use CSS radial-gradient / linear-gradient combinations. It is recommended to use color-mix(in srgb, var(--color-fill-brand) X%, transparent) to reference brand colors and avoid hardcoding.
5b. Shadow style adjustment
- Soft shadow (default): keep the default values
- Hard shadow: decrease blur-radius, increase spread
- No shadow (AMOLED/flat): set all to
none
5c. Custom image assets
If the user provides assets such as background images/preview images:
- Guide them to compress images (WebP format recommended)
- Single image ≤ 500 KB
- In CSS, reference via the
@/path (e.g.url(@/imgs/bg.webp)) @/is a path alias, which at runtime is replaced with the absolute path of the theme package directory
5d. iframe dynamic background
See references/iframe-guide.md。
Suitable scenarios: particle effects, dynamic gradient animations, etc.
Additional preparation required:
iframes/app.html: dynamic background entry file- Add to config.json
"iframe": { "app": "@/iframes/app.html" } - Recommends providing the
blurHashfield as a loading placeholder (optional but recommended)
Stage 6: Packaging and testing
See references/packaging-checklist.md。
Steps overview:
- Confirm the file structure is complete
- Generate
config.json - Check resource size
- Package as
.mftheme(ZIP format, rename the extension) - Guide the user to install and test
Installation and testing guide (tell the user):
- Open MusicFree Desktop
- Go to the "Themes" page
- Click the "Install theme package" button
- Select the generated
.mfthemefile - Click the theme card to apply
- Check whether each page displays correctly
Stage 7: Iterative optimization
Make fine adjustments based on user testing feedback. Common feedback and corresponding handling:
| User feedback | Possible cause | Adjustment direction |
|---|---|---|
| "Text in a certain area is hard to read" | Insufficient contrast between text color and background color | Increase the brightness difference between text color and background color |
| "Buttons are hard to see" | Insufficient contrast between brand fill color and on-brand text color | Adjust --color-text-on-brand |
| "Sidebar is too dark/too bright" | --color-bg-sidebar is inappropriate |
Adjust the brightness or transparency of that variable |
| "Overall it's too harsh on the eyes" | Light theme background is too white or brand color is too saturated | Reduce background brightness or brand color saturation |
| "Popups are not prominent" | overlay/modal background color is not distinct enough from the main background | Adjust --color-bg-overlay transparency |
| "Selected state is not visible" | brand-muted is too close to surface | Increase --color-fill-brand-muted transparency |
After each modification, repackage and have the user reinstall and test.
Stage 8 (optional): Submit to the theme marketplace
If the user wants to publish the theme to the MusicFree theme marketplace:
- Fork the repository: Guide the user to Fork MusicFreeThemePacks
- Switch branches: Based on the
v1/sourcebranch, create a development branch - Create a folder: Under
themes/create a theme folder- Naming rules: only letters, numbers, hyphens (
-), underscores (_)
- Naming rules: only letters, numbers, hyphens (
- Add tags: Add to config.json
tagsFields (1-5 tags, selected from the predefined list)- Do notadd the
idfield in config.json (the ID is managed automatically by the system) - Dynamic themes must include the
"动态"tag
- Do notadd the
- Local validation:
npm install npm run validate:theme your-theme-name - Submit PR: submit a Pull Request to the
v1/sourcebranch
Predefined tag list:
| key | label | Description |
|---|---|---|
dark |
Dark | Dark/dark-themed |
light |
Light | Light/bright-themed |
gradient |
Gradient | Gradient background |
minimalist |
Minimal | Minimalist style |
anime |
Anime | Anime/ACG style |
landscape |
Landscape | Natural landscape background |
illustration |
Illustration | Illustration-style background |
cyberpunk |
Cyber | Cyberpunk/tech feel |
pixel |
Pixel | Pixel style |
abstract |
Abstract | Abstract art style |
dynamic |
Dynamic | Includes animation effects (required if there is an iframe) |
cute |
Cute | Cute/moe style |
game |
Game | Game-related |
movie |
Film/TV | Movie/animated film-related |
season |
Season | Season-related |
nature |
Nature | Natural elements such as flowers, cherry blossoms, starry skies, etc. |
Theme package file structure
my-theme/
├── config.json # 必须 — 主题元信息
├── index.css # 必须 — CSS 变量覆盖
├── imgs/ # 可选 — 图片资源
│ ├── preview.webp # 预览图(推荐 WebP)
│ └── ...
└── iframes/ # 仅动态主题需要
├── app.html # 动态背景入口
└── ...
config.json field descriptions
{
"name": "主题名称", // 必须
"preview": "@/imgs/preview.webp", // 推荐 — 图片路径或 "#hex" 色值
"description": "主题描述", // 推荐
"author": "作者", // 推荐
"authorUrl": "https://...", // 可选
"version": "0.0.1", // 推荐 — 更新时必须递增
"tags": ["暗色"], // 提交到主题市场时需要,1-5 个
"blurHash": "...", // 有 iframe 时推荐(加载占位)
"iframe": { // 仅动态主题
"app": "@/iframes/app.html"
}
}
Note:
previewcan be an image path (such as@/imgs/preview.webp) or a CSS color value (such as"#1a1a2e")tagscan be omitted during local development and added later when submitting to the theme marketplaceidfield should not be added manually; it is managed automatically by the theme marketplace system
@/ path alias
In CSS and config.json, @/ is a path alias that points to the theme package root directory. At runtime it will be replaced with the file:// absolute path.
For example:
@/imgs/bg.webp→file:///C:/Users/.../themes/my-theme/imgs/bg.webpurl(@/imgs/texture.png)can reference local images in CSS
Resource limits
| Constraint | Limit |
|---|---|
| Single image | ≤ 500 KB |
| Single video | ≤ 5 MB |
| Entire theme package | ≤ 10 MB |
Optimization suggestions:
- Prefer WebP format (25-35% smaller than PNG/JPG)
- Use tools such as TinyPNG to compress images
- Prefer CSS gradients over image textures
- Use lower resolution or frame rate for videos when possible