Create Custom Themes (AI Reference)
This guide describes the file structure, configuration fields, and CSS used by custom themes in WonderPen for desktop. It helps AI assistants generate importable .wptheme files from user requirements and also supports manual theme creation. For theme controls in the app, see Themes.
Start by choosing a light or dark appearance, a color palette, a background image, and text reading styles. Then create the configuration and CSS, package the files, and check the result in WonderPen. Theme CSS mainly controls the application interface; styles for exported documents must be configured separately through Custom CSS.
Theme Package Structure
A .wptheme file is a ZIP archive with a different extension. Use this flat structure:
My Theme.wptheme
├── config.json
├── style.css
└── background.jpgconfig.json: required; defines the theme's identity, name, base theme, and default settings.style.css: optional; defines custom styles.background.jpg: optional; the theme's background image. Its name and format can differ.
Place these files directly at the root of the archive, without an enclosing folder or image subdirectories; the current importer does not create parent directories for packaged files. Use UTF-8 for config.json and style.css. Include only files the theme uses, excluding local settings, temporary files, old images, and system-generated directories such as __MACOSX. No HTML, JavaScript, or build tools are needed.
Configuration File
config.json uses standard JSON, without comments or trailing commas. The following configuration works with the Basic CSS Example later in this guide:
{
"id": "lake-light-6b6f66d3-604c-4c22-8537-22ba2a2723fa",
"title": {
"zh": "湖光",
"en": "Lake Light"
},
"theme_mode": "light",
"base_style": "light",
"bg_color": "#eef4f1",
"bd_color": "rgba(38, 59, 53, 0.12)",
"settings": {
"font_family": [],
"editor_font_family": [],
"editor_font_size": 18,
"editor_font_color": "auto",
"editor_width": 720,
"editor_line_height": 1.8,
"editor_paragraph_spacing": 0,
"editor_page_padding_h": 48,
"editor_page_padding_v": 30,
"editor_background_opacity": 1,
"editor_line_bg_show": false
}
}Generate a new unique id when creating a new theme. Do not copy the example ID.
Core Fields
| Field | Type | Required | Description |
|---|---|---|---|
id | String | Yes | Unique theme identifier |
title | String or object | Yes | Nonempty theme name; a multilingual object can include en, zh, and zh_tw |
theme_mode | String | No; explicit value recommended | "light" or "dark"; keep it consistent with the styles. See below for actual light/dark detection |
base_style | String | No | Built-in theme to inherit; omit or use an empty string for no base |
background_image | String | No | Background image filename in the package, such as "background.jpg"; set when using a theme background image |
background_image_blur | Number | No | Blur radius in px; the current settings UI allows 0–50 |
background_overlay_bg | String | No | Background overlay, usually a CSS color with transparency |
settings | Object | No | Default interface font and editor settings |
bg_color | String | No; recommended | Background color for the theme list preview |
bd_color | String | No; recommended | Border color for the theme list preview |
title can be a simple string such as "Lake Light". For a multilingual object, provide a nonempty en fallback name and add zh and zh_tw as needed. “Required” in the table refers to fields needed for a theme package that can be displayed, edited, and distributed correctly. The importer does not fully validate all fields, so a successful import does not prove the configuration is valid.
bg_color and bd_color do not set the actual interface colors. Both should be concrete color values, not complete border declarations or var(...) references to theme variables. When generating a package directly, include them as shown in the example so the theme list displays the intended palette; importing does not calculate them from CSS. Saving in the theme editor attempts to update the preview from CSS, but the result is not the browser's final computed color.
Do not distribute the runtime-generated bg_image field or duplicate the CSS in JSON. Keep styles in style.css.
Theme IDs and Updates
WonderPen identifies a theme by its id, not by its name or .wptheme filename.
- For a new, independent theme, generate a new ID.
- For an update to an existing theme, keep its ID.
- For variants that should coexist, use different IDs.
When importing a theme with an existing ID, WonderPen asks whether to overwrite it. After confirmation, the new package replaces the old theme directory. This is a full replacement, not a field-by-field merge; local theme settings in that directory are not retained either. The app does not compare version numbers or automatically keep multiple versions with the same ID.
Prefer an ID containing only lowercase ASCII letters, digits, and hyphens, such as a UUID or a name prefix followed by a UUID, to work with directory names and the app's generated CSS classes. Do not add the internal custom-- prefix or use whitespace, path separators, ., .., or a built-in theme name as the ID.
Inherit a Base Theme
base_style specifies a built-in theme to inherit. For example, "base_style": "light" starts from the Light theme.
WonderPen loads the base theme's styles first, then appends style.css. Custom rules can override the base styles according to the CSS cascade. Usually, you only need to override the variables you want to change, without copying the entire built-in theme.
base_style inherits the base theme's CSS, not all of the application states associated with that built-in theme. For example, a high contrast base provides its palette and CSS, but some components also rely on the app's high contrast state to enable borders or special styles. Those effects are not necessarily enabled by inheritance. Inspect the actual interface and add rules with confirmed selectors as needed, rather than changing the theme ID to imitate those states.
The following built-in themes are currently available. Set base_style to the identifier in the first column, not the display name:
| Identifier | Built-in theme name | Description |
|---|---|---|
light | Light | Light theme with a pale gray interface, white paper, dark text, and blue accents. |
dark | Dark | Dark theme with a charcoal background, light text, and blue accents. |
gray | Gray | Dark theme with gray backgrounds lighter than Dark and cyan accents. |
dracula | Dracula | Dark theme with a deep blue-purple background, light text, and purple accents. |
green | Green | Light theme with a soft gray-green interface and pale green paper. |
green2 | Green 2 | Light theme with a pale green interface, white paper, and green accents. |
cyan | Cyan | Light theme with a pale blue interface, nearly white paper, and cyan-blue accents. |
yellow | Yellow | Light theme with warm yellow backgrounds and paper, paired with dark brown text. |
pink | Pink | Light theme with pale pink backgrounds and paper, paired with pink accents. |
peach_fuzz | Peach Fuzz | Light theme with a soft peach interface, pale peach paper, and brown text. |
light_red | Light Red | Light theme with a nearly white, pale red background, white paper, and orange accents. |
silver | Silver | Light theme with a simple neutral palette of white, pale gray, and black. |
mocha_mousse | Mocha Mousse | Dark theme with coffee-brown backgrounds and paper, paired with warm white text. |
mocha_light | Mocha Light | Light theme with a beige interface, warm white paper, and dark brown text. |
high_contrast_light | Light | High contrast light theme with black text on white and distinct borders. |
high_contrast_dark | Dark | High contrast dark theme with white text on black and distinct borders. |
high_contrast_dark_green | Dark 2 | High contrast dark theme with bright green text and borders on black. |
high_contrast_dark_yellow | Dark 3 | High contrast dark theme with bright yellow text and borders on a nearly black background. |
To start without a base theme, omit base_style or set it to "". Omitting it is recommended. Do not use "none" or a custom theme ID.
Without a base theme, you need to provide enough theme variables to cover text, backgrounds, inputs, menus, selection states, and other interface elements. Starting with a base theme close to the desired appearance is usually easier.
theme_mode does not generate a color palette. The app determines light or dark appearance from the CSS variable --wp-dark:
.theme-custom {
--wp-dark: light;
}For dark themes, use --wp-dark: dark. Keep this value consistent with theme_mode and the overall colors.
Default Editor Settings
Prefer settings for fonts, font size, line height, paper opacity, and similar options. The app generates runtime styles from these settings; overriding the corresponding values directly in CSS can interfere with user adjustments. Omitted settings start with app defaults, followed by local adjustments and settings kept consistent across themes. They do not inherit local editor settings from the base theme.
The table below lists the settings currently applied with a theme. Do not add arbitrary app settings to settings: for example, editor_letter_spacing and editor_text_align are outside this list. Putting such fields at the top level does not make them take effect either.
| Field | Value and units |
|---|---|
font_family | Array of interface font names |
editor_font_family | Array of editor font names, with the primary font first and the fallback font second |
editor_font_size | Font size, number, px |
editor_font_color | "auto" or a CSS color |
editor_width | Editor width, number, px |
editor_line_height | Line height, number, used as em |
editor_paragraph_spacing | Paragraph spacing, number, used as em |
editor_page_padding_h | Horizontal page padding, number, px |
editor_page_padding_v | Vertical page padding, number, px |
editor_background_opacity | Paper opacity, from 0 to 1 |
editor_line_bg_show | Whether to show ruled lines, boolean |
editor_line_bg_use_custom_color | Whether to use a custom ruled-line color, boolean |
editor_line_bg_color | Ruled-line color |
editor_background_type | "auto", "color", or "image" |
editor_background_color | Custom background color |
editor_background_image | Background image URL used at runtime |
Do not append units to numbers: write 18 for font size, not "18px". Use [] when no font is specified, without null or meaningless blank entries. Listing font names does not install those fonts with the theme.
editor_background_opacity controls the paper background: 0 is fully transparent and 1 is fully opaque. It does not change text opacity.
Prefer values within the current theme editor's input ranges: font size 10–100 px, line height 0.5–4, paragraph spacing 0–4, and horizontal and vertical page padding 0–200 px. Editor width starts at 400 px, with an upper limit based on screen width. These are UI ranges, not a guarantee that importing will validate or correct out-of-range values.
Reference a bundled background image through the top-level background_image field so the app can generate its actual URL. Do not put a package filename directly in settings.editor_background_image.
Background settings have additional application logic. Without local background overrides or rules keeping settings consistent across themes, a top-level background_image sets the background type to image. Without that field, the type resets to auto and the image URL is cleared. Therefore, setting only settings.editor_background_type: "color" and editor_background_color does not create a solid-color theme. Use --wp-base-bg, --wp-paper-bg, and panel background variables for solid colors; use the top-level background_image for an image theme.
CSS Scope and Writing Rules
When a custom theme is applied, WonderPen adds .theme-custom to body. Define shared theme variables there, and prefer meaningful data-* attributes for specific interface adjustments:
.theme-custom {
--wp-primary-color: #397d75;
}
.theme-custom [data-role='editor-nav-bar'] {
background: rgba(230, 240, 233, 0.8);
}Follow these rules:
- Override existing theme variables first, then style specific elements as needed.
- Keep the
.theme-customscope. Set local variables on the relevant region and global colors on.theme-custom, so floating elements such as menus can inherit them too. - Prefer confirmed
[data-role="..."]selectors and other state attributes. - Avoid generated class names, complex DOM hierarchies, and unverified selectors.
- Use plain CSS. Theme CSS is not compiled with Sass and does not support Sass variables or mixins.
- Use expanded selectors by default to simplify review and maintenance.
- Use
!importantonly where necessary, on specific declarations. - Use colors such as
rgba()for transparent backgrounds. Settingopacityon a whole panel also fades its text and buttons.
CSS can include gradients, pseudo-classes, pseudo-elements, shadows, filters, and animations. Give animations distinctive names and consider disabling or reducing motion with prefers-reduced-motion.
Both data-* attributes and theme variables may change between versions. To find additional selectors, inspect the target element in the app's developer tools instead of guessing attribute names. Check the actual result in the target version.
CSS Variables You Can Override
The table below lists common variables. For the complete variable listings and default values of the Light and Dark themes, see Built-in Theme Styles.
| Purpose | Common variables |
|---|---|
| Light or dark appearance | --wp-dark |
| Primary color and text on it | --wp-primary-color, --wp-on-primary-color |
| Primary and secondary text | --wp-text-color, --wp-text-color-2 |
| Links | --wp-link-color, --wp-link-hover-color |
| Text highlighting | --wp-text-highlight-color, --wp-text-highlight-bg, --wp-text-highlight-border |
| Base background and text | --wp-base-bg, --wp-on-base-bg, --wp-on-base-bg2 |
| Paper backgrounds | --wp-paper-bg, --wp-paper-bg-alpha |
| Inputs | --wp-input-bg, --wp-input-bg-disabled |
| Selection | --wp-selected-bg, --wp-on-selected-bg |
| Unfocused selection | --wp-selected-bg-blur, --wp-on-selected-bg-blur |
| Secondary selection and hover | --wp-selected-bg2, --wp-on-selected-bg2, --wp-hover-bg |
| General border colors | --wp-border-color, --wp-border-color-2, --wp-border-color-3 |
| Frame separators | --wp-frame-border-color (a complete border declaration, not just a color) |
| Left panel | --wp-left-panel-bg, --wp-left-panel-border, --wp-left-panel-backdrop-filter |
| Main panel | --wp-main-panel-bg, --wp-main-panel-border, --wp-main-panel-backdrop-filter |
| Right panel | --wp-right-panel-bg, --wp-right-panel-border, --wp-right-panel-backdrop-filter |
| Title and status bars | --wp-title-bar-bg, --wp-status-bar-bg |
| Memos | --wp-memo-bg |
| Popups | --wp-popup-bg, --wp-popup-border, --wp-popup-backdrop-filter |
| Page overlay and filter | --wp-page-wrapper-bg, --wp-page-wrapper-backdrop-filter |
| Shadows | --wp-shadow, --wp-shadow-sm, --wp-shadow-lg, --wp-shadow-float |
| Caret and focus outline | --wp-caret-color, --wp-focus-outline-color |
| Scrollbars | --wp-scrollbar-thumb, --wp-scrollbar-thumb-hover, --wp-scrollbar-track |
Use the value type expected by each variable. For example, a border color differs from a complete border declaration:
.theme-custom {
--wp-border-color: rgba(38, 59, 53, 0.12);
--wp-left-panel-border: 1px solid rgba(38, 59, 53, 0.12);
--wp-left-panel-backdrop-filter: blur(8px);
}--wp-paper-bg is used to calculate paper color and opacity. Supply a color, not a gradient or url(...). For gradients, use panel variables that accept background values, or set background on a confirmed target element.
When changing a background, check its corresponding text color too. For example, after changing --wp-selected-bg, also check --wp-on-selected-bg.
The reference page uses .theme-light and .theme-dark for built-in themes. When reusing their variables in a custom theme, place the declarations inside .theme-custom.
Island Layout and Borders
The main window's island layout separates rounded panels with empty space. Frame separators between panels and the outline of each island are different borders; do not hide them together. When creating a theme, preserve the built-in layout and adjust only the colors you need:
--wp-frame-border-colorcontrols frame separators below the main window's top toolbar and between the side panels and the central workspace. The built-in Light theme uses1px solid transparent; an opaque color adds lines in the existing gaps. Despite ending incolor, this variable takes a complete border declaration.--wp-left-panel-border,--wp-main-panel-border, and--wp-right-panel-bordercontrol panel and editor outlines. Components such as navigation bars and stacked panels also use them for necessary internal boundaries. Keep these borders visible and adjust their colors to suit the theme. Do not set them all tononeor transparent to remove frame separators.- General border colors such as
--wp-border-colorare also used by other components. Do not make them globally transparent to remove a line in one location.
For example, this preserves pale gray-green island outlines while keeping frame separators transparent:
.theme-custom {
--wp-frame-border-color: 1px solid transparent;
--wp-border-color: #c7d5cc;
--wp-left-panel-border: 1px solid var(--wp-border-color);
--wp-main-panel-border: 1px solid var(--wp-border-color);
--wp-right-panel-border: 1px solid var(--wp-border-color);
}If extra lines appear, compare the result with a similar built-in theme. Use developer tools to identify the element and variable drawing each line, then correct that variable. Do not apply blanket border: none or border-color: transparent overrides to regions such as main-page-frame, frame-body-left, frame-body-main, frame-body-right, editor-base, or navigation bars. These overrides replace component border rules and may also remove necessary boundaries in Composition Mode, Minimal Mode, or panels that slide into view.
The app's layout manages spacing, rounded corners, and border visibility in different modes. Unless a layout change is explicitly needed, preserve these rules instead of recreating the island layout in theme CSS.
Bottom Status Bar Backgrounds
In the normal island layout, the status bars at the bottom of the left, center, and right columns should blend into the window background rather than form separate color blocks matching the panels or navigation bars above them. To preserve the built-in Light theme's appearance, check all three of the following:
- Status bar variable: The bottom toolbars of the side panels and the editor status bar use
--wp-status-bar-bg. Set it totransparent. - Direct style overrides: Do not group
[data-role="editor-status-bar"]with navigation or tab bars when applying a solidbackground. A direct background declaration bypasses the status bar variable; remove such overrides so the component continues to use its built-in rules. Check the side-panel regions,[data-role="left-panel-bottom-bar"]and[data-role="right-panel-bottom-bar"], for similar overrides. - Parent container background: The central container includes both the editor area and its bottom status bar, and its background is controlled by
--wp-main-panel-bg. An opaque parent background still shows through a transparent status bar. Set this variable totransparentas well when the status bar should blend into the window background. Use--wp-paper-bgfor the text editor's paper color instead of coloring the entire central container.
Use the following variable settings together with removing direct background overrides on status bars:
.theme-custom {
--wp-status-bar-bg: transparent;
--wp-main-panel-bg: transparent;
}Transparency exposes the background underneath; it is not a fixed color. If a color block remains, inspect the computed backgrounds of the status bar and its ancestors. Do not fade the entire element with opacity or remove island borders to address a background issue. Unless a specific status bar design is needed, preserve the app's status bar rules for Composition Mode, Minimal Mode, and floating windows.
Common Interface Selectors
| Selector | Region |
|---|---|
[data-role="page-wrapper"] | Page wrapper |
[data-role="main-page-frame"] | Main window frame |
[data-role="frame-body-left"] | Left panel region |
[data-role="frame-body-main"] | Central working region |
[data-role="frame-body-right"] | Right panel region |
[data-role="left-panel-sidebar"] | Left vertical toolbar |
[data-role="right-panel-sidebar"] | Right vertical toolbar |
[data-role="editor-base"] | Editor pane container |
[data-role="editor-prosemirror"] | Main text editor region; use it to scope shared-editor rules |
[data-role="editor-nav-bar"] | Editor navigation bar |
[data-role="editor-status-bar"] | Editor status bar |
[data-role="editor"] | Outer container of the shared text editor |
[data-role="editor-paper"] | Text editor paper |
[data-role="editor-paper-content"] | Mounting container for editable content |
[data-role="editor-tabs"] | Editor tabs region |
[data-role="editor-tab-item"] | Individual editor tab |
[data-role="tree-panel"] | Document tree panel |
[data-role="memo-editor"] | Memo editor |
The shared editor can appear in multiple contexts. To target only the main text editor paper, use .theme-custom [data-role="editor-prosemirror"] [data-role="editor-paper"]. editor-paper-content is a mounting container, not the outer editor. Prefer configuration fields and theme variables for paper backgrounds, width, and text layout.
These attributes are not present in every window or view. For example, the main-window frame selector does not match floating windows, and vertical toolbars are absent in a horizontal toolbar layout. Status bars can also be rendered outside the editor region through a portal, so do not assume they are always descendants of editor-base.
Combine state attributes with region selectors:
/* Active tab */
.theme-custom [data-role='editor-tab-item'][data-active='1'] {
color: var(--wp-primary-color);
}
/* Navigation bar of the active pane in split view */
.theme-custom [data-role='editor-base'][data-active-status='1'] [data-role='editor-nav-bar'] {
background: rgba(210, 230, 219, 0.85);
}
/* Main window with an image background */
.theme-custom [data-role='main-page-frame'][data-background-type='image'] {
--wp-memo-bg: transparent;
}data-active-status="1" means the pane is active in split view; "0" means it is inactive in split view. The attribute may be absent when the editor is not split.
A matching selector does not guarantee that its rule wins. The app has dedicated styles for active panes, Continuous View, and other states. If a rule does not produce the expected result, inspect computed styles and selector specificity, then add the necessary region or state qualifiers.
The main window frame also provides data-composition="1" and data-minimal-mode="1" for Composition Mode and Minimal Mode. When a state attribute and data-role belong to the same element, place the selectors directly next to each other without a space.
Distinguish the two background state attributes: main-page-frame in the main window uses data-background-type; page-wrapper in both main and floating windows uses data-editor-background-type. To match an image background in both window types, use [data-role="page-wrapper"][data-editor-background-type="image"]. Do not interchange the attribute names.
To limit a rule to a window type, use:
body.theme-custom[data-win-name='main'] [data-role='page-wrapper'] {
/* Main window */
}
body.theme-custom[data-win-name='float'] [data-role='page-wrapper'] {
/* Floating window */
}Basic CSS Example
The following style.css works with the earlier JSON configuration. It inherits the Light theme and changes it to a soft green palette:
.theme-custom {
--wp-dark: light;
--wp-primary-color: #397d75;
--wp-on-primary-color: #ffffff;
--wp-text-color: #263b35;
--wp-text-color-2: #687d75;
--wp-base-bg: #eef4f1;
--wp-on-base-bg: #263b35;
--wp-on-base-bg2: #687d75;
--wp-paper-bg: #fbfdfb;
--wp-selected-bg: #397d75;
--wp-on-selected-bg: #ffffff;
--wp-hover-bg: rgba(57, 125, 117, 0.12);
--wp-frame-border-color: 1px solid transparent;
--wp-border-color: rgba(38, 59, 53, 0.12);
--wp-left-panel-bg: #dcebe3;
--wp-main-panel-bg: transparent;
--wp-right-panel-bg: #e6f0e9;
--wp-status-bar-bg: transparent;
--wp-left-panel-border: 1px solid var(--wp-border-color);
--wp-main-panel-border: 1px solid var(--wp-border-color);
--wp-right-panel-border: 1px solid var(--wp-border-color);
--wp-memo-bg: #f3f7ee;
--wp-caret-color: #397d75;
}
.theme-custom [data-role='editor-nav-bar'] {
background: rgba(230, 240, 233, 0.8);
}Background Images, Blur, and Transparency
To use a background image, place it at the root of the ZIP archive and merge these fields into the top level of the configuration. Prefer a simple filename such as background.png or background.jpg, matching the configuration exactly, including case. Avoid characters with URL meanings such as # and ?. The app's background-image save logic handles PNG, JPG/JPEG, GIF, BMP, and WebP.
{
"background_image": "background.jpg",
"background_image_blur": 8,
"background_overlay_bg": "rgba(255, 255, 255, 0.35)"
}Also adjust settings.editor_background_opacity as needed, for example to 0.2. The snippet above contains only the fields to add, not a complete config.json.
These settings control different layers:
- Background image: supplies the underlying image.
- Blur: softens image details.
- Overlay: reduces background contrast or makes the image lighter or darker.
- Paper opacity: controls how much the paper behind the text obscures the background.
- Panel backgrounds: controlled by CSS variables and can use translucent colors.
Images are centered and fill the window using cover by default, so some edges are cropped when aspect ratios differ. Lowering paper opacity does not make the side panels transparent. If you reuse the earlier CSS example, change the panel backgrounds to translucent colors separately to reveal the image beneath them.
Do not reference a bundled background image directly with url("./background.jpg"). Theme CSS is injected into a page <style> element, so relative URLs are not automatically resolved against the theme directory. Do not use absolute paths from the author's computer either.
Theme styles are assembled in this order: base theme styles → style.css → rules generated from background settings. A positive blur radius generates --wp-page-wrapper-backdrop-filter, and a nonempty overlay generates --wp-page-wrapper-bg. At equal specificity, these rules override the corresponding values in style.css.
Package, Import, and Check
Compress config.json, style.css, and any images in use into a ZIP archive, then change its extension to .wptheme. A ZIP tool can also write directly to a file with that extension.
For example, place the configuration and CSS in a my-theme/ directory and run this Python code from its parent directory:
import json
from pathlib import Path
from zipfile import ZipFile, ZIP_DEFLATED
source = Path("my-theme")
config = json.loads((source / "config.json").read_text(encoding="utf-8"))
files = ["config.json"]
if (source / "style.css").is_file():
files.append("style.css")
background = config.get("background_image")
if background:
# The image must be at the package root, not a path or URL.
assert isinstance(background, str)
assert "/" not in background and "\\" not in background
assert background not in (".", "..")
files.append(background)
for name in files:
assert (source / name).is_file(), f"Missing file: {name}"
with ZipFile("my-theme.wptheme", "w", ZIP_DEFLATED) as archive:
for name in files:
archive.write(source / name, arcname=name)In WonderPen, click Import under Settings → Appearance → Custom Themes, then click the imported theme to apply it. Feature access is indicated in the app and on the plan comparison page.
Check at least the following:
- Text in the editor, memos, document tree, inputs, and menus is readable.
- Selected, hovered, unfocused, and disabled states are distinguishable.
- Single-editor, split-view, tabbed, and floating-window layouts display correctly.
- Island outlines remain visible, gaps between panels have no extra frame separators, and necessary component boundaries such as those in navigation bars remain intact.
- The bottom status bars of the left, center, and right columns blend into the window background, without unexpected color blocks from direct background overrides or parent containers.
- Resizing the window does not cause backgrounds or panels to obscure content unexpectedly.
- Composition Mode and Minimal Mode remain usable.
- Switching to another theme removes the custom theme's effects.
If the result differs from expectations, also check:
- Whether other Custom CSS schemes are enabled under Advanced. They load after theme CSS and can override it at equal specificity.
- Whether local adjustments have been saved for this theme. If needed, clear them with Reset to Default in the theme's context menu.
- Whether Keep Consistent is enabled under Apply to Other Themes. Stop keeping settings consistent before checking all of the theme's defaults.
The theme editor saves the distributable design. Additional adjustments made in the style panel while using a theme are not automatically included in an exported theme. Save any settings you want to distribute in the theme design itself.
Delivery Checklist for AI Assistants
- The ZIP root contains valid
config.jsonwith a nonempty theme name. - JSON and CSS use UTF-8, and fields and value types follow this guide. A successful import is not a complete configuration check.
- A new theme uses a new ID; an update keeps the existing ID.
base_styleis a valid built-in theme identifier or is omitted.theme_mode,--wp-dark, and the actual palette agree.- CSS uses the
.theme-customscope and prefers confirmeddata-*selectors for specific elements. - Distinguish frame separators from island outlines and follow the border guidance, avoiding blanket overrides that hide panel or component borders.
- Follow the status bar background guidance to check the status bar variable, direct background overrides, and parent backgrounds together. Setting the status bar variable to transparent alone does not complete the check.
- Image references do not depend on absolute paths on the author's computer, and the package contains the referenced image.
- The package excludes
local_settings.json, otherlocal*files, and unrelated resources. - Deliver the
.wpthemefile with a short description of its appearance, fonts, and import instructions. - If the theme has not been checked in WonderPen, explicitly state that in-app validation has not been completed.
