AstroBaaS

Reviews & social proof

Draft & Preview

Free — GPL coresize Splanned, not built

Generated from docs/plan/core/draft-preview/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Merchants can save product, page, and collection changes as unpublished drafts, preview them before going live, and publish safely. This core feature prevents costly published mistakes by moving the point of no-return from save to publish.

The problem

When every change goes live immediately, merchants make typos, pricing errors, or wrong descriptions that damage credibility and lose sales until manually fixed. They need a way to compose, review, and approve changes before customers see them.

What it does

  • Add draft/published state machine to products, pages, collections, and settings
  • Save changes to draft without affecting live version
  • Preview draft in storefront context using temporary token
  • Promote draft to published (sets publishedAt timestamp)
  • Revert published version to draft state
  • Exclude drafts from all storefront GET endpoints and search indexes
  • Show draft status and publish button in admin UI for all content types
  • Preserve audit trail: who saved draft, when, and who published, when
  • Permission gate: can edit draft without publish permission
  • Support drafts across all storage drivers (lowdb, libSQL, relational)

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Scheduled publishing (requires scheduler integration and a separate publish-at timestamp; that’s a different capability)
  • Collaborative editing locks (adds concurrency state; out of scope for initial delivery)
  • Draft versioning or history beyond the current draft (belongs with a full content version system)
  • Multi-language draft workflows (language complexity is orthogonal; each locale has its own draft)
  • Draft approval workflows with roles/queues (that’s workflow automation, separate feature)

Data model

Add nullable publishedAt: DateTime and status: 'draft' | 'published' enum to products, pages, collections, settings schema. This is a schema migration for existing content (backfill publishedAt = createdAt, status = ‘published’ for live data).

API

  • POST /admin/products — accepts { status: ‘draft’ } to create unpublished
  • PATCH /admin/products/:id — change status field or content; draft changes do not affect published
  • POST /admin/products/:id/preview — returns draft content as if published, for admin preview
  • GET /storefront/products/:id?_preview=token — returns draft IF token is valid; used for shareable previews
  • GET /storefront/products — storefront list returns only where status=‘published’ AND publishedAt <= now
  • GET /admin/products/:id — returns both draft and published state for editor
  • POST /admin/products/:id/publish — transitions draft → published, sets publishedAt = now

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Content editor shows status badge (‘Draft’, ‘Published’). Draft view shows unpublished changes. Publish button appears on draft cards. Clicking Publish transitions to live with confirmation. Revert to Draft button on published items. Admin can preview draft in a read-only storefront panel. Audit log records every publish event with actor and timestamp.

The seam — why this is core

Core owns the draft state machine, storage of status and publishedAt, preview token validation, and audit logging. No paid involvement—this is honest CRUD infrastructure, not a credential or external dependency.

Core owns the interface + honest implementation; draft state is a basic CRUD feature, not a support commitment.

Dependencies

  • Product, page, and collection schemas must support status enum and publishedAt field
  • Assumes audit log system exists to record publish events
  • Preview token generation (can use short-lived JWT or random string in cache)
  • Storefront query filters must exclude drafts from all public endpoints

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • A product with status=‘draft’ does NOT appear in GET /storefront/products or any storefront search
  • A product with status=‘published’ and future publishedAt does NOT appear in storefront (even if published)
  • Publishing a draft sets status=‘published’ and publishedAt to current timestamp
  • Reverting published to draft preserves all content and sets status=‘draft’
  • Audit log shows the actor, action (publish/revert), timestamp, and product ID
  • A user without ‘products.publish’ permission can PATCH and save but cannot transition status from draft to published
  • Preview token is valid for 24 hours and tied to one product ID
  • Editing a draft does not update the live version until publish

Risks

If storefront queries do not filter by status, drafts leak to customers. If publishedAt migration does not backfill existing products, they vanish from storefronts. If preview tokens are never invalidated on publish, old preview URLs remain accessible. Race condition if two admins publish the same draft simultaneously.

Commercial context

Suggested pricefree (core)
Rival anchorShopify: included; Magento: included

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.