Introduction
When a WordPress theme update overwrites your carefully tuned theme.json, the result is not a minor visual glitch. It is a structural regression. Shadows vanish. Font sizes collapse. Layout widths snap back to defaults. For a small-to-mid publishing team running a block theme, this is not a cosmetic problem—it is a content-delivery failure. The theme.json file is the central configuration hub for global styles, block settings, and design tokens in modern block themes. Adjacent concepts include the Global Styles REST API, the wp_theme_json_data filter, and child-theme JSON merging. If you treat theme.json as a monolithic file you edit directly, you are building technical debt that will surface during the next automatic update. This article documents a durable method to preserve your customizations without forking the parent theme.
Why Direct Edits to theme.json Are a Trap
Editing the parent theme’s theme.json directly is the fastest path to a working design. It is also the fastest path to a broken site. When the parent theme updates—whether through a security patch, a feature release, or a routine maintenance bump—the entire file is replaced. Every custom color palette, every typography scale adjustment, every block-level spacing override disappears. The site reverts to the theme author’s defaults. For a publishing team, this means the article template that was carefully tuned for readability on tablet devices suddenly uses the wrong line height. The byline block that was constrained to a specific width now stretches edge to edge. These are not hypotheticals. They are the exact failure modes I have debugged on live sites after a minor theme update rolled out at 3 a.m.

The Core Mechanism: How WordPress Merges theme.json Data
To build a durable override system, you must understand the merge logic. WordPress reads theme.json from the active theme directory first. If a child theme is active, it reads the child’s theme.json and merges it on top of the parent’s data. The merge is recursive: child values replace parent values at the same path. After that, user customizations saved via the Site Editor are stored in the database and applied as a third layer. The wp_theme_json_data filter runs before the database layer, allowing programmatic overrides. This hierarchy—parent, child, filter, database—is the architecture you exploit to make customizations survive updates.
The Merge Order in Practice
- Parent theme.json – The baseline shipped by the theme author.
- Child theme.json – Your overrides, merged recursively.
- wp_theme_json_data filter – PHP-level adjustments.
- Database user styles – Changes made via the Site Editor UI.
If you edit the parent’s theme.json directly, you are modifying layer 1. The next update nukes it. If you use the Site Editor UI, you are writing to layer 4. That survives updates but is opaque, hard to version-control, and tied to a specific database. The sweet spot for a publishing team is layer 2: a child theme’s theme.json that contains only your deltas.
Step 1: Create a Child Theme with a Minimal theme.json
If you do not already have a child theme, create one. The child theme needs only a style.css header and a theme.json file. The style.css must declare the parent theme slug. The theme.json starts as an empty object or contains only the properties you intend to override. Do not copy the entire parent theme.json. That defeats the purpose: you want the parent to supply defaults, and the child to supply only the differences.
{
"version": 2,
"settings": {
"color": {
"palette": [
{
"slug": "brand-primary",
"color": "#1a73e8",
"name": "Brand Primary"
}
]
},
"typography": {
"fontSizes": [
{
"slug": "body",
"size": "18px",
"name": "Body"
}
]
}
},
"styles": {
"typography": {
"lineHeight": "1.6"
}
}
}
This child theme.json adds one custom color, overrides the body font size, and sets a global line height. Everything else inherits from the parent. When the parent theme updates, these overrides persist because they live in the child theme’s file, which is never touched by the update process.

Step 2: Document Every Custom Property with a Changelog
A child theme.json is only as maintainable as its documentation. Without a changelog, a team member will look at a property six months later and wonder why it exists. They might delete it, thinking it is cruft. Then the site breaks. The fix is a CHANGELOG.md file stored in the child theme root, or a theme.json comment block if your build process strips comments before deployment. Each entry must answer three questions: what was changed, why it was changed, and what the parent default was.
Example Changelog Entry
## 2025-01-14 – Typography Override
- Changed: `styles.typography.lineHeight` to 1.6
- Reason: Parent theme default of 1.2 caused text cramping on article pages with mixed Chinese and Latin scripts.
- Parent default: 1.2
- Affected blocks: paragraph, heading, list, quote
This practice is not busywork. When a parent theme update changes its own typography scale, you need to know whether your override is still necessary. Without documentation, you are guessing. With it, you can diff the new parent theme.json against your changelog and decide whether to keep, adjust, or remove each override.
Step 3: Use a Version-Controlled Diff Workflow
Store the parent theme’s theme.json in your repository as a reference file, not as active code. Before applying a parent theme update, pull the new version, diff it against the old reference, and check the diff against your child theme.json and changelog. This workflow catches conflicts before they hit production. A simple shell script can automate the diff:
#!/bin/bash
# diff-theme-json.sh
# Compare new parent theme.json against stored reference
diff -u reference-theme.json wp-content/themes/parent-theme/theme.json
Run this script after every parent theme update. Review the output. If the parent changed a property you override, evaluate whether your override is still correct. If the parent added a new property that conflicts with your design, decide whether to override it in your child theme.json or adjust your custom styles.
Step 4: Lock Critical Settings with the wp_theme_json_data Filter
Some settings are too important to leave solely in a JSON file that could be accidentally modified or deleted. The wp_theme_json_data filter lets you enforce overrides programmatically in your child theme’s functions.php. This is a belt-and-suspenders approach: the child theme.json handles the standard overrides, and the filter locks down settings that must never regress.
add_filter( 'wp_theme_json_data', function( $theme_json ) {
$new_data = array(
'version' => 2,
'settings' => array(
'layout' => array(
'contentSize' => '720px',
'wideSize' => '1080px',
),
),
);
return $theme_json->update_with( $new_data );
});
This filter runs after the child theme.json merge but before the database layer. It is the last line of defense. Use it sparingly—only for settings that would cause a publishing outage if reverted. Overusing the filter makes debugging harder because the source of truth is split between a JSON file and PHP code.

