npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@docufast/react

v0.1.2

Published

React components and API client for Docufast e-signing

Downloads

223

Readme

@docufast/react

React components and API client for embedding Docufast e-signing into any application.

Requirement: Use of this package requires a valid Docufast account.

Installation

npm install @docufast/react

Peer dependencies: @mui/material, @mui/icons-material, @emotion/react, @emotion/styled, react, react-dom

Quick Start

import { DocufastProvider, DocufastContractWidget } from "@docufast/react";

function App() {
  return (
    <DocufastProvider baseUrl="https://your-instance.com" apiKey="YOUR_API_KEY">
      <DocufastContractWidget
        appId="app-uuid"
        groupId="group-uuid"
        fields={{ tenant_name: "John Doe", monthly_rent: 850 }}
        signers={[{ name: "John Doe", email: "[email protected]" }]}
        onContractCreated={(contractId, signerId) => {
          // persist IDs to your database
        }}
        onSigned={(signer) => console.log("Signed!", signer)}
        onError={(err) => console.error(err)}
      />
    </DocufastProvider>
  );
}

Components

<DocufastProvider>

Wraps your app with the Docufast client context. Required by all components and hooks.

<DocufastProvider baseUrl="https://..." apiKey="YOUR_API_KEY">
  {children}
</DocufastProvider>

<DocufastContractWidget>

Self-contained widget for the full contract lifecycle: template selection, PDF generation, and signing.

Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | appId | string | Yes | Docufast application ID | | groupId | string | Yes | Group (tenant/org) that owns the contract | | templateId | string | No | Template UUID. Omit to show a dropdown | | fields | Record<string, unknown> | Yes | Field values injected into the template | | signers | AddSignerInput[] | Yes | Signers for the contract | | title | string | No | Display title. Falls back to template name | | metadata | Record<string, unknown> | No | Custom metadata attached to the contract | | contractId | string \| null | No | Existing contract ID — widget fetches real status | | signerId | string \| null | No | Existing signer ID — required with contractId | | variant | "card" \| "fab" | No | card (default) or fab (floating action button) | | onContractCreated | (contractId, signerId) => void | No | Fired after generation succeeds | | onSigned | (signer) => void | No | Fired when signing completes | | onError | (error) => void | No | Fired on any error |

Usage: Auto template selection (recommended)

Omit templateId — the widget fetches templates, shows a dropdown, and auto-selects the group's default template. Includes a gear icon to set the default.

<DocufastContractWidget
  appId="app-uuid"
  groupId="group-uuid"
  fields={{
    landlord_name: "Jane Smith",
    tenant_name: "John Doe",
    property_address: "123 Main St, Athens",
    monthly_rent: 850,
    deposit_amount: 1700,
    lease_start_date: "2026-04-01",
    lease_end_date: "2027-03-31",
    payment_due_day: 1,
    pets_allowed: false,
  }}
  signers={[{ name: "John Doe", email: "[email protected]" }]}
  onContractCreated={(contractId, signerId) => {
    // save to your DB
  }}
  onSigned={(signer) => console.log("Done!", signer)}
  onError={(err) => console.error(err)}
/>

Usage: Fixed template

Pass templateId to skip the dropdown and use a specific template.

<DocufastContractWidget
  appId="app-uuid"
  groupId="group-uuid"
  templateId="template-uuid"
  title="Rental Agreement — John Doe"
  fields={{
    landlord_name: "Jane Smith",
    tenant_name: "John Doe",
    property_address: "123 Main St, Athens",
    monthly_rent: 850,
    deposit_amount: 1700,
    lease_start_date: "2026-04-01",
    lease_end_date: "2027-03-31",
    payment_due_day: 1,
    pets_allowed: false,
  }}
  signers={[{ name: "John Doe", email: "[email protected]" }]}
  onContractCreated={(contractId, signerId) => {
    // save to your DB
  }}
  onSigned={(signer) => console.log("Done!", signer)}
/>

Usage: Resume existing contract

Pass contractId and signerId to resume — the widget fetches the real status on mount.

<DocufastContractWidget
  appId="app-uuid"
  groupId="group-uuid"
  templateId="template-uuid"
  fields={{ tenant_name: "John Doe", monthly_rent: 850 }}
  signers={[{ name: "John Doe", email: "[email protected]" }]}
  contractId={booking.docufastContractId}
  signerId={booking.docufastSignerId}
  onSigned={(signer) => markBookingSigned(booking.id)}
/>

<TemplateSelector>

Displays available templates for an app. User selects which contract type to use.

