Features

Templates

Templates let admins save a set of field values from an existing document and reuse them as a starting point when creating new documents. When templates exist for a collection, the "New" button opens a picker so the author can choose between a blank document or any saved template.

When templates help

Templates are most valuable when your team publishes content that follows a repeating structure but still needs flexibility per document.

  • Recurring content patterns — Weekly newsletters, product pages, or event announcements often share the same field structure. A template pre-fills the boilerplate so authors only change what actually differs each time.
  • Onboarding new editors — New team members may not know which fields matter or what values are expected. A well-named template ("Standard product page", "Weekly recap") acts as an in-app guide.
  • Consistency without rigidity — Unlike mandatory field defaults, templates are suggestions. An author can accept the template values, override individual fields, or ignore the template and start blank. The schema still validates — templates just reduce blank-page friction.
  • Faster time-to-publish — Pre-filling common fields (status, category, layout choices) means fewer decisions before an author can start writing.

Templates vs. alternatives

ApproachWhen to use
TemplatesOpt-in starting points for new documents. Authors choose a template at create time; it does not affect existing documents.
Cloning an existing documentCopies all fields including content you may not want to carry over. Better when the new document is closely derived from a specific existing one.
Field defaults in codeApplied automatically to every new document regardless of context. Use for universal fallbacks, not for collection-specific patterns.
Collection presetsDeveloper-managed configuration baked into the schema. Templates are user-managed and can be created or updated without a code deploy.

Creating a template

Open any document in a collection and use the Save as Template option in the editor header actions menu. A dialog appears with three fields:

FieldRequiredDescription
Template nameYesA short, human-readable label shown in the picker (e.g. Blog post draft).
DescriptionNoOptional text shown below the name in the picker to help authors choose.
Set as default templateNoWhen checked, this template is pre-selected and shown with a "Default" badge.

Clicking Save template captures the current form values for all non-system fields and stores them against the collection.

Only one template per collection can be the default. Setting a new default does not automatically unset others — manage defaults explicitly via updateTemplate.

Set a default when most new documents in this collection follow the same structure — editors can still choose a different template or start blank.

Using templates

When one or more templates exist for a collection, clicking the New button on the collection list page opens the Create new document dialog instead of navigating directly. The dialog presents:

  • Blank document — opens the new document form with all fields empty.
  • One button per saved template — opens the new document form pre-filled with that template's field values. Default templates are marked with a "Default" badge.

Selecting a template appends ?templateId=<id> to the new document URL. The document edit page fetches the template and merges its fields map into the empty form, giving the author a head start.

Template values are applied only to new documents (isNew flag). Navigating to an existing document with a templateId query parameter has no effect.

Managing templates

Templates are stored per collection. Use the admin module API to list, update, or delete them programmatically or from custom UI.

Audit log

Every template operation is recorded in the audit log:

ActionTriggered by
template.createcreateTemplate mutation
template.updateupdateTemplate mutation
template.deletedeleteTemplate mutation

Admin module API

The following functions are available on the object returned by createVextroAdminModule.

listTemplatesForCollection

Returns all templates for a given collection, ordered by creation time.

const templates = await convex.query(api.listTemplatesForCollection, {
  collectionSlug: "posts",
});
// Array<AdminTemplate>

Args

ArgTypeDescription
collectionSlugstringThe collection to list templates for.

getTemplate

Returns a single template by ID, or null if not found.

const template = await convex.query(api.getTemplate, {
  templateId: "abc123",
});
// AdminTemplate | null

Args

ArgTypeDescription
templateIdstringThe ID of the template to fetch.

createTemplate

Creates a new template for a collection. Returns the new template ID.

const templateId = await convex.mutation(api.createTemplate, {
  name: "Blog post draft",
  description: "Standard layout with a title, body, and tags pre-filled.",
  collectionSlug: "posts",
  fields: {
    status: "draft",
    tags: ["general"],
  },
  isDefault: false,
});

Args

ArgTypeRequiredDescription
namestringYesDisplay name shown in the template picker.
descriptionstringNoShort description shown below the name.
collectionSlugstringYesThe collection this template belongs to.
fieldsRecord<string, unknown>YesMap of field names to pre-populated values.
isDefaultbooleanNoWhether this is the default template for the collection.

updateTemplate

Patches an existing template. All patch fields are optional.

await convex.mutation(api.updateTemplate, {
  templateId: "abc123",
  patch: {
    name: "Updated name",
    isDefault: true,
  },
});

Args

ArgTypeDescription
templateIdstringThe ID of the template to update.
patch.namestringNew display name.
patch.descriptionstringNew description.
patch.fieldsRecord<string, unknown>Replacement field values (replaces the entire map).
patch.isDefaultbooleanSet or unset the default flag.

deleteTemplate

Permanently deletes a template. This does not affect documents already created from it.

await convex.mutation(api.deleteTemplate, {
  templateId: "abc123",
});

Args

ArgTypeDescription
templateIdstringThe ID of the template to delete.

AdminTemplate type

type AdminTemplate = {
  _id: string;
  _creationTime: number;
  name: string;
  description?: string;
  collectionSlug: string;
  fields: Record<string, unknown>;
  createdBy: string;   // User ID of the admin who created the template
  createdAt: number;   // Unix timestamp (ms)
  updatedAt: number;   // Unix timestamp (ms)
  isDefault: boolean;
};
Previous
Webhooks