React components and hooks for AppClerk compliance infrastructure. Works with Next.js, Vite, CRA, and other React 18+ frameworks.
npm install appclerk-core appclerk-react
# or
yarn add appclerk-core appclerk-react
# or
pnpm add appclerk-core appclerk-reactIn the App Router, create a small "use client" wrapper for AppClerkProvider, then wrap your app with it.
// app/appclerk-provider.tsx
"use client";
import { AppClerkProvider } from "appclerk-react";
export function AppClerkRootProvider({ children }: { children: React.ReactNode }) {
return (
<AppClerkProvider
apiKey={process.env.NEXT_PUBLIC_APPCLERK_API_KEY!}
projectId={process.env.NEXT_PUBLIC_APPCLERK_PROJECT_ID!}
>
{children}
</AppClerkProvider>
);
}// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";
import { AppClerkRootProvider } from "./appclerk-provider";
export const metadata: Metadata = { /* ... */ };
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<AppClerkRootProvider>{children}</AppClerkRootProvider>
</body>
</html>
);
}// pages/_app.tsx
import { AppClerkProvider } from "appclerk-react";
export default function App({ Component, pageProps }) {
return (
<AppClerkProvider
apiKey={process.env.NEXT_PUBLIC_APPCLERK_API_KEY}
projectId={process.env.NEXT_PUBLIC_APPCLERK_PROJECT_ID}
>
<Component {...pageProps} />
</AppClerkProvider>
);
}// src/main.tsx or src/index.tsx
import { AppClerkProvider } from "appclerk-react";
import { createRoot } from "react-dom/client";
import App from "./App";
const root = createRoot(document.getElementById("root")!);
root.render(
<AppClerkProvider
apiKey={import.meta.env.VITE_APPCLERK_API_KEY}
projectId={import.meta.env.VITE_APPCLERK_PROJECT_ID}
>
<App />
</AppClerkProvider>
);Display your privacy policy as a native markdown view or embed via webview.
"use client";
import { PrivacyPolicy } from "appclerk-react";
export function MyPrivacyPolicy() {
return <PrivacyPolicy renderMode="native" displayMode="inline" />;
}Display your terms of service document, inline or in a modal.
"use client";
import { TermsOfService } from "appclerk-react";
export function MyTerms() {
return <TermsOfService renderMode="native" displayMode="modal" />;
}Show a detailed compliance status panel, including score and issues.
"use client";
import { ComplianceStatus } from "appclerk-react";
export function CompliancePanel() {
return <ComplianceStatus />;
}AppClerk React SDK provides comprehensive styling options for all markdown elements. You can style every aspect of your legal documents using either CSS classes or inline styles.
Use the className prop to style the document container:
<TermsOfService className="max-w-4xl mx-auto p-6 bg-white rounded-lg shadow-lg" />Apply CSS classes to specific markdown elements using the markdownClassNames prop. Ideal when using CSS frameworks like Tailwind CSS:
<TermsOfService
markdownClassNames={{
container: "max-w-4xl mx-auto",
h1: "text-3xl font-bold text-gray-900 mb-4",
h2: "text-2xl font-semibold text-gray-800 mt-8 mb-3",
h3: "text-xl font-medium text-gray-700 mt-6 mb-2",
p: "text-gray-700 mb-4 leading-relaxed",
ul: "list-disc ml-6 mb-4 space-y-2",
ol: "list-decimal ml-6 mb-4 space-y-2",
li: "text-gray-700 mb-2",
a: "text-blue-600 hover:text-blue-800 underline",
strong: "font-semibold text-gray-900",
em: "italic text-gray-700",
code: "bg-gray-100 px-2 py-1 rounded text-sm font-mono",
pre: "bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto",
blockquote: "border-l-4 border-blue-500 pl-4 italic text-gray-600",
hr: "my-8 border-gray-300",
table: "w-full border-collapse mb-4",
th: "bg-gray-100 p-3 text-left font-semibold border",
td: "p-3 border",
}}
/>Apply inline styles using the customStyles prop for complete control:
<TermsOfService
customStyles={{
container: {
maxWidth: "800px",
margin: "0 auto",
padding: "2rem",
backgroundColor: "#ffffff",
borderRadius: "8px",
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
},
h1: {
fontSize: "2.5rem",
fontWeight: "bold",
color: "#1a1a1a",
marginTop: "2rem",
marginBottom: "1rem",
fontFamily: "Georgia, serif",
},
p: {
fontSize: "1rem",
lineHeight: "1.75",
color: "#4a4a4a",
marginBottom: "1rem",
},
ul: {
marginBottom: "1rem",
paddingLeft: "1.5rem",
listStyleType: "disc",
},
li: {
marginBottom: "0.5rem",
lineHeight: "1.6",
},
a: {
color: "#2563eb",
textDecoration: "underline",
},
}}
/>You can combine className, markdownClassNames, and customStyles for maximum flexibility:
<TermsOfService
className="my-custom-container"
markdownClassNames={{
h1: "text-3xl font-bold",
p: "text-gray-700",
}}
customStyles={{
h1: {
color: "#1a1a1a", // Overrides any conflicting CSS class
},
p: {
lineHeight: "1.8", // Adds to CSS class styles
},
}}
/>The following markdown elements can be styled:
| Element | markdownClassNames Key | customStyles Key |
|---|---|---|
| Container | container | container |
| Headings (h1-h6) | h1, h2, h3... | h1, h2, h3... |
| Paragraph | p | p |
| Lists (ul, ol, li) | ul, ol, li | ul, ol, li |
| Links | a | a |
| Code (inline & block) | code, pre | code, pre |
| Tables | table, th, td... | table, th, td... |
<TermsOfService
theme="dark"
customStyles={{
container: {
backgroundColor: "#1f2937",
color: "#f9fafb",
},
h1: { color: "#ffffff" },
p: { color: "#d1d5db" },
a: { color: "#60a5fa" },
}}
/><TermsOfService
customStyles={{
container: {
maxWidth: "600px",
margin: "0 auto",
padding: "3rem 1rem",
},
h1: {
fontSize: "1.75rem",
fontWeight: "300",
marginBottom: "2rem",
letterSpacing: "-0.02em",
},
p: {
fontSize: "0.9375rem",
lineHeight: "1.7",
marginBottom: "1.25rem",
},
}}
/>Fetch document markdown content for a given document type.
import { useDocumentContent } from "appclerk-react";
function PrivacySection() {
const { data, loading, error } = useDocumentContent({
documentType: "privacy-policy",
});
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <pre>{data?.content}</pre>;
}Fetch overall compliance status for your project and keep it updated.
import { useComplianceStatus } from "appclerk-react";
function ComplianceBadge() {
const { data, loading } = useComplianceStatus({
refreshInterval: 60000, // refresh every minute
});
if (loading) return <div>Checking compliance…</div>;
return <div>Compliance score: {data?.score}%</div>;
}// app/api/compliance/route.ts
import { init } from "appclerk-core";
import { NextResponse } from "next/server";
const appclerk = init({
apiKey: process.env.APPCLERK_API_KEY!,
projectId: process.env.APPCLERK_PROJECT_ID!,
});
export async function GET() {
const compliance = await appclerk.getComplianceStatus();
return NextResponse.json(compliance);
}import { PrivacyPolicy } from "appclerk-react";
export function LegalPage() {
return (
<main>
<h1>Privacy Policy</h1>
<PrivacyPolicy renderMode="native" displayMode="inline" />
</main>
);
}To use the SDK, you need an API key and project ID from your AppClerk dashboard.