appclerk-react-native

React Native/Expo components and hooks for AppClerk compliance infrastructure

📦 npm: appclerk-react-native•📄 License: MIT•View on npm →

Installation

React Native (Bare Workflow)

npm install appclerk-core appclerk-react-native react-native-markdown-display react-native-webview

Expo

npx expo install appclerk-core appclerk-react-native react-native-markdown-display react-native-webview

Note: Use EXPO_PUBLIC_ prefix for environment variables in Expo projects.

Quick Start

1. Setup Provider

// App.tsx
import { AppClerkProvider } from 'appclerk-react-native';

export default function App() {
  return (
    <AppClerkProvider
      apiKey={process.env.APPCLERK_API_KEY}
      projectId={process.env.APPCLERK_PROJECT_ID}
    >
      <YourApp />
    </AppClerkProvider>
  );
}

2. Use Components

import { PrivacyPolicy, TermsOfService } from 'appclerk-react-native';
import { View } from 'react-native';

export function SettingsScreen() {
  return (
    <View>
      <PrivacyPolicy renderMode="native" />
      <TermsOfService renderMode="native" />
    </View>
  );
}

Components

AppClerkProvider

Required context provider that wraps your app. Must be placed at the root of your component tree.

interface AppClerkProviderProps {
  /** Your AppClerk API key (required) */
  apiKey: string;
  
  /** Your AppClerk project ID (required) */
  projectId: string;
  
  /** Custom API URL (optional, defaults to https://appclerk.dev/api/v1) */
  apiUrl?: string;
  
  /** Enable debug logging (optional) */
  debug?: boolean;
  
  /** Cache TTL in milliseconds (optional) */
  cacheTtl?: number;
  
  /** Maximum retry attempts (optional) */
  maxRetries?: number;
  
  /** React children */
  children: React.ReactNode;
}

PrivacyPolicy

Component for displaying privacy policy documents. Supports both native markdown rendering and webview modes.

import { PrivacyPolicy } from 'appclerk-react-native';

<PrivacyPolicy
  renderMode="native"        // "native" | "webview"
  displayMode="inline"       // "inline" | "modal"
  theme="auto"               // "light" | "dark" | "auto"
  showHeader={true}          // Show document header
  showFooter={false}         // Show footer
  cachePolicy="cache-first"  // "cache-first" | "network-only" | "cache-only"
  onError={(error) => {}}    // Error callback
  onClose={() => {}}         // Close callback (for modal mode)
/>

TermsOfService

Component for displaying terms of service documents. Same props as PrivacyPolicy.

import { TermsOfService } from 'appclerk-react-native';

<TermsOfService
  renderMode="native"
  displayMode="modal"
  theme="dark"
/>

ComplianceStatus

Component for displaying detailed compliance status, including score, issues, and document statuses.

import { ComplianceStatus } from 'appclerk-react-native';

<ComplianceStatus
  showDetails={true}         // Show detailed issues and documents
  showScore={true}           // Show compliance score
  refreshInterval={60000}     // Auto-refresh interval in ms
  onIssuePress={(issue) => {}} // Callback when issue is pressed
  theme="auto"               // "light" | "dark" | "auto"
/>

DocumentViewer

Generic component for viewing any document type. Use PrivacyPolicy or TermsOfService for convenience, or DocumentViewer for custom document types.

import { DocumentViewer } from 'appclerk-react-native';

<DocumentViewer
  documentType="privacy-policy"  // "privacy-policy" | "terms-conditions" | etc.
  renderMode="native"
  displayMode="inline"
/>

Hooks

useAppClerk()

Access the AppClerk SDK instance directly. Useful for custom implementations or when you need more control.

import { useAppClerk } from 'appclerk-react-native';

function MyComponent() {
  const appclerk = useAppClerk();
  
  const handleFetch = async () => {
    const doc = await appclerk.getDocumentMarkdown("privacy-policy");
    console.log(doc.content);
  };
  
  return <Button onPress={handleFetch}>Fetch Document</Button>;
}

useDocumentContent()

Hook for fetching document markdown content. Automatically handles loading and error states.

import { useDocumentContent } from 'appclerk-react-native';
import { View, Text, ActivityIndicator } from 'react-native';

