Skip to content

Astro Starter

The Astro Starter utilizes Hybrid Rendering, enabling lightning-fast static page delivery while maintaining a dynamic preview system and on-demand cache revalidation.

1. Preview Implementation (src/pages/api/preview.ts)

Section titled “1. Preview Implementation (src/pages/api/preview.ts)”

This endpoint handles the second step of the Handshake – verifying the signature with the backend and setting the session cookie.

import type { APIRoute } from "astro";
export const GET: APIRoute = async ({ request, cookies, redirect }) => {
const url = new URL(request.url);
const path = url.searchParams.get('path') || '';
const expires = url.searchParams.get('expires');
const signature = url.searchParams.get('signature');
const internalUrl = import.meta.env.INTERNAL_API_URL;
const verifyUrl = `${internalUrl}/api/preview/verify?path=${path}&expires=${expires}&signature=${signature}`;
try {
const response = await fetch(verifyUrl);
const data = await response.json();
if (!response.ok || !data.valid) {
return new Response('Nieprawidłowa sygnatura z backendu', { status: 403 });
}
cookies.set('pyxis_preview', data.preview_token, {
path: '/',
httpOnly: true,
sameSite: 'lax',
maxAge: 3600
});
const redirectPath = (path === 'homepage' || path === '') ? '/' : `/${path}`;
return redirect(redirectPath);
} catch (e) {
return new Response('Błąd połączenia z API: ' + e.message, { status: 500 });
}
}

2. Data Fetching (src/pages/[…path].astro)

Section titled “2. Data Fetching (src/pages/[…path].astro)”

The primary routing engine that forwards the preview token in the API request header.

---
const { path } = Astro.params;
const previewToken = Astro.cookies.get('pyxis_preview')?.value;
const INTERNAL_API = import.meta.env.INTERNAL_API_URL;
const fetchUrl = path ? `${INTERNAL_API}/api/pages/${path}` : `${INTERNAL_API}/api/pages`;
const res = await fetch(fetchUrl, {
headers: {
'Accept': 'application/json',
...(previewToken ? { 'X-Pyxis-Preview': previewToken } : {})
}
});
if (!res.ok) return Astro.redirect('/404');
const { data } = await res.json();
---

3. Instant Revalidation (src/pages/api/revalidate.ts)

Section titled “3. Instant Revalidation (src/pages/api/revalidate.ts)”

An endpoint that receives the “Publish” signal from the CMS, allowing for immediate server-side cache invalidation.

import type { APIRoute } from "astro";
export const POST: APIRoute = async ({ request }) => {
try {
const body = await request.json();
const { path, secret } = body;
// Check if secret token is valid
// Set REVALIDATE_TOKEN in both apps
if (secret !== import.meta.env.REVALIDATE_TOKEN) {
return new Response(JSON.stringify({ message: "Invalid token" }), {
status: 401,
});
}
if (!path) {
return new Response(JSON.stringify({ message: "Path is required" }), {
status: 400,
});
}
console.log(`[Revalidate] Refreshing path: ${path}`);
return new Response(JSON.stringify({
revalidated: true,
now: Date.now(),
path: path
}), {
status: 200,
});
} catch (err) {
return new Response(JSON.stringify({ message: "Error revalidating" }), {
status: 500,
});
}
};