Blocks

Reference Tracking

Vextro automatically tracks which documents reference each block. This prevents orphaned blocks and warns editors when changes affect multiple documents.

How tracking works

Every block stores a usedIn array that records each document referencing it. When a document is created or updated, syncBlockUsageForDocument() compares the previous block references against the new set. It patches each affected block's usedIn array -- adding entries for newly referenced blocks and removing entries for blocks that were unlinked. When a document is deleted or restored, all referenced blocks are updated accordingly.

Each usedIn entry has this structure:

{
  collection: "pages",        // collection slug
  tableName: "pages",         // Convex table name
  documentId: "pages:abc123", // ID of the referencing document
  field: "content"            // field name containing the reference
}

A block with an empty usedIn array is unreferenced and can be safely cleaned up.

Referenced By sidebar

When editing a block in the admin UI, the sidebar displays a "Referenced By" section listing every document that uses the block. Each entry is a clickable link that navigates to the referencing document's edit page. This gives editors immediate visibility into where a block appears across the site.

Multi-use confirmation

When a block is used by two or more documents, saving changes to that block triggers a confirmation dialog. The dialog lists every affected document with links that open in a new tab so editors can review them without losing unsaved work. The total count of affected documents is shown at the top of the dialog. The editor must click "Save Anyway" to proceed or "Cancel" to go back and review.

Shared block edits

Changes to a shared block affect every document that references it. The confirmation dialog exists specifically to prevent accidental updates across the site. Encourage editors to review the affected documents before confirming.

Reordering

Editors can drag blocks to reorder them within a blocks field. The order values on each block reference are recalculated when the document is saved, ensuring consistent sequential ordering starting from 0.

Custom field names

By default, block references use blockType, blockId, and order as field names. You can override these with the fieldNames option:

export const pages = defineVextroCollection({
  label: "Pages",
  collectionType: "content",
  tableName: "pages",
  fields: {
    content: f.blocks([hero, cta], {
      fieldNames: {
        blockType: "type",
        blockId: "ref",
        order: "position",
      },
    }),
  },
});

This changes the stored reference shape to { type, ref, position } instead of the defaults. Use this when integrating with existing data structures or when you prefer different naming conventions.

Previous
Nested Blocks