<TemplateSelector
  appId="app-uuid"
  onSelect={(template) => console.log(template.id, template.name)}
  selectedId={currentTemplateId}
/>

<ContractPreview>

Shows the contract PDF in an iframe.

<ContractPreview
  appId="..."
  groupId="..."
  contractId="..."
  height={500}
/>

<SigningFlow>

Full embedded signing experience: review PDF, draw/type/upload signature, submit.

<SigningFlow
  appId="..."
  groupId="..."
  contractId="..."
  signerId="..."
  onComplete={(signer) => console.log("Signed")}
  onDecline={(signer) => console.log("Declined")}
  onError={(err) => console.error(err)}
/>

<SignaturePad>

Standalone signature capture pad (draw, type, or upload).

<SignaturePad onSignatureChange={(data) => {
  // data: { signature: string, signature_type: "draw"|"type"|"upload", typed_name?: string }
  // or null when cleared
}} />

Hooks

useDocufast()

Access the DocufastClient from context.

const { client } = useDocufast();
const templates = await client.listTemplates(appId);

useTemplates(appId)

List and fetch templates for an app.

const { templates, loading, error, refresh, getTemplate } = useTemplates(appId);

useContract(appId, groupId)

Create, fetch, and manage contracts.

const {
  contract,
  loading,
  error,
  createFromFields,   // Generate from template + fields (no PDF)
  createFromTemplate, // Upload PDF + fill template
  addSigners,
  fetch,
  getPdfUrl,
} = useContract(appId, groupId);

// Create contract from template fields (recommended — no PDF upload)
const result = await createFromFields(templateId, fields, signers, title);
// result: { contract, signers }

// Add signers after creation
const signers = await addSigners(contractId, [{ name: "John", email: "[email protected]" }]);

useSigning(appId, groupId)

Manage signing sessions for in-person signing.

const { startSession, sign, decline, sessionToken, status, contract, signer } = useSigning(appId, groupId);

// Start a session for a contract + signer
const token = await startSession(contractId, signerId);

// Capture signature (use with SignaturePad)
await sign(token, { signature: "...", signature_type: "draw" });

API Client

Use DocufastClient directly for full control:

import { DocufastClient } from "@docufast/react";

const client = new DocufastClient({ baseUrl: "https://...", apiKey: "YOUR_API_KEY" });

// Templates
const templates = await client.listTemplates(appId);
const template = await client.getTemplate(appId, templateId);

// Groups
const groups = await client.listGroups(appId);
const group = await client.getGroup(appId, groupId);
await client.updateGroup(appId, groupId, { default_template_id: templateId });

// Contracts
const result = await client.createContractFromFields(appId, groupId, templateId, fields, signers, title);
const contract = await client.getContract(appId, groupId, contractId);
const status = await client.getContractStatus(appId, groupId, contractId);

// Signers
const signers = await client.addSigners(appId, groupId, contractId, [
  { name: "John Doe", email: "[email protected]" }
]);

// Sessions & Signing
const session = await client.createSession(appId, groupId, contractId, signerId);
const signingData = await client.getSessionSigningData(session.session_token);
await client.captureSessionSignature(session.session_token, { signature: "...", signature_type: "draw" });

// PDF
const pdfUrl = await client.getPdfUrl(appId, groupId, contractId);
const signedPdfUrl = await client.getSignedPdfUrl(appId, groupId, contractId);

// Audit
const logs = await client.getAuditTrail(appId, groupId, contractId);

Field Mapping

Map your domain objects to flat contract fields:

import { createFieldMapper, defaultCarRentalFieldMapper } from "@docufast/react";

// Use the built-in car rental mapper
const fields = defaultCarRentalFieldMapper({ customer, booking, business });

// Or create a custom mapper
const myMapper = createFieldMapper({
  customer_name: "customer.fullName",
  start_date: "reservation.checkIn",
  room_number: "reservation.room.number",
});
const fields = myMapper({ customer, reservation });

Integration Guide

How to integrate @docufast/react into your application (e.g. booking system, CRM) for document signing.

Prerequisites

  1. A running Docufast instance (the library backend)
  2. An EsignApp created in the Docufast dashboard
  3. An API Key generated for the app (Settings > API Keys)
  4. At least one EsignGroup (represents a tenant/org, e.g. per branch)
  5. At least one EsignTemplate with JSON Schema and UI Schema defined

Next.js Configuration

Add to your next.config.ts:

const nextConfig = {
  transpilePackages: ["@docufast/react"],
};

1. Wrap with Provider

