A portable, self-describing archive format for WordPress site data. A Vector archive is a single gzip-compressed tar file (.tar.gz) containing a metadata.json manifest alongside a database dump and/or filesystem snapshot.
archive.tar.gz
├── metadata.json ← manifest (always first entry)
├── database.sql ← mysqldump output (when scope includes database)
├── wp-content/uploads/... ← WordPress files at natural paths (when scope includes files)
├── wp-content/plugins/...
├── wp-content/themes/...
├── wp-content/mu-plugins/...
├── wp-content/languages/...
└── wp-config.php
- Single file. The archive is one
.tar.gz— easy to upload, download, and transfer. metadata.jsonis always the first tar entry. This enables cheap manifest extraction without decompressing the full archive:tar xzf archive.tar.gz metadata.json -O.database.sqlis uncompressed inside the tar. Compression comes from the outer gzip layer — no double-gzip.- WordPress files use natural paths relative to the WP root. No wrapper directory.
- WordPress core files are not included. Only
wp-content/subdirectories (uploads, plugins, themes, mu-plugins, languages) andwp-config.php. WordPress core is reproducible from the official package. - Scope determines which entries exist. A
database-scope archive has no file entries. Afiles-scope archive has nodatabase.sql. Afull-scope archive has both.
To read the manifest without extracting the full archive:
tar xzf archive.tar.gz metadata.json -OThis decompresses only the first few KB of the gzip stream (since metadata.json is the first entry), regardless of total archive size.
{
"version": "1.0",
"created_at": "2026-02-04T02:00:00Z",
"scope": "full",
"compression": "gzip",
"app": {
"type": "wordpress",
"version": "6.7.1",
"php_version": "8.3.30",
"site_url": "https://mysite.example.com",
"multisite": false,
"active_theme": "flavor/flavor",
"active_plugins": [
{ "name": "woocommerce", "version": "8.5.1" },
{ "name": "wordfence", "version": "7.11.0" }
]
},
"database": {
"engine": "mysql",
"version": "8.0.36",
"name": "wordpress",
"tables": [
"wp_commentmeta", "wp_comments", "wp_links", "wp_options",
"wp_postmeta", "wp_posts", "wp_term_relationships",
"wp_term_taxonomy", "wp_termmeta", "wp_terms",
"wp_usermeta", "wp_users"
],
"prefix": "wp_",
"charset": "utf8mb4",
"collation": "utf8mb4_unicode_520_ci"
},
"files": {
"includes": [
"wp-content/uploads",
"wp-content/plugins",
"wp-content/themes",
"wp-content/mu-plugins"
],
"excludes": [
"wp-content/cache",
"wp-content/upgrade",
"wp-content/debug.log"
]
}
}{
"version": "1.0",
"created_at": "2026-02-04T14:30:00Z",
"description": "Before WooCommerce 9.0 update",
"scope": "database",
"compression": "gzip",
"app": {
"type": "wordpress",
"version": "6.7.1",
"php_version": "8.3.30",
"site_url": "https://store.example.com",
"multisite": false,
"active_plugins": [
{ "name": "woocommerce", "version": "8.5.1" }
]
},
"database": {
"engine": "mysql",
"version": "8.0.36",
"name": "wordpress",
"tables": [
"wp_commentmeta", "wp_comments", "wp_links", "wp_options",
"wp_postmeta", "wp_posts", "wp_term_relationships",
"wp_term_taxonomy", "wp_termmeta", "wp_terms",
"wp_usermeta", "wp_users",
"wp_wc_orders", "wp_wc_order_items"
],
"prefix": "wp_"
}
}An archive with minimal metadata — only the required fields:
{
"version": "1.0",
"created_at": "2026-02-04T18:00:00Z",
"scope": "full",
"compression": "gzip",
"app": {
"type": "wordpress",
"version": "6.5.0",
"php_version": "8.1.27",
"site_url": "https://old-host.example.com"
},
"database": {
"engine": "mariadb",
"version": "10.6.12",
"name": "oldsite_wp",
"tables": ["wp_options", "wp_posts", "wp_users"],
"prefix": "wp_"
},
"files": {
"includes": ["wp-content/"]
}
}| Field | Type | Required | Description |
|---|---|---|---|
version |
string | Yes | Manifest schema version. Currently "1.0". |
created_at |
string (ISO 8601) | Yes | UTC timestamp when the archive was created. |
description |
string | No | Human-provided label (e.g., "Before WooCommerce update"). |
scope |
string | Yes | What the archive contains: "full", "database", or "files". |
compression |
string | Yes | Compression format used for the archive: "gzip". |
Scope values:
| Value | Description |
|---|---|
full |
Contains both database dump and filesystem entries. |
database |
Contains database dump only. No file entries. |
files |
Contains filesystem entries only. No database.sql. |
Describes the application that was backed up. Fields beyond type vary by application and are all optional — the tool captures what it can detect.
| Field | Type | Required | Description |
|---|---|---|---|
app.type |
string | Yes | Application type: "wordpress", "unknown". |
app.version |
string | No | Application version (e.g., "6.7.1" for WordPress). |
app.php_version |
string | No | PHP version at backup time (e.g., "8.3.30"). |
app.site_url |
string | No | Site URL at backup time. Used as "from" in search-replace on restore. |
app.multisite |
boolean | No | Whether this is a WordPress multisite installation. |
app.active_theme |
string | No | Active theme slug (e.g., "flavor/flavor"). |
app.active_plugins |
array | No | Active plugins. Each entry: { "name": "slug", "version": "x.y.z" }. |
app.typetells consumers how to interpret the rest of theappfields.- When
app.typeis"unknown", no otherappfields are expected.
Present when scope includes database. Omitted when scope is "files".
| Field | Type | Required | Description |
|---|---|---|---|
database.engine |
string | Yes | Database engine: "mysql", "mariadb". |
database.version |
string | Yes | Database server version (e.g., "8.0.36"). |
database.name |
string | Yes | Database name that was dumped. |
database.tables |
string[] | Yes | All table names included in the dump. |
database.prefix |
string | No | Table prefix (e.g., "wp_"). WordPress-specific. |
database.charset |
string | No | Character set (e.g., "utf8mb4"). |
database.collation |
string | No | Collation (e.g., "utf8mb4_unicode_520_ci"). |
Present when scope includes files. Omitted when scope is "database".
| Field | Type | Required | Description |
|---|---|---|---|
files.includes |
string[] | No | Directories/files that were included. |
files.excludes |
string[] | No | Directories/files that were excluded. |
Vendor/platform-specific metadata. Consumers that don't recognize the platform should ignore this section entirely. The entire object is optional — archives created by third-party tools won't have it.
| Field | Type | Required | Description |
|---|---|---|---|
platform.name |
string | Yes | Platform identifier. |
platform.type |
string | No | Archive type (e.g., "manual", "scheduled", "import"). |
- Readers must ignore unknown fields — don't error on fields you don't recognize.
- New optional fields can be added without a version bump.
- New required fields or changed semantics require a version bump.
- The tool always writes the latest version.
The manifest (metadata.json) is always the first entry in the tar archive. This serves two purposes:
- Completeness signal — its presence means the archive was fully written. If extraction fails or the manifest is missing, the archive is corrupt or incomplete.
- Cheap extraction — consumers can read just the manifest without decompressing the entire archive, since gzip decompression only needs to process the stream up to the end of the first tar entry.