---
title: "PDFs in Astro mit Cloudflare Browser Rendering am Edge generieren"
description: "Erfahren Sie, wie Sie Rechnungen, Berichte und OG-Bilder als PDFs direkt aus Ihren Astro-Seiten mit Cloudflare Browser Rendering erzeugen. Headless Chromium am Edge ausführen, Print-CSS anwenden und PDFs mit minimaler Latenz streamen."
source: "https://www.launchfa.st/de/blog/astro-cloudflare-browser-rendering-pdf"
author: "Rishi Raj Jain"
created_at: 2025-12-08T13:00:00.000Z
keywords: "astro, cloudflare, browser rendering, pdf, chromium, print css, edge computing"
---

> **Site index for agents**
> Fetch https://www.launchfa.st/llms.txt to discover every page on this site.
> Every page is also available as Markdown by appending `.md` to its URL.

<img width="1600" height="900" alt="Generating PDFs in Astro with Cloudflare Browser Rendering at the Edge" decoding="async" loading="eager" class="mt-4 border rounded-sm bg-cover bg-center bg-no-repeat transform will-change-auto" src="https://ik.imagekit.io/vjeqenuhn/launchfast-website/astro-cloudflare-browser-rendering-pdf.png" />

Die serverseitige PDF-Erzeugung bedeutet oft Lambda-Cold-Starts, Chromium-Binaries oder Drittanbieter-APIs mit extra Latenz und Kosten. Wer schon einmal einen Docker-Container mit über 1 GB nur für HTML-zu-PDF gestartet hat, kennt das Problem.

