> ## Documentation Index
> Fetch the complete documentation index at: https://docs.frankieone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Next.js

> This guide walks you through integrating OneSDK with Next.js, providing you with a solid foundation for building secure and efficient KYC workflows.

## Quick Start Video

<div style={{ position: 'relative', paddingBottom: '56.25%', height: 0, boxShadow: '10px 10px #93bbe1' }}>
  <iframe src="https://www.loom.com/embed/c610bd5f7b26443c96d967f2cefb0fbb?sid=1dd4ea24-bdd9-48d6-a706-73fa73916362&hide_title=true&hide_share=true&hideEmbedTopBar=true&hide_owner=true" frameBorder="0" webkitAllowFullScreen mozAllowFullScreen allowFullScreen style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} />
</div>

## Setup Instructions

<Steps>
  <Step title="Create Next.js Project">
    ```bash theme={null}
    npx create-next-app@latest my-next-app
    cd my-next-app
    ```
  </Step>

  <Step title="Install Dependencies">
    ```bash theme={null}
    npm install
    npm install @frankieone/one-sdk
    ```
  </Step>

  <Step title="Configure Environment">
    Create a `.env.local` file with your OneSDK credentials:

    ```env theme={null}
    NEXT_PUBLIC_CUSTOMER_ID=your_customer_id
    NEXT_PUBLIC_API_KEY=your_api_key
    NEXT_PUBLIC_CHILD_ID=your_child_id  # Optional
    ```
  </Step>
</Steps>

## Implementation Guide

<AccordionGroup>
  <Accordion title="1. Create OneSDK Hook">
    Create a new file `hooks/useOneSDK.js`:

    ```javascript theme={null}
    "use client";
    import OneSDK from "@frankieone/one-sdk";
    import { useEffect, useRef, useState } from "react";

    const useOneSDK = ({ config }) => {
      const [oneSDKInstance, setOneSDKInstance] = useState(null);
      const [error, setError] = useState(null);
      const [loading, setLoading] = useState(false);
      const initializedRef = useRef(false);

      const generateToken = async () => {
        try {
          const credentials = btoa(
            `${process.env.NEXT_PUBLIC_CUSTOMER_ID}:${process.env.NEXT_PUBLIC_API_KEY}`
          );
          
          const response = await fetch(
            "https://backend.latest.frankiefinancial.io/auth/v2/machine-session",
            {
              method: "POST",
              headers: {
                authorization: `machine ${credentials}`,
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                permissions: {
                  preset: "one-sdk",
                  reference: `demo-${new Date().toISOString()}`,
                },
              }),
            }
          );
          
          return await response.json();
        } catch (error) {
          setError(error.message);
          return null;
        }
      };

      const initializeSDK = async () => {
        setLoading(true);
        try {
          const token = await generateToken();
          if (!token) return;

          const instance = await OneSDK({
            session: token,
            ...config,
          });
          
          setOneSDKInstance(instance);
        } catch (error) {
          setError(error.message);
        } finally {
          setLoading(false);
        }
      };

      useEffect(() => {
        if (!initializedRef.current) {
          initializeSDK();
          initializedRef.current = true;
        }
      }, [config]);

      return { oneSDKInstance, error, loading };
    };

    export default useOneSDK;
    ```
  </Accordion>

  <Accordion title="2. Create End-to-End Component">
    Create a new component file `components/EndToEnd.js`:

    ```javascript theme={null}
    "use client";
    import { useEffect } from "react";
    import useOneSDK from "../hooks/useOneSDK";

    const EndToEnd = () => {
      const config = {
        mode: "development",
        recipe: {
          form: {
            provider: {
              name: "react",
            },
          },
        },
      };

      const { oneSDKInstance, error, loading } = useOneSDK({ config });

      const initializeComponents = () => {
        if (!oneSDKInstance) return;

        // Initialize Components
        const components = {
          welcome: oneSDKInstance.component("form", {
            name: "WELCOME",
            type: "manual",
          }),
          consent: oneSDKInstance.component("form", {
            name: "CONSENT"
          }),
          document: oneSDKInstance.component("form", {
            name: "DOCUMENT",
            showPreps: true,
          }),
          biometrics: oneSDKInstance.component("biometrics"),
        };

        // Mount Welcome Component
        components.welcome.mount("#form-container");

        // Setup Event Handlers
        setupEventHandlers(components);
      };

      const setupEventHandlers = (components) => {
        const { welcome, consent, document, biometrics } = components;

        welcome.on("form:welcome:ready", () => {
          consent.mount("#form-container");
        });

        consent.on("form:consent:ready", () => {
          document.mount("#form-container");
        });

        // Add more event handlers as needed
      };

      useEffect(() => {
        if (oneSDKInstance) {
          initializeComponents();
        }
      }, [oneSDKInstance]);

      if (loading) {
        return <div>Loading OneSDK...</div>;
      }

      if (error) {
        return <div>Error: {error}</div>;
      }

      return <div id="form-container" />;
    };

    export default EndToEnd;
    ```
  </Accordion>

  <Accordion title="3. Add Component to Page">
    Update your page file (e.g., `app/page.js`):

    ```javascript theme={null}
    import EndToEnd from '../components/EndToEnd';

    export default function Home() {
      return (
        <main>
          <EndToEnd />
        </main>
      );
    }
    ```
  </Accordion>
