Filter draft/scheduled posts out of public blog fetches

getBlogPosts()/getPostBySlug() now only return status='published' posts
for normal requests — draftMode's live preview passes {draft:true} to
bypass it, same as before. Backend-side scheduling in the payload repo
(status/scheduledPublishAt + a per-minute autopublish job).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-29 23:10:07 +00:00
parent c852752006
commit c83bbfbc35
+9
View File
@@ -49,6 +49,11 @@ type PayloadPost = {
export async function getBlogPosts(limit = 3): Promise<BlogPost[]> {
const params = new URLSearchParams({
"where[tenant.slug][equals]": TENANT_SLUG,
// Draft/scheduled posts never appear publicly — same "filter, not
// access-control" pattern as Products.active. Live preview
// (LivePostContent.tsx) bypasses this entirely since it fetches the
// one specific document by id directly, not through this list.
"where[status][equals]": "published",
sort: "-featured,-publishedAt",
depth: "2",
limit: String(limit),
@@ -144,6 +149,10 @@ export async function getPostBySlug(slug: string, options?: { draft?: boolean })
depth: "2",
limit: "1",
});
// Draft/scheduled posts 404 for a normal visitor — draftMode's preview
// (options.draft, wired from the page's own draftMode() call) is the
// one legitimate way to view one before its scheduledPublishAt fires.
if (!options?.draft) params.set("where[status][equals]", "published");
const res = await fetch(`${PAYLOAD_URL}/api/posts?${params}`, livePreviewCacheOption(Boolean(options?.draft)));
if (!res.ok) {