← Back to list

How to Ship Legal Pages as Code in Next.js with OpenPolicy?

From Code to Compliance: Generate Privacy, Terms & Cookie Consent with OpenPolicy

Rajdeep Singh in FrontEnd Web · 2026-04-21 10:05 · 50 claps · 7.2 min read paywalled
#openpolicy #policy-as-code #nextjs-16 #web-development #privacy-policy
Open on Medium ↗
Wiki topics: 🌐 · Web Development 🔒 · Cybersecurity ⚖️ · Law & Justice

How to Ship Legal Pages as Code in Next.js with OpenPolicy?

How to Ship Legal Pages as Code in Next.js with OpenPolicy?

Next.js 16

How to Ship Legal Pages as Code in Next.js with OpenPolicy?

From Code to Compliance: Generate Privacy, Terms & Cookie Consent with OpenPolicy

OpenPolicy framework is an open-source policy-as-code initiative that lets you define legal and consent settings in code. It enables the generation and display of legal pages such as Privacy Policy, Terms of Service, and Cookie Policy, with cookie consent support, in a React/Next.js app.

This guide offers a step-by-step explanation of installing and configuring the OpenPolicy framework in your Next.js project.

· (Optional) Create a Next.js application · Install the packagesWhat package does? · Create your OpenPolicy configuration · Create a provider component. · Mount the provider in your app layout · Add policy pagesPrivacy policy pageTerms of service pageCookie page · How to Install cookie banner UI (recommended) · How to customize the cookie banner with Open Policy? · How can you modify the OpenPolicy content style using CSS?

The entire code is open-source and accessible on GitHub: https://github.com/officialrajdeepsingh/openpolicy-framework

(Optional) Create a Next.js application

If you already have a Next.js project, skip this section. Otherwise, create a new nextjs application with the command below.

pnpm dlx create-next-app@latest
✔ What is your project named? … open-policy
✔ Would you like to use the recommended Next.js defaults? › Yes, use recommended defaults
Creating a new Next.js app in /home/officialrajdeepsingh/medium/open-policy.

Using pnpm.

Initializing project with template: app-tw 

Installing dependencies:
- next
- react
- react-dom

Installing devDependencies:
- @tailwindcss/postcss
- @types/node
- @types/react
- @types/react-dom
- eslint
- eslint-config-next
- tailwindcss
- typescript

Packages: +357
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 424, reused 362, downloaded 0, added 357, done

dependencies:
+ next 16.2.2
+ react 19.2.4
+ react-dom 19.2.4

devDependencies:
+ @tailwindcss/postcss 4.2.2
+ @types/node 20.19.37 (25.5.0 is available)
+ @types/react 19.2.14
+ @types/react-dom 19.2.3
+ eslint 9.39.4 (10.1.0 is available)
+ eslint-config-next 16.2.2
+ tailwindcss 4.2.2
+ typescript 5.9.3 (6.0.2 is available)

Done in 8s using pnpm v10.12.1

Generating route types...
✓ Types generated successfully

Initialized a git repository.

Success! Created open-policy at /home/officialrajdeepsingh/medium/open-policy

Install the packages

To install and configure the OpenPolicy framework, you need to install both the @openpolicy/sdk and @openpolicy/react packages in your project:

pnpm add @openpolicy/sdk @openpolicy/react

The command output looks like this

pnpm add @openpolicy/sdk @openpolicy/react
Packages: +2
++
Progress: resolved 426, reused 362, downloaded 2, added 2, done

dependencies:
+ @openpolicy/react 0.0.17
+ @openpolicy/sdk 0.0.17

Done in 3.5s using pnpm v10.12.1

Alternative package managers:

npm install @openpolicy/sdk @openpolicy/react
# or
yarn add @openpolicy/sdk @openpolicy/react
# or
bun add @openpolicy/sdk @openpolicy/react

What package does?

  1. The @openpolicy/sdk package enables you to define your legal policy configuration
  2. The @openpolicy/react package provides ready-made React components like PrivacyPolicy, TermsOfService, CookiePolicy, and a cookie-consent UI

Create your OpenPolicy configuration

Create a file named lib/openpolicy.ts. This file contains all policy and consent settings used across your app.

// lib/openpolicy.ts | openpolicy.ts

import { defineConfig } from "@openpolicy/sdk";