import { DocufastProvider } from "@docufast/react";

// In your app layout or page
<DocufastProvider
  baseUrl={process.env.NEXT_PUBLIC_DOCUFAST_URL!}
  apiKey={process.env.NEXT_PUBLIC_DOCUFAST_API_KEY!}
>
  {children}
</DocufastProvider>

2. Use the Widget (recommended)

The DocufastContractWidget handles everything: template selection, PDF generation, and signing. No PDF upload needed — contracts are generated from template fields.

import { DocufastContractWidget } from "@docufast/react";

<DocufastContractWidget
  appId={process.env.NEXT_PUBLIC_DOCUFAST_APP_ID!}
  groupId={groupId}
  fields={{
    landlord_name: "Jane Smith",
    tenant_name: customer.name,
    property_address: property.address,
    monthly_rent: 850,
    deposit_amount: 1700,
    lease_start_date: "2026-04-01",
    lease_end_date: "2027-03-31",
    payment_due_day: 1,
    pets_allowed: false,
  }}
  signers={[{ name: customer.name, email: customer.email }]}
  onContractCreated={(contractId, signerId) => {
    // Persist to your database
    await updateBooking(booking.id, { docufast_contract_id: contractId });
    await updateCustomer(customer.id, { docufast_signer_id: signerId });
  }}
  onSigned={(signer) => {
    toast.success("Contract signed successfully");
  }}
  onError={(err) => toast.error(err)}
/>

3. Programmatic Flow (hooks)

For full control, use useContract and useSigning:

import { useContract, useDocufast, createFieldMapper } from "@docufast/react";

const { createFromFields, addSigners } = useContract(appId, groupId);
const { client } = useDocufast();

// 1. Select template (or use TemplateSelector)
const template = await client.getTemplate(appId, templateId);

// 2. Map your domain data to flat fields
const mapper = createFieldMapper({
  customer_name: "customer.name",
  booking_start: "booking.startDate",
  vehicle_plate: "booking.vehicle.plate",
});
const fields = mapper({ customer, booking });

// 3. Create contract (no PDF — generated from template)
const result = await createFromFields(templateId, fields, [], title);
if (result) {
  const { contract, signers } = result;
  // 4. Add signers if not passed in createFromFields
  const added = await addSigners(contract.id, [
    { name: customer.name, email: customer.email },
  ]);
  // Save contract.id and signers[0].id to your DB
}

4. Signing Flow (at pickup / kiosk)

Use SigningFlow when the signer is present (e.g. tablet at pickup):

import { SigningFlow } from "@docufast/react";

<SigningFlow
  appId={appId}
  groupId={groupId}
  contractId={booking.docufast_contract_id}
  signerId={customer.docufast_signer_id}
  onComplete={(signer) => {
    toast.success("Contract signed successfully");
  }}
  onDecline={(signer) => {
    toast.error("Customer declined to sign");
  }}
  onError={(err) => toast.error(err)}
/>

Data Flow

1. Owner opens booking in your app
2. Selects template (or omit — widget uses group default)
3. App maps booking + customer + business data to flat fields
4. createFromFields() or DocufastContractWidget generates PDF
5. App saves contract_id + signer_id to your DB
6. Owner hands tablet to customer at pickup
7. SigningFlow shows contract PDF + signature pad
8. Customer signs → signature captured + PDF signed
9. Webhook (optional) notifies your system of completion

Backend Requirements (optional)

If your app has its own DB (e.g. bookings, customers), add nullable columns:

ALTER TABLE bookings ADD COLUMN docufast_contract_id VARCHAR(36) NULL;
ALTER TABLE customers ADD COLUMN docufast_signer_id VARCHAR(36) NULL;

You need PUT/PATCH endpoints to update these fields from the frontend after contract creation and signing.

Webhook Setup (optional)

Configure a webhook URL in the Docufast app settings to receive notifications:

POST https://your-system.com/api/webhooks/docufast

Payload:

{
  "event": "contract.completed",
  "contract_id": "...",
  "app_id": "...",
  "timestamp": "..."
}

Verify the webhook signature using the HMAC-SHA256 X-Webhook-Signature header with your webhook secret.

Environment Variables

NEXT_PUBLIC_DOCUFAST_URL=https://your-docufast-instance.com
NEXT_PUBLIC_DOCUFAST_API_KEY=YOUR_API_KEY
NEXT_PUBLIC_DOCUFAST_APP_ID=uuid-of-app
NEXT_PUBLIC_DOCUFAST_GROUP_ID=uuid-of-group