Dyrecteddyrected
Core Concepts

Workflows

Learn how to configure states, capability gates, and custom editorial approval flows.

Workflows enable structured editorial lifecycles in your Dyrected collections. By activating workflows, updates to collection items do not immediately overwrite the live site data. Instead, changes are kept as a working draft and must step through transition gates (like submission, review, approval) before being promoted.


Defining a Workflow

To enable workflows on a collection, add the workflow property to its definition. Dyrected ships with a built-in editorial approval template called publishingWorkflow() which implements the standard draftin_reviewpublished path.

import { defineCollection, publishingWorkflow } from "@dyrected/core"

export const Articles = defineCollection({
  slug: "articles",
  // Activates the editorial approval workflow
  workflow: publishingWorkflow(),
  fields: [
    { name: "title", label: "Title", type: "text", required: true },
    { name: "content", label: "Content", type: "richText" },
  ],
})

State & Revision Model

When a collection is configured with a workflow:

  1. Working Drafts: Creating or editing an item updates its working draft revision. The current revision number is tracked in _workflow.revision.
  2. Promoted Snapshot: When the item transitions to a state marked as published: true (e.g. the 'published' state), Dyrected creates an atomic snapshot of the current working draft fields under a special __published namespace.
  3. Public vs. Working Views: Anonymous visitors and authenticated users without workflow capabilities are served fields from __published. Editors, publishers, and other users with workflow capabilities see the current working draft so they can continue editing without affecting the live site.

Custom Workflows

You can fully customize the workflow stages, transitions, required capabilities, and roles:

export const CustomWorkflow = {
  initialState: "draft",
  draftState: "draft",
  states: [
    { name: "draft", label: "Draft", color: "neutral" },
    { name: "in_review", label: "In review", color: "warning" },
    { name: "published", label: "Published", color: "success", published: true },
  ],
  transitions: [
    { name: "submit", label: "Submit for review", from: "draft", to: "in_review", requiredCapabilities: ["entry.submit"] },
    { name: "publish", label: "Publish", from: "in_review", to: "published", requiredCapabilities: ["entry.publish"] },
    { name: "reject", label: "Request changes", from: "in_review", to: "draft", requiredCapabilities: ["entry.publish"], requireComment: true },
    { name: "unpublish", label: "Unpublish", from: "published", to: "draft", requiredCapabilities: ["entry.unpublish"], unpublish: true },
  ],
  roles: [
    { role: "editor", capabilities: ["entry.edit", "entry.submit"] },
    { role: "publisher", capabilities: ["entry.edit", "entry.submit", "entry.publish", "entry.unpublish"] },
  ],
}

On this page