Builds

How did we publish 701 decision pages to Sanity at agent scale?

Short answer

Deploi published 701 Build vs. Buy decision pages to Sanity by having AI agents write one document per page, with slug-based IDs and weak references. From wave 5, developers imported each wave of about 100 pages as a pack they could check and roll back by ID list. Sanity runs validation rules only in Sanity Studio, not on imports (Sanity Docs, October 2026), so Deploi gates each wave.

Documents per page
About 4.4, counted 24 October 20263,057 documents across five types for 701 decision pages (Deploi arithmetic from the figures above)
Document quota
10,000 on Free, 25,000 on GrowthGrowth goes to 50,000 with the Increased quota add-on at $299 a month; drafts count toward the maximum, as of October 2026Sources: Sanity (Plans that scale with you); Sanity Docs (Technical limits)
Validation on imports
None: Studio rules don't run thereImports, migrations and API writes are accepted without schema checks; sanity documents validate checks a dataset afterwardsSources: Sanity Docs (Schema validation and the Content Lake, Import data)
Reference order
Any order, with weak referencesA weak reference may point at a document that isn't published yet or was deleted, so it never blocks a push and never flags a gapSources: Sanity Docs (Reference, Import data)

Deploi’s call

Model each page as one document, derive every ID from its slug, make every reference weak, and ship in waves a developer can undo by ID list. Then spend as much effort on the checks as on the content, because this design removes exactly the errors that would have stopped a bad push.

ReuseReuse one Sanity document per page, with slug-based IDs and weak references, when

  • Dozens or hundreds of pages share one anatomy that fits in one document type.
  • Prices, names or statuses repeat across pages and can live in one referenced document, so one edit reaches every page that joins it.
  • Developers can own a wave package with an ID list, count checks and a rollback.
  • You can run a dangling-reference check and a seed-to-dataset diff after every push, because Sanity does not check imported documents against schema validation rules as of October 2026.

AvoidAvoid this Sanity pattern when

  • Pages are one-off layouts that editors compose by hand.
  • Agents would write straight to production with no review dataset or ID list.
  • Nobody re-verifies the shared records that every page joins.

What did we publish, and why one document per page?

Deploi published the Build vs. Buy hub on deploi.ca as 701 capabilityDecision documents in Sanity, one per page, counted in the production dataset on 24 October 2026. Each page answers one Shopify capability decision: buy an app, build, customize or wait. The document's field groups (core, verdict, evidence, conversion, ops) mirror the page's sections, so a complete, valid document is a complete page and nobody assembles it afterwards. That's what makes agent authoring safe: an agent fills fields, never layouts. Shared facts sit in their own document types:

701 pages take 3,057 documents, about 4.4 per page (Deploi arithmetic from the counts in this table)
Document typeCountWhat it holds
capabilityDecision701One page: verdict, scenario bands, a 12-dimension cost and risk score, FAQs
capability701The capability the page decides on
appProfile1,528, of which 5 are draftsApp name, status and price, stored once
verdictChange100One dated verdict change each, never edited
bvbDomain27The domain hubs that group decisions

The pages also carry 2,103 FAQ sub-questions as arrays inside the decision documents, not as separate documents, so they add nothing to the document count. The programmatic pages use case covers when this kind of hub pays off.

How do deterministic IDs and weak references make agent pushes safe?

Deterministic IDs make a push repeatable, and weak references make it order-free. Every document ID is built from a slug, so the same content pushed twice lands on the same ID instead of creating a duplicate:

  • bvb.<slug> for a decision page, capability.<slug> for its capability
  • app.<slug> for an app profile, bvbDomain.<slug> for a domain
  • vc.<decision-slug>.<yyyy-mm-dd> for a verdict change

The Sanity command-line interface (CLI) import overwrites a matching document with --replace and otherwise stops with an error (Sanity Docs, Import data, October 2026).

Every reference in the schema is weak: true. Sanity's reference type lets a weak reference point to "a document that has not yet been published or one that has been deleted" (Sanity Docs, Reference, October 2026), so an agent can push a decision before its app profile exists. The same import already handles order for strong references by importing them weak and strengthening them afterwards (Sanity Docs, Import data, October 2026). We keep them weak for a second reason: "A published document can't hold a strong reference to unpublished content" (Sanity Docs, Drafts and versions, October 2026), and agent-written corrections land as drafts. A draft is just a drafts. prefix on the decision's ID, while references keep pointing at published IDs. The cost is silence: a weak reference to a missing document fails nothing, so a check has to find it.

How do 701 pages stay consistent with GROQ joins?

Facts that many pages share live once and join at query time with GROQ (Graph-Relational Object Queries). A decision stores only why an app fits; the app's name, status and price come from its appProfile through a reference, so a quarterly price check edits one document and every page that references it updates. The change log runs the other way: each verdict change is its own dated document, and the page query finds them by reverse reference.

"apps": appLandscape[]{
  "name": app->name,
  "status": app->status.label,
  "url": app->listingUrl,
  "statusNote": app->status.note,
  "pricing": app->pricing.summary,
  bestFor
},
"changeLog": *[_type == "verdictChange" && decision._ref == ^._id] | order(date desc){
  "date": date, "from": fromVerdict, "to": toVerdict, note
},
Part of the decision page query, from Deploi's frontend code (sanity/bvbQueries.js)