Step 5: Validate theme.json Before Deployment
A malformed theme.json can break the Site Editor and cause a white screen in the block editor. Validation must be part of your deployment pipeline. The WordPress core schema for theme.json is available at wp-includes/theme.json and can be used with a JSON schema validator. A simple Node.js script can check your child theme.json before it goes live:
const Ajv = require('ajv');
const schema = require('./theme-schema.json');
const childTheme = require('./child-theme.json');
const ajv = new Ajv();
const validate = ajv.compile(schema);
const valid = validate(childTheme);
if (!valid) {
console.error('theme.json validation errors:', validate.errors);
process.exit(1);
}
console.log('theme.json is valid.');
This step catches syntax errors, invalid property names, and type mismatches before they hit the editor. For teams without a Node.js pipeline, the WordPress.org Theme Check plugin includes a JSON linting step that can be run locally.
Step 6: Handle Global Styles Saved in the Database
When a user customizes styles via the Site Editor, those changes are stored in the wp_posts table as a wp_global_styles post. These database styles override both parent and child theme.json files. This is a problem if you want your child theme to be the single source of truth. The solution is to periodically export the database styles, merge them into your child theme.json, and then clear the database entry. WordPress provides a wp_theme_has_theme_json() function and a WP_Theme_JSON_Resolver class to help with this. A WP-CLI command can export the merged styles:
wp post list --post_type=wp_global_styles --format=json
Review the exported JSON, extract the relevant customizations, and add them to your child theme.json. Then delete the database entry to prevent it from masking your file-based overrides. This process should be part of your theme update checklist.
Common Failure Modes and Their Fixes
Failure: Custom Color Palette Disappears After Update
Cause: The parent theme’s theme.json defines a color.palette array. Your child theme also defines a color.palette array. The merge logic replaces the entire array rather than merging individual items. If your child theme’s palette is missing colors the parent expects, blocks referencing those colors break.
Fix: In your child theme.json, include all parent palette entries plus your custom ones. Alternatively, use the wp_theme_json_data filter to append colors to the parent palette programmatically.
Failure: Layout Widths Revert After Parent Update
Cause: The parent theme updated its settings.layout values. Your child theme.json did not override them, so the new parent values take effect.
Fix: Always explicitly set settings.layout.contentSize and settings.layout.wideSize in your child theme.json if your design depends on specific widths. Do not rely on inheritance for layout-critical values.
Failure: Custom Block Styles Stop Working
Cause: The parent theme added or changed block-level style defaults. Your child theme’s block styles are now conflicting or overridden.
Fix: Use the styles.blocks section in your child theme.json to explicitly set the properties you need. Be as specific as possible. For example, target styles.blocks.core/paragraph.typography.lineHeight rather than relying on the global styles.typography.lineHeight.
FAQ
Can I just use the Site Editor to make all my changes and skip child theme.json?
You can, but you are trading one problem for another. Database-stored styles survive theme updates, but they are not version-controlled, not portable between environments, and not reviewable in a pull request. If your database is corrupted or you migrate to a new server, those styles can be lost. A child theme.json is a file you can commit, diff, and deploy reliably.
What happens if the parent theme removes a property I depend on?
Your child theme override will have no effect because the parent no longer reads that property. This is rare but can happen if a theme author refactors their design system. Your changelog and diff workflow will catch this. When it happens, you need to find the new way the parent theme handles that design aspect and adjust your override accordingly.
How do I handle theme.json changes across a multisite network?
Each site in a multisite network can have its own child theme, so the same principles apply. If you need network-wide defaults, use a must-use plugin with the wp_theme_json_data filter. This enforces settings across all sites without requiring individual child themes. Be cautious: a mu-plugin override affects every site and can be difficult to override on a per-site basis.
Is there a way to test theme.json changes without affecting the live site?
Yes. Use a staging environment that mirrors your production setup. Apply the parent theme update there first, run your diff script, and test your child theme overrides. Only after confirming that all customizations survive the update should you deploy to production. For rapid iteration, the WP_DEBUG constant and the Query Monitor plugin can surface JSON parsing errors and filter conflicts.
Building a Durable Documentation Habit
Documenting theme.json changes is not a one-time task. It is a recurring discipline that pays off every time a theme update lands. The process I have outlined—child theme deltas, a changelog, version-controlled diffs, programmatic locks, validation, and database hygiene—turns a fragile, update-prone setup into a system that can survive automatic updates without manual intervention. For a publishing team, that means fewer late-night emergency fixes and more confidence that the site will look correct tomorrow morning.
If you are dealing with broader template-resolution issues after a theme change, the article What to Fix First When a New WordPress Site Says Nothing Found covers the template hierarchy and rewrite rules that often break alongside style changes.