When using Nuxt Studio's visual editor with @nuxt/content v3, the editor shows the warning:
"The content on GitHub differs from your website version. Ensure your latest changes are deployed and refresh the page."
This occurs even when the deployed website is fully up to date with GitHub. The root cause is that getOrderedSchemaKeys() alphabetically sorts schema properties when building the SQLite table, so the API response returns keys in a different order than the source JSON file on GitHub.
Nuxt Studio compares the raw GitHub file (which preserves the original key order) against the website's API response (which returns keys alphabetically). Since the key order differs, Studio flags it as a content mismatch even though the actual data is identical.
Reproduction
1. Define a collection with a schema in content.config.ts
import { defineContentConfig, defineCollection, z } from '@nuxt/content';
const pageSeoSchema = z.object({
seo_title: z.string(),
seo_description: z.string(),
seo_schema: z.string(),
});
export default defineContentConfig({
collections: {
landing_page: defineCollection({
type: 'data',
source: 'landing_page.json',
schema: pageSeoSchema.extend({
description: z.string(),
}),
}),
},
});
2. Create the corresponding JSON file at content/landing_page.json
{
"seo_title": "My Page Title",
"seo_description": "My page description.",
"seo_schema": "<script type=\"application/ld+json\">{}</script>",
"description": "<p>Hello world</p>"
}
Note the key order matches the schema definition: seo_title, seo_description, seo_schema, description.
3. Fetch the data using queryCollection
<script setup lang="ts">
const { data } = await useAsyncData('landing', () =>
queryCollection('landing_page').first()
);
// Log the key order returned by the API
console.log(Object.keys(data.value));
</script>
Expected key order (matching the source JSON and schema definition):
["seo_title", "seo_description", "seo_schema", "description"]
Actual key order (alphabetically sorted by getOrderedSchemaKeys):
["description", "seo_description", "seo_schema", "seo_title"]
The returned object has description as the first key instead of seo_title, even though both the JSON file and the Zod schema define seo_title first.
4. Deploy and open in Nuxt Studio
The visual editor shows the "content on GitHub differs" warning. Inspecting the comparison reveals:
- GitHub version (raw file): first key is seo_title
- Website version (API response): first key is description
- The website API returns keys in alphabetical order: description, seo_description, seo_schema, seo_title.
Root Cause
The issue is in getOrderedSchemaKeys() in @nuxt/content/dist/runtime/internal/schema.js:
export function getOrderedSchemaKeys(schema) {
const shape = Object.values(schema.definitions)[0]?.properties || {};
const keys = new Set([
shape.id ? "id" : void 0,
shape.title ? "title" : void 0,
...Object.keys(shape).sort() // <-- .sort() forces alphabetical order
].filter(Boolean));
return Array.from(keys);
}
The .sort() call on line 15 forces all schema keys into alphabetical order. This function is used by both generateCollectionTableDefinition() (which creates the SQLite table with columns in sorted order) and generateCollectionInsert() (which writes data in sorted order). As a result, queryCollection() returns objects with alphabetically-ordered keys.
Nuxt Studio then compares this alphabetically-ordered API response against the raw JSON from GitHub (which preserves the author's original key order), and concludes the content has diverged.
Expected Behavior
The key order in the API response should match the key order in the source JSON file (or at least the schema definition order), so that Nuxt Studio's comparison does not produce a false positive mismatch.
One thing to add :
The preview module (preview/collection.js), which is what Nuxt Studio specifically uses for live editing, has its own generateCollectionInsert that also calls getOrderedSchemaKeys at line 90. This means the alphabetical sorting affects both the deployed website and the Studio preview pipeline.
// preview/collection.js line 86-91
function computeValuesBasedOnCollectionSchema(collection, data) {
const fields = [];
const values = [];
const properties = collection.schema.definitions[collection.name].properties;
const sortedKeys = getOrderedSchemaKeys(collection.schema); // <-- same sort
sortedKeys.forEach((key) => {
Suggested Fix
Remove the .sort() call from getOrderedSchemaKeys()?:
const keys = new Set([
shape.id ? "id" : void 0,
shape.title ? "title" : void 0,
...Object.keys(shape)
].filter(Boolean));
return Array.from(keys);
}
Object.keys() already returns keys in insertion order (per the ECMAScript spec), which is deterministic for a given schema definition. The sort is unnecessary for correctness and actively breaks the Nuxt Studio content comparison.
Alternatively, if deterministic ordering across different schema definitions is desired, the comparison logic in Nuxt Studio could be made key-order-agnostic (e.g., deep equality comparison ignoring key order).
Workaround
Reorder the top-level keys in all content JSON files to be alphabetical. This aligns the raw file with what the API returns, preventing the false mismatch. However, this requires manually maintaining alphabetical key order in every content file going forward.
Environment
@nuxt/content: 3.11.2
nuxt: 4.3.1
nuxt-studio: 1.4.0
Collection type: data (JSON)
Content storage: SQLite with sqliteConnector: 'native'
When using Nuxt Studio's visual editor with @nuxt/content v3, the editor shows the warning:
This occurs even when the deployed website is fully up to date with GitHub. The root cause is that
getOrderedSchemaKeys()alphabetically sorts schema properties when building the SQLite table, so the API response returns keys in a different order than the source JSON file on GitHub.Nuxt Studio compares the raw GitHub file (which preserves the original key order) against the website's API response (which returns keys alphabetically). Since the key order differs, Studio flags it as a content mismatch even though the actual data is identical.
Reproduction
1. Define a collection with a schema in
content.config.ts2. Create the corresponding JSON file at
content/landing_page.jsonNote the key order matches the schema definition: seo_title, seo_description, seo_schema, description.
3. Fetch the data using
queryCollectionExpected key order (matching the source JSON and schema definition):
["seo_title", "seo_description", "seo_schema", "description"]Actual key order (alphabetically sorted by getOrderedSchemaKeys):
["description", "seo_description", "seo_schema", "seo_title"]The returned object has
descriptionas the first key instead ofseo_title, even though both the JSON file and the Zod schema define seo_title first.4. Deploy and open in Nuxt Studio
The visual editor shows the "content on GitHub differs" warning. Inspecting the comparison reveals:
Root Cause
The issue is in
getOrderedSchemaKeys()in @nuxt/content/dist/runtime/internal/schema.js:The .sort() call on line 15 forces all schema keys into alphabetical order. This function is used by both generateCollectionTableDefinition() (which creates the SQLite table with columns in sorted order) and generateCollectionInsert() (which writes data in sorted order). As a result, queryCollection() returns objects with alphabetically-ordered keys.
Nuxt Studio then compares this alphabetically-ordered API response against the raw JSON from GitHub (which preserves the author's original key order), and concludes the content has diverged.
Expected Behavior
The key order in the API response should match the key order in the source JSON file (or at least the schema definition order), so that Nuxt Studio's comparison does not produce a false positive mismatch.
One thing to add :
The preview module (
preview/collection.js), which is what Nuxt Studio specifically uses for live editing, has its owngenerateCollectionInsertthat also callsgetOrderedSchemaKeysat line 90. This means the alphabetical sorting affects both the deployed website and the Studio preview pipeline.Suggested Fix
Remove the .sort() call from getOrderedSchemaKeys()?:
Object.keys() already returns keys in insertion order (per the ECMAScript spec), which is deterministic for a given schema definition. The sort is unnecessary for correctness and actively breaks the Nuxt Studio content comparison.
Alternatively, if deterministic ordering across different schema definitions is desired, the comparison logic in Nuxt Studio could be made key-order-agnostic (e.g., deep equality comparison ignoring key order).
Workaround
Reorder the top-level keys in all content JSON files to be alphabetical. This aligns the raw file with what the API returns, preventing the false mismatch. However, this requires manually maintaining alphabetical key order in every content file going forward.
Environment
@nuxt/content: 3.11.2
nuxt: 4.3.1
nuxt-studio: 1.4.0
Collection type: data (JSON)
Content storage: SQLite with sqliteConnector: 'native'