Caputchin
Guías de integración

Ejemplos de integración de frontend

El widget es un custom element estándar, así que funciona en cada framework sin un wrapper que instalar. La forma siempre es la misma: carga el paquete una vez (integración del lado del cliente), renderiza <caputchin-widget sitekey="cpt_pub_..."> dentro de tu formulario, y lee el campo oculto caputchin-token que inyecta cuando el visitante supera el reto. Para un juego, cámbialo por <caputchin-game ... game="caputchin/games/leaf-memory">.

Los ejemplos de abajo difieren solo en la sintaxis de cada framework y en su única peculiaridad de custom element.

HTML plano

El campo inyectado viaja junto a un POST de formulario normal, así que no hay nada que cablear:

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

<form action="/contact" method="POST">
  <input name="email" type="email" required />
  <caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
  <button type="submit">Send</button>
</form>

React

Importa una vez al arranque, luego lee el campo de FormData al enviar:

import "@caputchin/widget";

export function ContactForm() {
  async function handleSubmit(e) {
    e.preventDefault();
    const data = new FormData(e.currentTarget);
    await fetch("/api/contact", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ email: data.get("email"), token: data.get("caputchin-token") }),
    });
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="email" type="email" required />
      <caputchin-widget sitekey="cpt_pub_..." />
      <button type="submit">Send</button>
    </form>
  );
}

Si usas TypeScript con React, declara ambos elementos una vez para que JSX los acepte:

// caputchin.d.ts
import type { DetailedHTMLProps, HTMLAttributes } from "react";
declare module "react" {
  namespace JSX {
    interface IntrinsicElements {
      "caputchin-widget": DetailedHTMLProps<HTMLAttributes<HTMLElement> & { sitekey: string }, HTMLElement>;
      "caputchin-game": DetailedHTMLProps<HTMLAttributes<HTMLElement> & { sitekey: string; game?: string; games?: string }, HTMLElement>;
    }
  }
}

Esta forma declare module "react" es específica del JSX de React. En TypeScript plano los elementos son solo HTMLElement y no necesitan declaración, y los demás frameworks de abajo tipan los custom elements a su manera, así que solo necesitas este bloque en un proyecto de React.

Vue

Dile al compilador de Vue que las etiquetas caputchin- son custom elements, para que no intente resolverlas como componentes:

// vite.config.js
export default {
  plugins: [vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith("caputchin-") } } })],
};
<script setup>
import "@caputchin/widget";
function onSubmit(e) {
  const data = new FormData(e.target);
  // send data.get("caputchin-token") to your backend
}
</script>

<template>
  <form @submit.prevent="onSubmit">
    <input name="email" type="email" required />
    <caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
    <button type="submit">Send</button>
  </form>
</template>

Svelte

Svelte renderiza los custom elements tal cual, sin configuración necesaria:

<script>
  import "@caputchin/widget";
  function onSubmit(e) {
    const data = new FormData(e.currentTarget);
    // send data.get("caputchin-token") to your backend
  }
</script>

<form on:submit|preventDefault={onSubmit}>
  <input name="email" type="email" required />
  <caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
  <button type="submit">Send</button>
</form>

Angular

Añade CUSTOM_ELEMENTS_SCHEMA al módulo o al componente standalone para que Angular permita la etiqueta desconocida, e importa el paquete una vez (en main.ts):

import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@caputchin/widget";

@Component({
  selector: "contact-form",
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    <form (submit)="onSubmit($event)">
      <input name="email" type="email" required />
      <caputchin-widget sitekey="cpt_pub_..."></caputchin-widget>
      <button type="submit">Send</button>
    </form>
  `,
})
export class ContactFormComponent {
  onSubmit(e: Event) {
    const data = new FormData(e.target as HTMLFormElement);
    // send data.get("caputchin-token") to your backend
  }
}

Next.js

El mismo código de React funciona. El custom element se renderiza como una etiqueta vacía durante el render en el servidor y se actualiza en el cliente una vez que el paquete carga, así que no hace falta ningún tratamiento especial más allá de importar @caputchin/widget en un componente de cliente (o cargar el script del CDN con next/script).

Véase también

En esta página