export default defineConfig({
  company: {
    name: "Your Company",
    legalName: "Your Company, Inc.",
    address: "123 Main St, City, State, ZIP",
    contact: "privacy@yourcompany.com",
  },
  privacy: {
    effectiveDate: "2025-01-01",
    dataCollected: {
      "Personal Information": ["Full name", "Email address"],
      "Usage Data": ["Pages visited", "Time spent on site"],
    },
    legalBasis: "consent",
    retention: {
      "Personal data": "As long as your account is active",
    },
    cookies: {
      essential: true,
      analytics: false,
      marketing: false,
    },
    thirdParties: [],
    userRights: ["access", "erasure", "portability"],
    jurisdictions: ["us"],
  },
  terms: {
    effectiveDate: "2025-01-01",
    acceptance: {
      methods: ["using the service", "creating an account"],
    },
    eligibility: {
      minimumAge: 13,
    },
    accounts: {
      registrationRequired: false,
      userResponsibleForCredentials: true,
      companyCanTerminate: true,
    },
    prohibitedUses: [
      "Violating any applicable laws or regulations",
      "Infringing on intellectual property rights",
    ],
    intellectualProperty: {
      companyOwnsService: true,
      usersMayNotCopy: true,
    },
    termination: {
      companyCanTerminate: true,
      userCanTerminate: true,
    },
    disclaimers: {
      serviceProvidedAsIs: true,
      noWarranties: true,
    },
    limitationOfLiability: {
      excludesIndirectDamages: true,
    },
    governingLaw: {
      jurisdiction: "Delaware, USA",
    },
    changesPolicy: {
      noticeMethod: "email or prominent notice on our website",
      noticePeriodDays: 30,
    },
  },
  cookie: {
    effectiveDate: "2026-01-01",
    cookies: {
      essential: true,
      analytics: true,
      functional: false,
      marketing: false,
    },
    thirdParties: [
      {
        name: "Google Analytics",
        purpose: "Website analytics and performance monitoring",
        policyUrl: "https://policies.google.com/privacy",
      },
    ],
    consentMechanism: {
      hasBanner: true,
      hasPreferencePanel: true,
      canWithdraw: true,
    },
    jurisdictions: ["us", "eu"],
  },
});

Update the company and legal fields in the lib/openpolicy.ts file with your real business details before production.

  • Define the company identity and contact details used in legal pages.
  • Configure privacy policy details, including data categories, legal bases, retention periods, and user rights.
  • Configure terms of service rules like eligibility, prohibited use, liability limits, and governing law.
  • Configure cookie policy details and consent behavior (banner, preference panel, withdrawal support).

Finally, based on the data you provide, OpenPolicy generates legal pages such as Privacy Policy, Terms of Service, and Cookie Policy for your application.

Create a provider component.

Create a file named components/OpenPolicyProvider.tsx and insert the following code. This will inject policy and cookie-consent state into your application using a React provider.

The config={openpolicy links your SDK configuration to React UI components. CookieBanner and CookiePreferences display the user-facing consent controls

// components/OpenPolicyProvider.tsx

"use client";

import { OpenPolicy } from "@openpolicy/react";
import type { ReactNode } from "react";
import openpolicy from "@/lib/openpolicy";

export function OpenPolicyProvider({ children }: { children: ReactNode }) {
  return (
    <OpenPolicy config={openpolicy}>
      {children}
    </OpenPolicy>
  );
}

Mount the provider in your app layout

Update app/layout.tsx to wrap the entire app with OpenPolicyProvider, ensuring the app has access to the OpenPolicy context globally for every route and that legal pages and cookie components work consistently throughout the application.

import { OpenPolicyProvider } from "@/components/OpenPolicyProvider";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <OpenPolicyProvider>{children}</OpenPolicyProvider>
      </body>
    </html>
  );
}

Add policy pages

Create route pages that render the OpenPolicy UI components.

Privacy policy page

Create the app/privacy/page.tsx file and render the PrivacyPolicy component to display the Privacy Policy content on your website, using your OpenPolicy configuration.

// app/privacy/page.tsx

"use client";

import { PrivacyPolicy } from "@openpolicy/react";

export default function PrivacyPage() {
  return (
    <main className="p-4 container mx-auto max-w-xl lg:prose-xl prose prose-slate dark:prose-invert">
      <PrivacyPolicy />
    </main>
  );
}

Your privacy page looks like this.

Your privacy page looks like this

Your privacy page looks like this

Terms of service page

Create the app/terms/page.tsxfile and render the TermsOfService component to display the Terms of Service content on your website, using your OpenPolicy configuration.

// app/terms/page.tsx

"use client";

import { TermsOfService } from "@openpolicy/react";

export default function TermsPage() {
  return (
    <main className="p-4 container mx-auto max-w-xl prose lg:prose-xl prose-slate dark:prose-invert">
      <TermsOfService />
    </main>
  );
}

Your terms and conditions page looks like this.

Your terms and conditions page looks like this.

Your terms and conditions page looks like this.

Cookie page

