feat(preview): consume rustycms live-preview drafts
`?preview_draft=<sid>` on any page/post route forwards the signed session id to the CMS, which renders the in-memory draft instead of the persisted entry. Layout listens for `rustycms:reload` postMessages from the admin iframe parent and re-runs `invalidateAll()` to pick up fresh draft state. CSP `frame-ancestors` is set per-request when `PUBLIC_PREVIEW_PARENT_ORIGIN` is configured so the admin iframe can embed the response. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -27,8 +27,9 @@ export const load: PageServerLoad = async ({ params, locals, fetch, url, setHead
|
||||
const { slug } = params;
|
||||
const translations = locals.translations ?? {};
|
||||
const preview = url.searchParams.get('preview') ?? undefined;
|
||||
const previewDraft = url.searchParams.get('preview_draft') ?? undefined;
|
||||
|
||||
if (preview) {
|
||||
if (preview || previewDraft) {
|
||||
setHeaders({
|
||||
'cache-control': 'private, no-store, max-age=0',
|
||||
'x-robots-tag': 'noindex, nofollow',
|
||||
@@ -42,6 +43,7 @@ export const load: PageServerLoad = async ({ params, locals, fetch, url, setHead
|
||||
// Levels). Kein Body-Stripping hier — Page-Detail braucht alle Felder.
|
||||
depth: 3,
|
||||
preview,
|
||||
previewDraft,
|
||||
});
|
||||
|
||||
if (!page) {
|
||||
@@ -91,6 +93,7 @@ export const load: PageServerLoad = async ({ params, locals, fetch, url, setHead
|
||||
page,
|
||||
translations,
|
||||
preview: !!preview,
|
||||
previewDraft: !!previewDraft,
|
||||
seoTitle: page.seoTitle ?? page.headline ?? page.linkName ?? slug,
|
||||
seoDescription: page.seoDescription ?? page.subheadline ?? '',
|
||||
robots: (page as { seoMetaRobots?: string }).seoMetaRobots ?? undefined,
|
||||
|
||||
Reference in New Issue
Block a user