Files
cap/docs/guide/index.md
T
Tiago Rangel 5e82f1f4d7 Changes
2025-01-14 13:07:08 +00:00

2.9 KiB

outline
outline
deep

Quickstart

Adding the Cap widget

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 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:

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.

Client-side

Start by adding it from a CDN:

<script src="https://cdn.jsdelivr.net/npm/@cap.js/widget"></script>

Next, add the <cap-widget> component to your HTML.

<cap-widget id="cap" cap-api-endpoint="<your cap api endpoint>"></cap-widget>

Note: You'll need to start a server with the Cap API running at the same URL as specified in the 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('/<endpoint>/...', ...).

The following attributes are supported:

  • 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:

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 <form></form> (where Cap will automatically submit the token alongside other form data).

Server-Side Validation

Once the token is generated and captured, you can use it later to validate the user's identity. This is typically done by sending the token to a server-side endpoint that uses the Cap API for validation.

You can do this by calling cap.validateToken:

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 }).