Astro
Using OpenPolicy with the Astro integration
The @openpolicy/astro package provides a first-class Astro integration that compiles your policy configs at build time and in dev mode with hot-reload. Under the hood it delegates entirely to @openpolicy/vite — no duplicated compilation logic.
Installation
The fastest way is astro add, which installs the package and updates astro.config.mjs automatically:
npx astro add @openpolicy/astroAlso install the SDK for defining policies:
bun add @openpolicy/sdkOr install manually:
bun add -D @openpolicy/astro @openpolicy/viteCreate your config
Create an openpolicy.ts at the root of your project using defineConfig():
// openpolicy.ts
import { defineConfig } from "@openpolicy/sdk";
export default defineConfig({
company: {
name: "Acme Inc.",
legalName: "Acme Corporation",
address: "123 Main St, Springfield, USA",
contact: "privacy@acme.com",
},
privacy: {
effectiveDate: "2026-01-01",
dataCollected: {
"Account Information": ["Name", "Email address"],
"Usage Data": ["Pages visited", "Browser type", "IP address"],
},
legalBasis: "Legitimate interests and consent",
retention: { "Account data": "Until account deletion" },
cookies: { essential: true, analytics: false, marketing: false },
thirdParties: [],
userRights: ["access", "erasure"],
jurisdictions: ["us", "eu"],
},
terms: {
effectiveDate: "2026-01-01",
acceptance: { methods: ["using the service", "creating an account"] },
governingLaw: { jurisdiction: "Delaware, USA" },
},
});See the openpolicy.ts reference → for all available fields.
Setup
Add openPolicy() to the integrations array in your Astro config. When no options are passed, the integration looks for openpolicy.ts by default:
// astro.config.mjs
import { defineConfig } from "astro/config";
import { openPolicy } from "@openpolicy/astro";
export default defineConfig({
integrations: [openPolicy()],
});To customize the output location or formats:
export default defineConfig({
integrations: [
openPolicy({
formats: ["markdown"],
outDir: "src/generated/policies",
}),
],
});On the first bun run dev, if a config file doesn't exist yet, the integration scaffolds it automatically. Edit the generated file and save — it watches for changes and regenerates without restarting the dev server.
Options
The integration accepts the same options as the Vite plugin:
| Option | Type | Default | Description |
|---|---|---|---|
configPath | string | "openpolicy.ts" | Path to the unified policy config file, relative to the Astro root. |
formats | OutputFormat[] | ["markdown"] | Output formats: "markdown" | "html" |
outDir | string | "public/policies" | Output directory, relative to the Astro root |
See the Vite plugin docs → for full details on each option.
Unified config
When the integration loads a file that exports a defineConfig() result, it automatically compiles all sections present — privacy, terms, and cookie — in a single pass:
src/generated/policies/
privacy-policy.md
terms-of-service.mdTo use a different filename, pass configPath:
openPolicy({
configPath: "my-policies.ts",
formats: ["markdown"],
outDir: "src/generated/policies",
})Rendering policies
Because the files land inside src/, Astro can import them directly as Markdown components:
---
// src/pages/privacy.astro
import { Content } from "../../generated/policies/privacy-policy.md";
---
<div class="prose prose-gray max-w-none">
<Content />
</div>