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/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",
"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.htmlCreate 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/