Layers

Scheduling

Automatic vs custom schedules, time zones, and the refresh commands.

View as Markdown

Find the schedule view at /project/{projectId}/dashboard/scheduled-posts (also reachable from the dashboard's Scheduled posts widget).

Automatic mode

Default. The social-distribution-plan workflow runs:

  • On config change — refresh-schedule fires automatically when any of distributionMode, willPublish, postsPerDay, schedule.times, contentLayerSourceIds, or generationMode change.
  • Nightly — refresh-schedule-scheduled runs on cron 0 3 * * * UTC.

Each run:

  1. Loads the project's timezone.
  2. Validates the connected social account.
  3. Loads the latest health snapshot (if any) to pick an account "temperature" — cold (1 slot/day at 10:00), warm (2 slots at 10:00 + 15:00), hot (3 slots at 10:00 + 15:00 + 19:00).
  4. Computes slots for a dynamic horizon — max(3 days, ceil(availableContent / slotsPerDay)).
  5. Upserts scheduled_posts rows for each slot.
  6. Attaches ready content_containers to the earliest empty slots.
  7. Optionally requests content generation to fill remaining gaps when generationMode = "automatic".

Custom schedule

Set distributionMode: "custom" and supply times as HH:MM in the project timezone:

{
  "distributionMode": "custom",
  "schedule": {
    "times": ["09:00", "13:00", "18:00"]
  }
}

Only 24-hour HH:MM entries are supported (no day-of-week syntax). postsPerDay equals schedule.times.length; allowed range is 1–5.

Manual mode

distributionMode: "manual" — the planner creates zero slots. Use this if you want to hand-pick every schedule in the UI.

Time zones

The project timezone determines slot computation. The planner converts local HH:MM values to UTC before writing scheduled_posts.scheduled_at. Changing the project timezone later does not shift already-scheduled posts.

Refresh-schedule command

refresh-schedule runs social-distribution-plan immediately. Invoke it from the layer's Commands panel after changing config if you don't want to wait for the onConfigChange effect.

Recover overdue

recover-overdue runs every 5 minutes and re-slots any ready or failed post whose scheduled_at has passed. YouTube posts (dormant platform) are explicitly skipped.

On this page