[Cloudflare Browser Rendering](https://developers.cloudflare.com/browser-rendering/) dreht dieses Modell um: ein verwalteter Headless-Chromium-Dienst auf Cloudflares Edge-Netzwerk, keine Binaries, keine Cold-Starts, keine Docker-Layer. Sie erhalten Puppeteer-kompatible APIs mit Startzeiten unter 100 ms, global verteilt.

In dieser Anleitung bauen Sie ein produktionsreifes PDF-System mit Astro, Cloudflare KV und Cloudflare Workers. Sie erstellen druckbare Belegseiten mit eigenem CSS, verdrahten einen API-Endpunkt, der Headless Chrome am Edge startet, und cachen die Ergebnisse in Cloudflare KV, um doppeltes Rendering zu vermeiden.

- [Beispielprojekt auf GitHub ansehen](https://github.com/rishi-raj-jain/my-astro-kv-pdf-app)

## Voraussetzungen

Sie benötigen:

- [Node.js 20](https://nodejs.org/en/blog/announcements/v20-release-announce) oder höher
- Ein [Cloudflare](https://dash.cloudflare.com/sign-up)-Konto

## Warum Cloudflare Browser Rendering für PDFs?

- **Kein Chromium-Pflegeaufwand**: Cloudflare betreibt und patcht Headless Chromium für Sie.
- **Edge-Nähe**: PDFs nahe am Anfragenden rendern, ideal für Dashboards, Rechnungen und OG-Bilder.
- **Streaming**: PDFs direkt aus dem Worker senden, ohne temporäre Dateien.
- **Kostenbewusst**: Nutzungsbasierte Abrechnung ohne eigene Renderer-Flotte.

## Architekturüberblick

```
1. Astro-Seite (src/pages/receipt/[id].astro)
   → SSR-Route mit Beleg-/Rechnungs-HTML + Print-CSS

2. PDF-API (src/pages/api/pdf/[id].ts)
   → Browser-Rendering-Session starten
   → Astro-Route-URL laden
   → page.pdf() aufrufen und Binary streamen

3. Cloudflare-Adapter + Browser-Binding
   → Astro auf Workers/Pages deployen
   → BROWSER-Binding für den Worker bereitstellen
```

## Neue Astro-Anwendung erstellen

Starten Sie mit einem neuen Astro-Projekt. Führen Sie aus:

```bash
npm create astro@latest my-astro-kv-pdf-app
cd my-astro-kv-pdf-app
npm install wrangler @cloudflare/puppeteer
```

Wählen Sie bei den Prompts:

- `Use minimal (empty) template`, wenn gefragt wird, wie das Projekt starten soll.
- `Yes`, wenn Abhängigkeiten installiert werden sollen.
- `Yes`, wenn ein Git-Repository initialisiert werden soll.

Danach ins Projektverzeichnis wechseln und die App starten:

```bash
npm run dev
```

Die App läuft unter [localhost:4321](http://localhost:4321/).

## Cloudflare-Adapter in Ihr Astro-Projekt integrieren

Für Cloudflare Workers und Cloudflare KV installieren Sie den Cloudflare-Adapter:

```bash
npx astro add cloudflare --yes
```

Setzen Sie in `astro.config.mjs` **output** auf **server**:

```javascript
// File: astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  output: 'server',
  adapter: cloudflare()
});
```

## Browser Rendering in wrangler.jsonc konfigurieren

Fügen Sie ein BROWSER-Binding hinzu, damit der Worker Headless Chromium starten kann:

```jsonc
// File: wrangler.jsonc
{
	"main": "dist/_worker.js/index.js",
	"name": "my-astro-kv-pdf-app",
	"compatibility_date": "2025-12-06",
	"compatibility_flags": [
		"nodejs_compat",
		"global_fetch_strictly_public"
	],
	"assets": {
		"binding": "ASSETS",
		"directory": "./dist"
	},
	"observability": {
		"enabled": true
	},
	"browser": {
		"binding": "BROWSER"
	}
}
```

> Der Block `browser` stellt Cloudflares Browser-Rendering-Dienst bereit und macht ihn als `env.BROWSER` im Worker verfügbar.

## KV für Caching hinzufügen

Erstellen Sie einen KV-Namespace für generierte PDFs:

```bash
npx wrangler kv namespace create PDF_CACHE
```

Die Ausgabe enthält eine `id` für `wrangler.jsonc`. Ergänzen Sie das KV-Binding:

```jsonc
// File: wrangler.jsonc
{
	"main": "dist/_worker.js/index.js",
	"name": "my-astro-kv-pdf-app",
	"compatibility_date": "2025-12-06",
	"compatibility_flags": [
		"nodejs_compat",
		"global_fetch_strictly_public"
	],
	"assets": {
		"binding": "ASSETS",
		"directory": "./dist"
	},
	"observability": {
		"enabled": true
	},
	"browser": {
		"binding": "BROWSER"
	},
	"kv_namespaces": [
		{
			"binding": "PDF_CACHE",
			"id": "generated-id",
			"remote": true
		}
	]
}
```

## TypeScript-Typen hinzufügen

Erstellen Sie `src/env.d.ts` für die Cloudflare-Bindings:

```typescript
// File: src/env.d.ts
/// <reference types="astro/client" />

type KVNamespace = import('@cloudflare/workers-types').KVNamespace

type ENV = {
  PDF_CACHE: KVNamespace
  BROWSER: Fetcher
}

type Runtime = import('@astrojs/cloudflare').Runtime<ENV>

declare namespace App {
  interface Locals extends Runtime {}
}
```

Damit sind `locals.runtime.env.PDF_CACHE` und `locals.runtime.env.BROWSER` in Ihren Routen typisiert.

## Druckbare Astro-Seite erstellen

Belegseite mit druckfreundlichen Styles:

```astro
---
const { id } = Astro.params;
const order = {
  id,
  customer: 'Ada Lovelace',
  total: '$128.00',
  items: [
    { name: 'Edge Functions', price: '$50.00' },
    { name: 'PDF Rendering', price: '$78.00' }
  ]
};
---

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Receipt #{order.id}</title>
    <style>
      :root { font-family: 'Inter', system-ui, -apple-system, sans-serif; }
      body { margin: 0; padding: 32px; color: #0f172a; }
      header { display: flex; align-items: center; justify-content: space-between; }
      table { width: 100%; border-collapse: collapse; margin-top: 24px; }
      th, td { padding: 12px 8px; text-align: left; border-bottom: 1px solid #e2e8f0; }
      .total { text-align: right; font-size: 1.125rem; font-weight: 700; }
      @page { margin: 24mm; }
      @media print {
        body { background: white; }
        a[href]::after { content: ''; }
      }
    </style>
  </head>
  <body>
    <header>
      <div>
        <h1>Receipt #{order.id}</h1>
        <p>Issued to {order.customer}</p>
      </div>
      <strong>launchfa.st</strong>
    </header>
    <table>
      <thead>
        <tr><th>Item</th><th>Price</th></tr>
      </thead>
      <tbody>
        {order.items.map(item => (
          <tr>
            <td>{item.name}</td>
            <td>{item.price}</td>
          </tr>
        ))}
      </tbody>
    </table>
    <p class="total">Total: {order.total}</p>
  </body>
</html>
```

Speichern als `src/pages/receipt/[id].astro`. Das Print-CSS (`@page`) setzt Ränder; `@media print` entfernt störende Link-Dekorationen.

## PDF-API-Route erstellen

Worker-API-Route mit Cloudflare Browser Rendering: PDF aus der Astro-HTML-Belegseite erzeugen und cachen.

Unter `src/pages/api/pdf/[id].ts`:

- prüfen, ob ein PDF in Cloudflare KV liegt, und es sofort zurückgeben
- bei Cache-Miss Headless-Browser über Browser Rendering starten
- zur druckbaren Seite navigieren und PDF erzeugen
- PDF sieben Tage in KV speichern

```typescript
// File: src/pages/api/pdf/[id].ts
import type { APIRoute } from "astro";
import puppeteer from "@cloudflare/puppeteer";

// Helper to create a proper PDF HTTP response
const pdfResponse = (pdf: Buffer<ArrayBuffer>, id: string) => {
    return new Response(pdf, {
        headers: {
            'Content-Type': 'application/pdf',
            'CDN-Cache-Control': 'max-age=604800',
            'Content-Disposition': `inline; filename="receipt-${id}.pdf"`
        }
    });
}

export const GET: APIRoute = async ({ locals, params, request }) => {
    const id = params.id as string;
    const origin = new URL(request.url).origin;
    const targetUrl = `${origin}/receipt/${id}`;
    const cache = locals.runtime.env.PDF_CACHE;

    // Try KV cache first to avoid unnecessary browser work
    const cachedPdf = await cache.get(targetUrl, "arrayBuffer");
    if (cachedPdf)
        return pdfResponse(Buffer.from(cachedPdf), id);

    // Only run browser in Cloudflare's env
    if (!locals.runtime.env.BROWSER)
        return new Response('Browser binding not available locally', { status: 501 });

    // Launch browser and render HTML to PDF
    const session = await puppeteer.launch(locals.runtime.env.BROWSER);
    const page = await session.newPage();
    await page.goto(targetUrl, { waitUntil: 'networkidle0' });
    const pdf = await page.pdf({
        format: 'A4',
        printBackground: true,
        margin: { top: '24mm', right: '18mm', bottom: '24mm', left: '18mm' }
    });
    await session.close();

    const result = Buffer.from(pdf);
    // Cache for a week (604800 seconds)
    await cache.put(targetUrl, result, { expirationTtl: 60 * 60 * 24 * 7 });
    return pdfResponse(result, id);
};
```

Unter `/api/pdf/123` erhalten Sie ein live aus `/receipt/123` erzeugtes PDF. Folgeanfragen liefern das gecachte PDF bis zum Ablauf.

## PDFs schützen und cachen

- **Auth**: Vor dem Rendern [Session-Token oder signierte Query-Strings](/blog/implement-basic-authorization-astro) verlangen. Unauthentifizierte Anfragen früh ablehnen.
- **Caching**: Statische Rechnungen kurz cachen (`Cache-Control: public, max-age=300`). Dynamische Inhalte privat halten.
- **Rate Limits**: Bei hohem Traffic einen [Rate Limiter (KV)](/blog/rate-limiting-astro-cloudflare-workers) ergänzen.

## Auf Cloudflare Workers deployen

```bash
# Build the project
npm run build

# Deploy to Cloudflare Workers
npx wrangler deploy
```

Nach dem Deploy ist die API unter `https://your-worker.workers.dev/api/pdf/[id]` erreichbar.

## Fazit

Cloudflare Browser Rendering macht PDF-Erzeugung zu einer leichten Edge-Funktion. Astro SSR plus Headless Chromium am Edge liefert Rechnungen, Belege und Reports on-demand, ohne Infrastruktur und ohne Cold-Starts.

Für fortgeschrittene Fälle: Mehrseitige Dokumente, eigene Kopf-/Fußzeilen oder Screenshots für Open-Graph-Bilder. Die Browser-Rendering-API bietet volle Puppeteer-Kontrolle am Cloudflare-Edge.

Fragen oder Anmerkungen? Schreiben Sie mir auf [Twitter](https://twitter.com/direct_messages/create/rishi_raj_jain_).
