OpenPolicy
Generative

SvelteKit

Use the OpenPolicy Vite plugin to generate type-safe privacy, terms, and cookie policy pages in your SvelteKit app — automatically at build time and hot-reloaded during development.

SvelteKit is built on Vite, so it works naturally with the @openpolicy/vite plugin. Define your policies once in TypeScript, and the plugin compiles them to HTML at build time. In dev mode, policies hot-reload whenever you save the config — no manual steps, no stale documents.

Installation

bun add @openpolicy/sdk
bun add -D @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",
      "Usage logs": "90 days",
    },
    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" },
  },
  cookie: {
    effectiveDate: "2026-01-01",
    cookies: { essential: true, analytics: true, functional: false, marketing: false },
    jurisdictions: ["us", "eu"],
    consentMechanism: { hasBanner: true, hasPreferencePanel: true, canWithdraw: true },
  },
});

See the openpolicy.ts reference → for all available fields.

Add the plugin

Add openPolicy() to the plugins array in vite.config.ts, alongside sveltekit():

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

export default defineConfig({
  plugins: [
    sveltekit(),
    openPolicy({
      formats: ["html"],
      outDir: "src/lib/policies",
    }),
  ],
});

Outputting to src/lib/policies means the files land inside SvelteKit's $lib alias and can be imported directly in your routes.

On the next vite dev or vite build, the plugin writes:

src/lib/policies/
  privacy-policy.html
  terms-of-service.html
  cookie-policy.html

Create the policy routes

Import each HTML file as a raw string using Vite's ?raw suffix, then render it with Svelte's {@html} tag.

<!-- src/routes/privacy/+page.svelte -->
<svelte:head>
  <title>Privacy Policy</title>
</svelte:head>

<script lang="ts">
  import policy from "$lib/policies/privacy-policy.html?raw";
</script>

<main>
  {@html policy}
</main>

Repeat the same pattern for terms and cookie:

<!-- src/routes/terms/+page.svelte -->
<script lang="ts">
  import policy from "$lib/policies/terms-of-service.html?raw";
</script>
<main>{@html policy}</main>
<!-- src/routes/cookie/+page.svelte -->
<script lang="ts">
  import policy from "$lib/policies/cookie-policy.html?raw";
</script>
<main>{@html policy}</main>

Dev mode

During vite dev, the plugin watches openpolicy.ts for changes. Every time you save the file, the affected policy documents are regenerated automatically — the same hot-reload loop you already rely on for your Svelte components.

Keeping policies in sync

Generated HTML files should be committed alongside your source so they're available at build time. A CI step can verify they're up to date:

# Regenerate and fail if the output differs from what's committed
vite build
git diff --exit-code src/lib/policies/

On this page