function MyComponent() {
  const { data, loading, error } = useDocumentContent({
    documentType: 'privacy-policy',
    cachePolicy: 'cache-first',
  });

  if (loading) return <ActivityIndicator />;
  if (error) return <Text>Error: {error.message}</Text>;
  if (!data) return null;

  return <Text>{data.content}</Text>;
}

useDocumentMetadata()

Hook for fetching document metadata without the full content.

import { useDocumentMetadata } from 'appclerk-react-native';

function MyComponent() {
  const { data, loading } = useDocumentMetadata({
    documentType: 'privacy-policy',
  });

  if (loading) return <Text>Loading...</Text>;
  
  return (
    <View>
      <Text>Title: {data?.title}</Text>
      <Text>Last Updated: {data?.lastUpdated}</Text>
      <Text>Version: {data?.version}</Text>
    </View>
  );
}

useComplianceStatus()

Hook for fetching compliance status. Supports auto-refresh via refreshInterval.

import { useComplianceStatus } from 'appclerk-react-native';

function MyComponent() {
  const { data, loading, error } = useComplianceStatus({
    refreshInterval: 60000, // Refresh every minute
  });

  if (loading) return <Text>Loading...</Text>;
  if (error) return <Text>Error: {error.message}</Text>;

  return (
    <View>
      <Text>Score: {data?.score}%</Text>
      <Text>Status: {data?.status}</Text>
      <Text>Issues: {data?.issues.length}</Text>
    </View>
  );
}

Rendering Modes

Native Mode (Default)

Renders markdown natively using react-native-markdown-display:

  • ✅ Better performance
  • ✅ Native feel and animations
  • ✅ Better offline support
  • ✅ Full styling control
  • ✅ Theme-aware (light/dark/auto)
<PrivacyPolicy renderMode="native" theme="auto" />

Webview Mode

Loads hosted HTML in a WebView using react-native-webview:

  • ✅ Exact rendering match with web version
  • ✅ Zero styling needed
  • ✅ Always up-to-date
  • ✅ Simpler implementation
<PrivacyPolicy renderMode="webview" />

Display Modes

Inline Mode

Displays the document directly in your component tree.

<PrivacyPolicy displayMode="inline" />

Modal Mode

Displays the document in a modal overlay. Requires an onClose callback.

<PrivacyPolicy
  displayMode="modal"
  onClose={() => setShowModal(false)}
/>

Style Guide

AppClerk React Native SDK provides comprehensive styling options for all markdown elements. You can style every aspect of your legal documents using React Native's ViewStyle and TextStyle objects.

Container Styling

Use the style prop to style the document container:

<TermsOfService
	style={{
		padding: 20,
		backgroundColor: "#ffffff",
		borderRadius: 8,
	}}
/>

Text Styling

Use the textStyle prop to apply base text styles:

<TermsOfService
	textStyle={{
		fontSize: 16,
		lineHeight: 24,
		color: "#333333",
		fontFamily: "System",
	}}
/>

Comprehensive Custom Styles

Apply granular styles to all markdown elements using the customStyles prop:

<TermsOfService
	customStyles={{
		// Container styles
		container: {
			padding: 20,
			backgroundColor: "#ffffff",
		},
		// Body/base text styles
		body: {
			fontSize: 16,
			lineHeight: 24,
			color: "#333333",
		},
		// Headings
		h1: {
			fontSize: 28,
			fontWeight: "bold",
			color: "#1a1a1a",
			marginTop: 24,
			marginBottom: 16,
		},
		h2: {
			fontSize: 24,
			fontWeight: "600",
			color: "#2d2d2d",
			marginTop: 20,
			marginBottom: 12,
		},
		// Paragraphs
		p: {
			fontSize: 16,
			lineHeight: 24,
			color: "#4a4a4a",
			marginBottom: 16,
		},
		// Lists
		ul: {
			marginBottom: 16,
			paddingLeft: 20,
		},
		li: {
			fontSize: 16,
			lineHeight: 24,
			color: "#4a4a4a",
			marginBottom: 8,
		},
		// Links
		a: {
			color: "#007AFF",
			textDecorationLine: "underline",
		},
		// Code
		code: {
			backgroundColor: "#f3f4f6",
			paddingHorizontal: 6,
			paddingVertical: 2,
			borderRadius: 4,
			fontSize: 14,
			fontFamily: "monospace",
		},
	}}
