--- outline: deep --- # Quickstart [[toc]] ## Client-side Start by adding it from a CDN: ```html ``` Next, add the `` component to your HTML. ```html ``` **Note:** You'll need to start a server with the Cap API running at the same URL as specified in the `data-cap-api-endpoint` attribute. In the server-side example we provided, it's set to `/api`, but you can change this by replacing every `app.post('/api/...', ...)` to `app.post('//...', ...)`. > [!NOTE] > You'll need to start a server with the Cap API running at the same URL as specified in the `data-cap-api-endpoint` attribute. > In the server-side example we provided, it's set to `/api`, but you can change this by replacing every `app.post('/api/...', ...)` to `app.post('//...', ...)`. > [!TIP] > The following attributes are supported: > > * `data-cap-api-endpoint`: API endpoint (required) > * `data-cap-worker-count`: Number of workers to use (defaults to `navigator.hardwareConcurrency || 8`) Then, in your JavaScript, listen for the `solve` event to capture the token when generated: ```js{3} const widget = document.querySelector("#cap"); widget.addEventListener("solve", function (e) { const token = e.detail.token; // Handle the token as needed }); ``` Alternatively, you can use `onsolve=""` directly within the widget or wrap the widget in a `
` (where Cap will automatically submit the token alongside other form data). ## Server-side Cap is fully self-hosted, so you'll need to start a server with the Cap API running at the same URL as specified in the `data-cap-api-endpoint` attribute. This is easy since we've already pre-made a library to help you generate and validate challenges for you. Start by installing it using npm or bun: ``` npm i @cap.js/server ``` Now, you'll need to change your server code to add the routes that Cap needs to work. Here's an example with Express.js: ```js const express = require('express'); const Cap = require('@cap.js/server'); const app = express(); app.use(express.json()); const cap = new Cap({ tokens_store_path: '.data/tokensList.json' // make sure this file has already been created and added to your gitignore }); app.post('/api/challenge', (req, res) => { res.json(cap.createChallenge()); }); app.post('/api/redeem', async (req, res) => { const { token, solutions } = req.body; if (!token || !solutions) { return res.status(400).json({ success: false }); } res.json(await cap.redeemChallenge({ token, solutions })); }); app.listen(3000, () => { console.log('Listening on port 3000'); }) ``` It should be pretty easy to replicate this code but with other frameworks such as Hono. ::: details Methods The following methods are supported: #### `new Cap({ ... })` Creates a new Cap instance. **Arguments** ```json { tokens_store_path: ".data/tokensList.json", state: { challengesList: {}, tokensList: {}, }, } ``` > [!TIP] > You can always access or set the options of the `Cap` class by accessing or modifying the `cap.config` object. #### `cap.createChallenge({ ... })` **Arguments** ```json { challengeCount: 18, challengeSize: 32, challengeDifficulty: 4, expiresMs: 600000 } ``` **Output:** `{ challenge, expires }` #### `cap.redeemChallenge({ ... })` ```json { token, solutions } ``` **Output:** `{ success, token }` #### `await cap.validateToken("...", { ... })` **Arguments:** ```json { keepToken: false } ``` **Output:** `{ success }` ::: ### Token Validation Once the token is generated and captured, you can use it later to validate the user's identity. You can do this by calling `await cap.validateToken` in your server-side code: ```js await cap.validateToken("...") // returns { success: Boolean } ``` Note that the token will immediately be deleted after this. To prevent this, use `await cap.validateToken("...", { keepToken: true })`.