Content Engine

Publication & Editorial

Add draft/published lifecycles, revision histories, signed preview links, and scheduled publishing to content types.

Content Engine includes complete editorial workflows: draft and published states, historical revisions with one-click restore, signed reviewer preview URLs, and automated scheduled publishing.

Quick start

Enable publication, public API, and editorial workflows in your content type definition:

plugins/blog/src/content/post.ts
import { defineContentType, field } from "@vitnode/core/content"

export const blogPostContentType = defineContentType({
  id: "blog.post",
  tableName: "blog_posts",
  publication: { enabled: true },
  publicApi: {
    path: "/posts",
    fields: ["title"],
  },
  editorial: {
    enabled: true,
    revisions: { retention: 20 }, // Store up to 20 historical versions
    preview: { enabled: true, expiresInMinutes: 60 },
    scheduling: { enabled: true },
  },
  fields: {
    title: field.text({ required: true }),
  },
})

Editorial Features

1. Publication Lifecycle

When publication: { enabled: true } is configured:

  • Records carry a status column ("draft" or "published") and a publishedAt timestamp.
  • Unauthenticated public queries automatically filter out drafts, returning only records where status = "published".
  • Publishing is idempotent: the first publish stamps publishedAt, while subsequent edits preserve the original publication date.
  • The service exposes typed publish(id) and unpublish(id) methods.

2. Revision History

When editorial: { enabled: true } is configured:

  • Adds a version column to the database table (defaults to 1 and increments on each restore).
  • Each save stores an immutable snapshot in the centralized core_content_revisions table.
  • revisions.retention sets the maximum number of revisions kept per record (1–500, default: 50).
  • Editors can inspect diffs between any historical snapshot and the current record state.
  • One-click restore reinstates previous content while incrementing the version and emitting a content.${id}.restored event.

Share unpublished drafts with stakeholders who lack AdminCP accounts:

  • Prerequisite: publicApi must be configured on the content type, because preview projections rely on publicApi.fields.
  • Generates HMAC-signed URLs valid for a customizable duration (expiresInMinutes: 1–1440, default: 15).
  • Optional pathTemplate allows custom preview URL routing (e.g. "/preview/posts/{id}").
  • Public frontend routes verify the preview token and stream the draft.

4. Scheduled Publishing

Pick a future release date and time for automatic publishing or unpublishing:

  • Prerequisite: publication: { enabled: true } must be enabled.
  • The background cron worker checks scheduled items periodically.
  • Transitions records between draft and published at the specified timestamp and emits content.${id}.scheduled or content.${id}.schedule_cancelled events.

Configuration Reference

OptionTypeDefaultDescription
publication.enabledbooleanfalseEnables status and publishedAt lifecycle columns.
editorial.enabledbooleanfalseEnables version tracking and revisions.
editorial.revisions.retentionnumber50Maximum historical revisions preserved per item (1–500).
editorial.preview.enabledbooleanfalseEnables signed preview links. Requires publicApi.
editorial.preview.expiresInMinutesnumber15Expiration time for signed preview links in minutes (1–1440).
editorial.preview.pathTemplatestringCustom URL template for preview links.
editorial.scheduling.enabledbooleanfalseEnables scheduled publication/unpublication. Requires publication.enabled: true.

Learn More