OpenPolicy
Generative

Vite

Using OpenPolicy with the Vite plugin

The @openpolicy/vite package provides a Vite plugin that compiles your policy config automatically — at build time and in dev mode with hot-reload.

Installation

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

Create your config

Create an openpolicy.ts at the root of your project using defineConfig() from @openpolicy/sdk:

// 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 plugins array in your Vite config. When no options are passed, the plugin looks for openpolicy.ts by default:

// vite.config.ts
import { defineConfig } from "vite";
import { openPolicy } from "@openpolicy/vite";

export default defineConfig({
  plugins: [openPolicy()],
});

To customize the output location or formats, pass options explicitly:

openPolicy({
  formats: ["markdown", "html"],
  outDir: "public/policies",
})

Options

OptionTypeDefaultDescription
configPathstring"openpolicy.ts"Path to the unified policy config file, relative to the Vite root.
formatsOutputFormat[]["markdown"]Output formats: "markdown" | "html" | "pdf"
outDirstring"public/policies"Output directory, relative to the Vite root

Use { config: "legal.config.ts", type: "terms" } to override explicitly.

Unified config

When the plugin loads a file that exports a defineConfig() result, it automatically compiles all sections present — privacy, terms, and cookie — in a single pass. You don't need to list them separately:

// generates privacy-policy.md, terms-of-service.md, and cookie-policy.md
openPolicy({ formats: ["markdown"], outDir: "public/policies" })

To use a different filename, pass configPath:

openPolicy({
  configPath: "my-policies.ts",
  formats: ["markdown", "html"],
  outDir: "public/policies",
})

Scaffold

If a config file doesn't exist when Vite starts, the plugin creates a starter config at that path with placeholder content. Edit the file and save — the dev server picks up the changes automatically.

Build mode

During vite build, the plugin writes all policy files to outDir before Vite processes other assets. Files in public/ are copied to dist/ automatically by Vite.

Dev mode

During vite dev, the plugin:

  1. Compiles all configs on startup
  2. Watches every config file for changes (using Vite's built-in Chokidar watcher)
  3. Regenerates the affected policy file on every save without restarting the dev server

Errors during regeneration are logged to the console but don't crash the dev server.

Output

Output filenames are determined by the policy type:

Policy typeOutput filenames
"privacy"privacy-policy.md, privacy-policy.html, privacy-policy.pdf
"terms"terms-of-service.md, terms-of-service.html, terms-of-service.pdf
"cookie"cookie-policy.md, cookie-policy.html, cookie-policy.pdf

Astro

For Astro projects, use the dedicated @openpolicy/astro integration instead. It wraps this Vite plugin and plugs into Astro's first-class integration API.

On this page