Across the hub, 701 decisions carry 2,401 app rows that resolve this way, counted 24 October 2026. The same fields feed structured data: each page's JSON-LD Article.description is the capsule field, copied verbatim, so the visible answer and the markup can't drift. JSON-LD from fields covers that build, and the GROQ feature review covers joins in general.

How does a content wave reach production?

A content wave reaches production as a package that developers import, check and can undo. Agents wrote waves 5 to 8 to a scratch dataset, since deleted, and developers imported them; agent-written corrections now land in production as drafts for a person to publish. Agents authored about 100 pages per wave and pushed them through Sanity's MCP (Model Context Protocol) server into that dataset for review. Schema changes deploy through the Sanity command-line interface (CLI), never the MCP deploy tool.

Agent authoringScratch datasetWave packProduction datasetChecksRollbackdocuments with deterministic IDsnewline-delimited JSON (NDJSON) and a list of new IDsCLI import, waves in orderdocument counts and reference checksdelete the listed IDs if a check fails
Agents write to a review dataset; developers move a checked package to production

The checks can't be left to the schema. On imports and API (application programming interface) writes "the Content Lake accepts the write without checking your validation rules" (Sanity Docs, Schema validation and the Content Lake, October 2026). Some MCP tools are schema-aware, but the Content Lake does not check writes (Sanity Docs, Schema validation and the Content Lake). So each wave clears Deploi's own gates before packing: wave 8 passed lint on 101 of 101 pages and two page audits with 0 findings (5 September 2026). Rollback is deleting the pack's listed IDs, which works because the wave 8 pack added documents and modified none. See safe release scripts and the datasets review.

What went wrong when we published 701 pages to Sanity, and how did we fix it?

Three things went wrong in Deploi's agent publishing to Sanity, all from design choices that make pushes fast.

  • One bad source multiplied across pages. A 15 September 2026 root-cause report found 177 auto-generated app profiles whose format collapsed annual and per-order pricing into one fake monthly range. Pages join prices from those profiles, so every page that used them inherited the error. Corrected profiles go back as drafts for a person to publish; 5 awaited review on 24 October 2026.
  • A delta check missed documents. The first wave 8 push left 97 of 101 new pages with dangling app references: the delta calculation skipped two kinds of app profile the seed generator makes. A seed-to-dataset diff found 140 missing documents, and the dataset then matched the seed at 3,052 (Deploi's wave 8 quality report, 5 September 2026).
  • Finished waves sat unpublished. Waves 5 to 7 waited in the scratch dataset while production showed 300 pages, so none could rank. All 701 were live by 24 October 2026.

How many pages like these fit in your Sanity document quota?

A Sanity Growth plan holds about 5,700 pages built this way: its 25,000 included documents divided by this hub's ratio of about 4.4 documents per page, before drafts or other content (Deploi arithmetic from the figures above). Size the count first, because Sanity's quota counts documents across all datasets in a project (Sanity pricing, October 2026), and "Drafts, release versions, and documents created by plugins count toward the maximum" (Sanity Docs, Technical limits, October 2026). The Free and Growth plans include 2 datasets, so a scratch dataset takes the second one (Sanity pricing, October 2026).

Pages that fit each plan's documents at 4.4 documents per page (Deploi arithmetic)
PlanDocuments includedPages at 4.4 documents per page
Free10,000About 2,300
Growth25,000About 5,700
Growth with the Increased quota add-on, $299 a month50,000About 11,400
EnterpriseCustomNot published
Free has no document add-on. Enterprise quotas are custom.Source: Sanity (Plans that scale with you). As of 24 October 2026.

Deploi’s point of view

Where we disagree
Programmatic content advice treats scale as a template problem: build one layout and pour rows in. The harder problem is provenance. A shared record that's wrong is wrong on every page that joins it, and weak references let missing records through without an error. The second mistake is trusting schema validation to guard agent writes. Sanity runs it in the Studio, not on imports or API writes, so the gates have to live in your pipeline.
What we’ve seen
deploi.ca's Build vs. Buy hub runs 701 decision pages from 3,057 documents across five types, counted 24 October 2026. Our wave 8 push on 5 September 2026 left 97 of 101 new pages with dangling app references until a seed-to-dataset diff found 140 missing documents. A 15 September 2026 root-cause report traced pricing errors to 177 auto-generated app profiles whose format turned annual and per-order prices into monthly ranges. Waves 5 to 7 also waited in a scratch dataset while only 300 pages were live.
What we'd tell you to do first
Write the ID convention and the rollback list format before the first page. Both cost minutes on day one and are painful to retrofit once agents have pushed a few thousand documents.

When this answer changes

  • Sanity validates schema rules on imports or API writes
  • Sanity adds a bulk publish command to the CLI
  • Sanity changes the document quotas or the $299 Increased quota add-on
  • The Sanity MCP server changes how agents create or publish documents
  • Deploi moves app prices off the shared app profiles or passes 1,000 decision pages

Sources

Every source opened and checked on 25 October 2026.

  1. Sanity Docs, Import datasanity.io · checked 24 October 2026
  2. Sanity Docs, Referencesanity.io · checked 24 October 2026
  3. Sanity Docs, Schema validation and the Content Lakesanity.io · checked 24 October 2026
  4. Sanity, Plans that scale with yousanity.io · checked 24 October 2026
  5. Sanity Docs, Technical limitssanity.io · checked 24 October 2026
  6. Sanity Docs, Drafts and versionssanity.io · checked 24 October 2026