OpenPolicy
Generative

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/astro

Also install the SDK for defining policies:

bun add @openpolicy/sdk

Or install manually:

bun add -D @openpolicy/astro @openpolicy/vite

Create 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:

OptionTypeDefaultDescription
configPathstring"openpolicy.ts"Path to the unified policy config file, relative to the Astro root.
formatsOutputFormat[]["markdown"]Output formats: "markdown" | "html"
outDirstring"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.md

To 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>

On this page