@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/reactPeer 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
- A running Docufast instance (the library backend)
- An EsignApp created in the Docufast dashboard
- An API Key generated for the app (Settings > API Keys)
- At least one EsignGroup (represents a tenant/org, e.g. per branch)
- 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 completionBackend 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/docufastPayload:
{
"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