> For the complete documentation index, see [llms.txt](https://docs.akinon.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.akinon.com/technical-guides/project-zero/next.js/plugins/otp.md).

# OTP

The `Otp` component allows you to implement a One-Time Password (OTP) verification UI. With the `customUIRender` prop, you can fully customize the look and behavior of the OTP interface to match your project's needs.

## <mark style="color:red;">Installation Method</mark>

You can use the following command to install the extension with the latest plugins:

```bash
npx @akinon/projectzero@latest --plugins
```

### <mark style="color:red;">**Props**</mark>

<table><thead><tr><th width="148.53125">Prop</th><th width="188.6796875">Type</th><th width="102.2265625">Required</th><th>Description</th></tr></thead><tbody><tr><td>customUIRender</td><td>React.ReactNode</td><td>Optional</td><td>A render function to override the default OTP interface. Provides access to UI and control handlers</td></tr><tr><td>submitAction</td><td>SubmitHandler&#x3C;{ [key: string]: any }></td><td>Yes</td><td>A submit handler function triggered when OTP form is submitted.</td></tr><tr><td>data</td><td>{ [key: string]: any }</td><td>Yes</td><td>Data object containing required fields like phone number. OTP code will be appended here before submission</td></tr></tbody></table>

### <mark style="color:red;">**CustomUIRender Parameters**</mark>

<table><thead><tr><th width="147.28125">Parameter</th><th width="188.10546875">Type</th><th>Description</th></tr></thead><tbody><tr><td>closeHandler</td><td>() => void</td><td>Closes the popup manually.</td></tr><tr><td>resendHandler</td><td>() => void</td><td>Triggers OTP resend functionality.</td></tr><tr><td>onSubmit</td><td>(event: FormEvent&#x3C;HTMLFormElement>) => Promise&#x3C;void></td><td>Form submit function that wraps validation and calls submitAction.</td></tr><tr><td>otp</td><td>string</td><td>Current OTP value in the input field.</td></tr><tr><td>setOtp</td><td>(otp: string) => void</td><td>Updates the OTP input value.</td></tr><tr><td>hasError</td><td>boolean</td><td>Whether the current OTP input has a validation error.</td></tr><tr><td>error</td><td>string</td><td>Error message for invalid OTP attempts.</td></tr><tr><td>canResend</td><td>boolean</td><td>Indicates whether the resend option is enabled.</td></tr><tr><td>time</td><td>number</td><td>Countdown in seconds for the resend option.</td></tr><tr><td>codeLength</td><td>number</td><td>Expected number of digits in the OTP input.</td></tr><tr><td>setHasError</td><td>(hasError: boolean) => void</td><td>Allows toggling of error state manually.</td></tr></tbody></table>

## <mark style="color:red;">**Usage Example**</mark>

### <mark style="color:red;">**Default Usage**</mark>

```javascript
import PluginModule, { Component } from '@akinon/next/components/plugin-module';

<PluginModule
   component={Component.Otp}
   props={{
     data: getValues(),
     submitAction: registerHandler
   }}

 />
```

### <mark style="color:red;">Customizing OTP</mark>

```javascript
import PluginModule, { Component } from '@akinon/next/components/plugin-module';

<PluginModule
  component={Component.Otp}
  props={{
    data: getValues(),
    submitAction: registerHandler,
    customUIRender: ({
      closeHandler,
      resendHandler,
      onSubmit,
      otp,
      setOtp,
      hasError,
      error,
      canResend,
      time,
      codeLength,
      setHasError
    }) => {
      return (
        <div className="fixed left-0 top-0 z-50 flex h-screen w-screen items-end md:items-center md:justify-center md:bg-black/10">
          <div className="h-[calc(100vh-48px)] w-screen flex md:h-auto md:max-w-lg flex-col items-center rounded-sm bg-white p-8 shadow-xl">
            <div className="w-full flex items-center justify-end">
              <div className="cursor-pointer" onClick={closeHandler}>
                <svg
                  width="14"
                  height="14"
                  viewBox="0 0 14 14"
                  xmlns="http://www.w3.org/2000/svg"
                >
                  <g fill="#000" fillRule="nonzero">
                    <path d="M.684 14A.684.684 0 0 1 .2 12.833L12.833.2a.684.684 0 1 1 .967.967L1.167 13.8a.682.682 0 0 1-.483.2z" />
                    <path d="M13.316 14a.682.682 0 0 1-.483-.2L.2 1.167A.684.684 0 0 1 1.167.2L13.8 12.833A.684.684 0 0 1 13.316 14z" />
                  </g>
                </svg>
              </div>
            </div>
            <div className="flex flex-col items-center px-14 mt-5">
              <div className="text-2xl font-medium">OTP Verification</div>
              <div className="mt-2.5 text-center text-gray-700">
                {`Please enter the ${codeLength}-digit sms code sent to your registered number and email address`}
              </div>
            </div>
            <form
              onSubmit={onSubmit}
              className="flex flex-col items-center w-full"
            >
              <OtpInput
                value={otp}
                onChange={(otp) => {
                  setOtp(otp);
                  setHasError(false);
                }}
                numInputs={codeLength}
                containerStyle="mt-12 gap-2 flex-wrap"
                inputStyle={`h-12 w-8 md:h-16 md:w-12 rounded-md border border-gray-600 text-center text-lg ${hasError ? 'border-error' : ''}`}
                renderInput={(props) => <input {...props} />}
                skipDefaultStyles={true}
              />
              {error && <p className="text-xs text-error mt-2">{error}</p>}
              <Button
                type="submit"
                className="mt-5 h-auto w-full py-4 text-lg font-medium uppercase"
              >
                Verify
              </Button>
            </form>
            <div className="mt-6 flex flex-col items-center">
              <span className="text-gray-700">I didn’t receive a code</span>
              <div
                className={`font-medium underline cursor-pointer ${!canResend ? 'cursor-not-allowed text-gray-700' : ''}`}
                onClick={resendHandler}
              >
                RESEND
              </div>
            </div>
          </div>
        </div>
      );
    }
  }}
/>;
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.akinon.com/technical-guides/project-zero/next.js/plugins/otp.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