</AccordionGroup>

## Component Configuration

<Tabs>
  <Tab title="Welcome Form">
    ```javascript theme={null}
    const welcome = oneSDKInstance.component("form", {
      name: "WELCOME",
      type: "manual",
      descriptions: [
        { label: 'Welcome to our KYC process', style: {} },
        { label: 'Please follow the steps to verify your identity', style: {} },
      ],
    });
    ```
  </Tab>

  <Tab title="Document Form">
    ```javascript theme={null}
    const document = oneSDKInstance.component("form", {
      name: "DOCUMENT",
      showPreps: true,
      // Additional configuration options
    });
    ```
  </Tab>

  <Tab title="Biometrics">
    ```javascript theme={null}
    const biometrics = oneSDKInstance.component("biometrics", {
      // Add your biometrics configuration here
    });
    ```
  </Tab>
</Tabs>

## Event Handling

<AccordionGroup>
  <Accordion title="Form Events">
    ```javascript theme={null}
    // Welcome Form Events
    welcome.on("form:welcome:ready", () => {
      // Handle welcome form ready
    });

    welcome.on("form:welcome:failed", () => {
      // Handle welcome form failure
    });

    // Document Form Events
    document.on("form:document:ready", async ({ inputInfo }) => {
      // Handle document form ready
      const docType = inputInfo.documentType;
      // Initialize OCR component
    });
    ```
  </Accordion>

  <Accordion title="Biometrics Events">
    ```javascript theme={null}
    biometrics.on("detection_failed", () => {
      // Handle failed detection
    });

    biometrics.on("processing", () => {
      // Handle processing state
    });

    biometrics.on("results", (result) => {
      // Handle biometrics results
    });
    ```
  </Accordion>
</AccordionGroup>

## Best Practices

<Columns cols={2}>
  <Card title="Error Handling" icon="shield-check">
    Always implement proper error handling for both SDK initialization and
    component events.
  </Card>

  <Card title="Loading States" icon="spinner">
    Show appropriate loading states during initialization and between component
    transitions.
  </Card>

  <Card title="Event Cleanup" icon="broom">
    Properly clean up event listeners when components unmount to prevent memory
    leaks.
  </Card>

  <Card title="Security" icon="lock">
    Never expose credentials in client-side code. Use environment variables and
    server-side token generation.
  </Card>
</Columns>

<Callout icon="bell" color="#FFCA16" iconType="regular">
  Remember to handle cleanup in your components by implementing proper
  unmounting logic and removing event listeners when components are destroyed.
</Callout>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Common Issues">
    * **SDK Initialization Failed**: Check your credentials and network connection
    * **Component Mount Errors**: Ensure the container element exists in the DOM
    * **Event Handler Issues**: Verify event names and handler implementations
  </Accordion>

  <Accordion title="Debug Tips">
    ```javascript theme={null}
    // Enable debug logging
    const config = {
      mode: "development",
      debug: true,
      // ... other config options
    };

    // Listen to all events
    oneSDKInstance.on("*", (event) => {
      console.log("Event:", event);
    });
    ```
  </Accordion>
</AccordionGroup>