/>

Combining Style Props

You can combine style, textStyle, and customStyles for maximum flexibility:

<TermsOfService
	style={{
		padding: 20,
		backgroundColor: "#ffffff",
	}}
	textStyle={{
		fontSize: 16,
		fontFamily: "System",
	}}
	customStyles={{
		h1: {
			fontSize: 28,
			fontWeight: "bold",
		},
		p: {
			lineHeight: 26, // Overrides textStyle lineHeight
		},
	}}
/>

Styleable Elements

The following markdown elements can be styled:

ElementcustomStyles KeyType
ContainercontainerViewStyle
BodybodyTextStyle
Headings (h1-h6)h1, h2, h3... or heading1, heading2...TextStyle
Paragraphp or paragraphTextStyle
Listsul, ol, li or bullet_list, ordered_list, listItemViewStyle / TextStyle
Linksa or linkTextStyle
Codecode, pre or code_inline, code_blockTextStyle / ViewStyle

Common Examples

Dark Mode

<TermsOfService
	theme="dark"
	customStyles={{
		container: {
			backgroundColor: "#1f2937",
		},
		body: {
			color: "#f9fafb",
		},
		h1: { color: "#ffffff" },
		p: { color: "#d1d5db" },
		a: { color: "#60a5fa" },
	}}
/>

Platform-Specific Styles

import { Platform } from "react-native";

<TermsOfService
	customStyles={{
		h1: {
			fontSize: Platform.OS === "ios" ? 28 : 26,
			fontWeight: Platform.OS === "ios" ? "600" : "bold",
		},
		p: {
			fontSize: Platform.OS === "ios" ? 16 : 15,
			lineHeight: Platform.OS === "ios" ? 24 : 22,
		},
	}}
/>

Examples

Settings Screen

import { PrivacyPolicy, TermsOfService } from 'appclerk-react-native';
import { View, ScrollView, TouchableOpacity, Text } from 'react-native';

export function SettingsScreen() {
  const [showPrivacy, setShowPrivacy] = useState(false);
  const [showTerms, setShowTerms] = useState(false);

  return (
    <ScrollView>
      <TouchableOpacity onPress={() => setShowPrivacy(true)}>
        <Text>View Privacy Policy</Text>
      </TouchableOpacity>
      
      <TouchableOpacity onPress={() => setShowTerms(true)}>
        <Text>View Terms of Service</Text>
      </TouchableOpacity>

      {showPrivacy && (
        <PrivacyPolicy
          displayMode="modal"
          onClose={() => setShowPrivacy(false)}
        />
      )}

      {showTerms && (
        <TermsOfService
          displayMode="modal"
          onClose={() => setShowTerms(false)}
        />
      )}
    </ScrollView>
  );
}

Compliance Dashboard

import { ComplianceStatus } from 'appclerk-react-native';
import { View } from 'react-native';

export function ComplianceScreen() {
  return (
    <View style={{ flex: 1 }}>
      <ComplianceStatus
        showDetails={true}
        showScore={true}
        refreshInterval={60000}
        onIssuePress={(issue) => {
          console.log('Issue:', issue);
          // Navigate to issue details
        }}
      />
    </View>
  );
}

Expo Compatibility

This package is fully compatible with Expo and works in both:

  • ✅ Expo Go (for development)
  • ✅ EAS Build (for production)
  • ✅ Bare React Native workflow

Environment Variables in Expo:

Use the EXPO_PUBLIC_ prefix for environment variables:

<AppClerkProvider
  apiKey={process.env.EXPO_PUBLIC_APPCLERK_API_KEY}
  projectId={process.env.EXPO_PUBLIC_APPCLERK_PROJECT_ID}
/>

Getting Started

To use the SDK, you need an API key and project ID from your AppClerk dashboard.

  1. Sign up for AppClerk or log in to your account
  2. Create a project in your dashboard
  3. Generate an API key from API Keys settings
  4. Install the packages and start using them!