JSON files
Where the files go
Each folder VX reads holds one folder per kind of object:
text
wp-content/themes/my-theme/vx-config/
├── post-types/book.json
├── taxonomies/genre.json
└── fieldsets/book_details.jsonVX reads three kinds of folders:
Your theme's
vx-configfolder. VX finds it automatically. A child theme's is read too, and its files override the parent theme's for the same key.Any folder you add, in a plugin or anywhere else on the server, with a filter:
phpadd_filter( 'vxframework/config/paths', function ( array $paths ) { $paths[] = plugin_dir_path( __FILE__ ) . 'vx-config'; return $paths; } );wp-content/uploads/vx-framework/vx-config, VX's own folder, listed as Uploads folder in the dashboard. It's in the site's uploads folder, so on a multisite network each site has its own:wp-content/uploads/sites/<site ID>/vx-framework/vx-configfor sites other than the main one.
When two folders have a file for the same key, a folder you added wins over your theme, and your theme wins over the uploads folder.
Where VX writes files
VX writes config files to the uploads folder, whether the dashboard, an assistant or WP-CLI saves them, so Save to project, Sync and Direct mode work there. It creates the folder the first time it needs it, with an index.php against directory listing and an .htaccess that blocks direct requests on servers that read one, such as Apache. On nginx, add an equivalent rule if the files shouldn't be downloadable.
Files in the uploads folder belong to the site rather than to your theme, so a deploy that ships your theme doesn't include them.
For a folder VX reads but doesn't write to, the Source tab hands the work over to you. Save to project and Sync show the file's path and copy its JSON; you save the file, and Check file confirms VX sees it. Remove from project keeps the configuration in the database and asks you to delete the file.
Saving to the uploads folder from the dashboard needs the same permission as editing the configuration itself. The files are configuration, not code, so DISALLOW_FILE_EDIT and DISALLOW_FILE_MODS don't turn it off. VX ignores a folder registered inside its own plugin folder, whose files are replaced on every update.
VX Framework Pro also writes to every folder you register, and registers the active and parent theme's vx-config folders for you, so Save to project, Sync and Direct mode work in all of them. It never writes inside wp-admin or wp-includes, nor directly into the site root, wp-content, or the plugins, must-use plugins, themes or uploads directory. Saving into a theme's folder needs permission to edit theme files, and into any other registered folder permission to edit plugin files, so neither works when DISALLOW_FILE_EDIT or DISALLOW_FILE_MODS is set.
The file format
Every file wraps one object in the same envelope, the format the dashboard's Export produces:
json
{
"$schema": "vx-config/v1",
"type": "fieldset",
"key": "book_details",
"config": {
"label": "Book details",
"fields": [
{ "type": "text", "key": "tagline", "label": "Tagline" }
],
"location": { "groups": [ { "object": "post_type", "targets": [ "book" ] } ] }
}
}A dictionary's entries go inside its config:
json
{
"$schema": "vx-config/v1",
"type": "dictionary",
"key": "formats",
"config": {
"label": "Formats",
"entries": [
{ "value": "hardcover", "label": "Hardcover" },
{ "value": "paperback", "label": "Paperback" }
]
}
}The easiest way to get a correct file is to build the object in the dashboard and export it: from its Source tab, choose Save to project, or use wp vx-framework config export … --write. Exports are deterministic, so the same object always produces byte-identical JSON and your diffs only show real changes.
Editing files from the dashboard
JSON-backed objects can use Direct mode: dashboard edits are written straight back to the file. Turn it on for local development, commit the files, and keep production Read only. See Editing modes.
Direct mode needs the file to be in the uploads folder (see above), and the web server to be able to write to it. With VX Framework Pro, a file in one of the folders it writes to works too.
When a file is invalid
A file that fails validation isn't registered. Its object's Source tab reports the problem, and wp vx-framework config status --strict fails, so a broken file shows up in CI rather than on production.
A file can also load and still do less than it says. An unknown field type, an unknown location rule, a field key another fieldset already uses, a key WordPress reserves (like author), a post type key longer than 20 characters, or a file name that doesn't match the key inside it. VX still loads the file and ignores the parts that don't work, and reports each one:
- Errors are parts of the file that are invalid.
- Warnings are parts that are kept as written but do nothing. A misspelled field type is a warning, with the type it probably meant (
Unknown field type "texarea"… Did you mean "textarea"?).
Both show on the object's Source tab, and both fail wp vx-framework config status --strict.
Technical details for LLMs
- Discovery:
vx-framework/vx-config/in the site's uploads directory (wp_upload_dir()['basedir'], souploads/sites/<blog_id>/vx-framework/vx-config/on a network's other sites), then the parent and child themevx-config/, thenvxframework/config/paths(later directories win per key). Registered paths inside VX's plugin folder are ignored. Subfolders:post-types,taxonomies,fieldsets; file name = key. - Writes:
write_targetsinvx-framework/get-config-statuslists every folder an object can be saved to, withlabel(Uploads folderfor VX's own),writableand, when false, areason. Writing to a folder that isn't writable fails withread_only_location.vx-framework/get-config-sourcereportssync.manualanddetach.manualfor an object kept in such a folder: sync or remove the file by hand. Writing to VX's folder needsmanage_options, and is refused withconfig_write_not_allowedwithout it; WP-CLI needs no capability. - Pro: every registered path is writable except inside
wp-admin/wp-includesor when it is the site root,wp-content, or the plugins, must-use plugins, themes or uploads directory itself. Writing to one needsedit_plugins, oredit_themesfor a path inside a theme, and is refused withfile_edit_not_allowedwithout it. - Envelope:
{ "$schema": "vx-config/v1", "type": "post_type" | "taxonomy" | "fieldset", "key", "config" }. Same envelope asvx-framework/export-config,vx-framework/import-config,vx-framework/validate-config. - Option pages and dictionaries use the same envelope, in the
option-pagesanddictionariessubfolders, with"type": "option_page"and"type": "dictionary". - JSON is shadowed by a PHP registration of the same key.
- Loaded-with-problems files and PHP registrations appear in
vx-framework/get-config-conflictsasinvalid_definition, witherrorsandwarningslists of{ path, message }. Every conflict entry hasseverity: "error" | "warning"(aninvalid_definitionwith only warnings is awarning), and the response counts both inerrorsandwarnings.vx-framework/get-config-statusreturns them underproblems;vx-framework/get-config-sourceunderproblems.errors/problems.warnings. - Write-through:
vx-framework/set-config-sourcefile; write a database object to a file withvx-framework/write-config-to-project(dry-run reports create / overwrite / identical; no undo);vx-framework/detach-configdeletes the file (no undo). - After editing files on disk, permalink changes need
vx-framework/flush-permalinksor a visit to Settings → Permalinks.