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

# Quickstart

> Install Ribaunt, configure your secret, issue signed challenges, verify the submitted proofs, and embed the browser widget in minutes.

This guide walks you through building a complete Ribaunt CAPTCHA integration: two server endpoints that issue and verify proof-of-work challenges, plus a browser widget your users interact with. By the end you'll have a working bot-protection layer you can drop in front of any form or API action.

<Steps>
  <Step title="Install Ribaunt">
    Add the `ribaunt` package to your project.

    <CodeGroup>
      ```bash npm theme={null}
      npm install ribaunt
      ```

      ```bash yarn theme={null}
      yarn add ribaunt
      ```

      ```bash pnpm theme={null}
      pnpm add ribaunt
      ```
    </CodeGroup>
  </Step>

  <Step title="Set your secret">
    Ribaunt signs every challenge token with a secret you control. Add `RIBAUNT_SECRET` to your server environment — a `.env` file, your hosting platform's secrets manager, or however you manage server config.

    ```env theme={null}
    RIBAUNT_SECRET="replace-with-a-long-random-secret"
    ```

    <Warning>
      Keep `RIBAUNT_SECRET` server-only. Never expose it to the browser. In Next.js, do **not** prefix it with `NEXT_PUBLIC_` — that would embed the secret in your client bundle and allow anyone to forge valid challenge tokens.
    </Warning>
  </Step>

  <Step title="Create server endpoints">
    You need two endpoints: one that issues challenges and one that verifies solutions. Here is a complete Express example using the current `createChallenge` and `verifySolution` APIs from `ribaunt`.

    ```ts theme={null}
    import 'dotenv/config';
    import express from 'express';
    import { createChallenge, verifySolution } from 'ribaunt';

    const app = express();
    app.use(express.json());

    app.get('/api/captcha/challenge', (_req, res) => {
      const challenges = createChallenge({
        difficulty: 5,
        amount: 4,
        ttlSeconds: 120,
        context: 'signup',
      });

      res.json({ challenges });
    });

    app.post('/api/captcha/verify', async (req, res) => {
      const { tokens, solutions } = req.body;
      const result = await verifySolution(tokens, solutions, { context: 'signup' });

      if (!result.valid) {
        return res.status(400).json({ success: false, error: result.reason, message: result.message });
      }

      return res.json({ success: true });
    });

    app.listen(3000);
    ```

    `createChallenge()` accepts either positional arguments or an options object. The options object supports `difficulty`, `amount`, `ttlSeconds`, `context`, and an adaptive `workload` configuration.

    `verifySolution()` now returns a structured result object instead of a bare boolean. Check `result.valid` and use `result.reason` or `result.message` when verification fails.
  </Step>

  <Step title="Add the widget to your frontend">
    Include the Ribaunt web component script and place the `<ribaunt-widget>` element wherever you need CAPTCHA protection. The widget fetches a challenge from your server, solves it in the browser, and sends the solutions back to your verify endpoint when `auto-verify="true"` is set.

    ```html theme={null}
    <script type="module" src="/node_modules/ribaunt/dist/widget-browser.js"></script>

    <ribaunt-widget
      challenge-endpoint="/api/captcha/challenge"
      verify-endpoint="/api/captcha/verify"
      auto-verify="true"
      solve-timeout="15000"
    ></ribaunt-widget>

    <script>
      const widget = document.querySelector('ribaunt-widget');

      widget.addEventListener('verify', (event) => {
        console.log('Verified!', event.detail.solutions);
      });
    </script>
    ```

    If you're using React, import the wrapper component instead of the web component directly. See [React Integration](/integrations/react) for the full example.
  </Step>
</Steps>

<Note>
  The widget emits a `verify` event when the challenge is solved. A corresponding `error` event fires if verification fails, and `state-change` reports intermediate states such as `fetching`, `solving`, `verifying`, and `done`.
</Note>

## Next steps

<CardGroup cols={2}>
  <Card title="Widget configuration" icon="sliders" href="/widget/configuration">
    Explore all widget attributes — timeouts, worker mode, challenge method, calibration, theming, and the `disabled` state.
  </Card>

  <Card title="React integration" icon="react" href="/integrations/react">
    Use the `ribaunt/widget-react` wrapper with full prop support in React and Next.js App Router.
  </Card>

  <Card title="Express server example" icon="server" href="/server/express">
    A production-ready Express server setup with replay protection, structured warnings, and context-aware verification.
  </Card>
</CardGroup>