Create an app/cookie/page.tsx file and render the CookiePolicy component to showcase the cookie policy content, including cookie categories, third parties, and consent details on your website, utilizing your OpenPolicy configuration.

// app/cookie/page.tsx

"use client";

import { CookiePolicy } from "@openpolicy/react";

export default function CookiePolicyPage() {
  return (
    <main className="p-4 container mx-auto max-w-xl lg:prose-xl prose prose-slate dark:prose-invert">
      <CookiePolicy />
    </main>
  );
}

Your cookie page looks like this.

Your cookie page looks like this.

Your cookie page looks like this.

How to Install cookie banner UI (recommended)

Install or add the OpenPolicy @openpolicy/cookie-banner from the shadcn registry to include ready-to-use CookieBanner and CookiePreferences components.

pnpm dlx shadcn@latest add @openpolicy/cookie-banner

Alternative package managers:

npx shadcn@latest add @openpolicy/cookie-banner
# or
yarn dlx shadcn@latest add @openpolicy/cookie-banner
# or
bunx shadcn@latest add @openpolicy/cookie-banner

This incorporates CookieBanner and CookiePreferences UI components into your project, enabling you to display consent controls. Finally, make changes to your components/OpenPolicyProvider.tsx file.

// components/OpenPolicyProvider.tsx |app/layout.ts

"use client";

import { OpenPolicy } from "@openpolicy/react";
import type { ReactNode } from "react";
import openpolicy from "@/lib/openpolicy";
import { CookieBanner, CookiePreferences } from "./ui/openpolicy/cookie-banner";

export function OpenPolicyProvider({ children }: { children: ReactNode }) {
 return (
  <OpenPolicy config={openpolicy}>
   {children}
   <CookieBanner />
   <CookiePreferences />
  </OpenPolicy>
 );
}

You should now see the cookie banner displayed on your website.

Cookie banner with an open policy.

Cookie banner with an open policy.

How to customize the cookie banner with Open Policy?

You can create or customize a cookie banner for your application using the useCookies() function from the @openpolicy/react package.

// components/Banner.tsx
"use client";
import { useCookies } from "@openpolicy/react";
import { Button } from "./ui/button";

export function Banner() {

    const { route, acceptAll, acceptNecessary, setRoute } = useCookies();

    if (route !== "cookie") return null;

    return (
        <div className="w-fill flex justify-center gap-4 items-center bg-accent p-4">
            <p className="text-accent-foreground">We use cookies to improve your experience.</p>
            <div className="flex gap-3.5">
                <Button onClick={acceptAll}>Accept all</Button>
                <Button onClick={acceptNecessary}>Accept necessary only</Button>
                <Button onClick={() => setRoute("preferences")}>Preferences</Button>
            </div>
        </div>
    );
}

You should now see the cookie banner displayed on your website.

Cookie banner with an open policy.

Cookie banner with an open policy.

How can you modify the OpenPolicy content style using CSS?

The OpenPolicy framework uses CSS variables to style content. You can pass these variables through the style prop to theme the legal content rendered by OpenPolicy without altering your page layout classes.

We modify the —op-body-color to control the body text color and —op-heading-color to control the heading color.

import type { CSSProperties } from "react";

const policyTheme = {
  "--op-body-color": "var(--foreground)", # shadcn --foreground variable
  "--op-heading-color": "var(--foreground)", # shadcn --foreground variable
} as CSSProperties;

Use the policyTheme variable with any OpenPolicy component:

<TermsOfService style={policyTheme} />
# or
<PrivacyPolicy style={policyTheme} />
# or
<CookiePolicy style={policyTheme} />

Now you can change the content color in OpenPolicy or add your own custom CSS as well. Due to CSS variables, we cannot use the @tailwindcss/typography package to style the OpenPolicy content, which is the only downside of the OpenPolicy framework.

To learn more about frontend developers, React.js, Next.js, and Linux, follow the frontend web publication and The Linux on Medium for updates. You can also follow me on Twitter (X) and Medium.

Subscribe to Our Newsletter and publication to receive updates every week.

Subscribe to Our Newsletter and publication to receive updates every week.


메타데이터
post_id
472bee4e1e86
slug
how-to-ship-legal-pages-as-code-in-next-js-with-openpolicy-472bee4e1e86
url
https://medium.com/frontendweb/how-to-ship-legal-pages-as-code-in-next-js-with-openpolicy-472bee4e1e86
canonical_url
https://medium.com/frontendweb/how-to-ship-legal-pages-as-code-in-next-js-with-openpolicy-472bee4e1e86
author_url
https://medium.com/@officialrajdeepsingh
status
ok
fetched_at
2026-06-11 10:13:20