Hanzo Sign - Open Source Document Signing
Hanzo Sign is an open-source DocuSign alternative for electronic document signing. Turborepo monorepo with a React Router (Remix) + Hono server frontend, tRPC + ts-rest APIs, Prisma ORM, and PDF si...
Overview
Hanzo Sign is an open-source DocuSign alternative for electronic document signing. Turborepo monorepo with a React Router (Remix) + Hono server frontend, tRPC + ts-rest APIs, Prisma ORM, and PDF signing via P12 certificates or Google Cloud KMS. Live at sign.hanzo.ai. Version 2.7.1. Licensed AGPL-3.0.
Why Hanzo Sign?
- Self-hostable: Full control over your signing infrastructure
- Open source: Inspect and audit the entire signing pipeline
- Multiple signing providers: Local P12 certificates or Google Cloud HSM
- Swappable storage: Database or S3-compatible object storage
- API-first: REST (V1) and tRPC (V2) APIs with OpenAPI spec
- Enterprise features: Teams, custom branding, webhooks, bulk sending
- i18n: Multi-language via Lingui
- AI integration: Google Vertex AI (Gemini) for document analysis
Tech Stack
- Frontend: React 18, React Router v7 (Remix), Tailwind CSS, shadcn/ui, Radix UI
- Server: Hono (on Node.js)
- Database: PostgreSQL 15 (Prisma ORM + Kysely)
- API: tRPC (V2, current), ts-rest (V1, deprecated)
- Auth: Arctic (OAuth), WebAuthn/Passkeys, Hanzo IAM (hanzo.id)
- Email: React Email, Nodemailer (SMTP, Resend, MailChannels)
- PDF: @libpdf/core, pdfjs-dist, PDF-Lib
- Jobs: Inngest or local database-backed queue
- Build: Turborepo + npm workspaces, Vite
- Testing: Playwright (E2E)
OSS Base
Repo: hanzoai/sign (fork of documenso/documenso).
When to use
- Sending documents for electronic signature
- Building document signing workflows
- Self-hosting a DocuSign-like service
- Creating document templates for recurring signatures
- Bulk sending documents via API
- Embedding signing into existing applications
Hard requirements
- Node.js v22 or above
- PostgreSQL database
- SMTP server or email provider (Resend, MailChannels)
- P12 signing certificate (or Google Cloud KMS)
Quick reference
| Item | Value |
|---|---|
| UI | https://sign.hanzo.ai (port 3000) |
| API V2 | /api/v2/* (tRPC + OpenAPI) |
| API V1 | /api/v1/* (ts-rest, deprecated) |
| Auth | Arctic OAuth + WebAuthn + Hanzo IAM |
| DB | PostgreSQL (Prisma + Kysely) |
| Root package | @hanzo/sign-root |
| Version | 2.7.1 |
| License | AGPL-3.0 |
| Repo | github.com/hanzoai/sign |
One-file quickstart
Developer Quickstart (Docker)
# Clone and setup
git clone https://github.com/hanzoai/sign.git
cd sign
cp .env.example .env
# One command: install, start db/mail containers, migrate, seed, dev
npm run dManual Setup
npm install
cp .env.example .env
# Set required env vars:
# NEXTAUTH_SECRET, NEXT_PUBLIC_WEBAPP_URL
# NEXT_PRIVATE_DATABASE_URL, NEXT_PRIVATE_DIRECT_DATABASE_URL
# NEXT_PRIVATE_SMTP_FROM_NAME, NEXT_PRIVATE_SMTP_FROM_ADDRESS
npm run prisma:migrate-dev
npm run translate:compile
npm run devDocker (Production)
docker run -d --restart=unless-stopped \
-p 3000:3000 \
-v hanzo-sign:/app/data \
--name hanzo-sign \
hanzo-sign:latestCore Concepts
Architecture
Remix App (Hono Server)
apps/remix
/api/v1/* /api/v2/* /api/trpc/* /api/jobs/* React Router UI
(ts-rest) (tRPC) (tRPC) (Jobs API)
| | | |
@hanzo/sign-api @hanzo/sign-trpc @hanzo/sign-lib @hanzo/sign-email
|
+--------------+--------------+
| | |
Storage Jobs PDF Signing
Provider Provider Provider
| | |
DB or S3 Inngest/Local Local P12 or GCloud HSMMonorepo Packages
Applications (apps/):
| Package | Description | Port |
|---|---|---|
@hanzo/sign-remix | Main app (React Router + Hono) | 3000 |
@hanzo/sign-documentation | Documentation site (Nextra) | 3002 |
@hanzo/sign-openpage-api | Public analytics API | 3003 |
Core Packages (packages/):
| Package | Description |
|---|---|
@hanzo/sign-lib | Core business logic (server, client, universal) |
@hanzo/sign-trpc | tRPC API layer with OpenAPI (V2) |
@hanzo/sign-api | REST API layer via ts-rest (V1) |
@hanzo/sign-prisma | Database layer (Prisma ORM + Kysely) |
@hanzo/sign-ui | UI components (shadcn + Radix + Tailwind) |
@hanzo/sign-email | Email templates (React Email) |
@hanzo/sign-auth | Auth (Arctic OAuth, WebAuthn/Passkeys) |
@hanzo/sign-signing | PDF signing (Local P12, Google Cloud KMS) |
@hanzo/sign-ee | Enterprise Edition features |
@hanzo/sign-assets | Static assets |
Swappable Providers
Storage (NEXT_PUBLIC_UPLOAD_TRANSPORT):
database-- Store files as Base64 in PostgreSQL (default)s3-- S3-compatible storage (AWS, MinIO, etc.)
PDF Signing (NEXT_PRIVATE_SIGNING_TRANSPORT):
local-- P12 certificate file (default)gcloud-hsm-- Google Cloud KMS Hardware Security Module
Email (NEXT_PRIVATE_SMTP_TRANSPORT):
smtp-auth-- Standard SMTP with credentials (default)smtp-api-- SMTP with API keyresend-- Resend APImailchannels-- MailChannels API
Background Jobs (NEXT_PRIVATE_JOBS_PROVIDER):
local-- Database-backed queue (default)inngest-- Managed cloud service
Document Signing Flow
- Upload document to storage provider (DB or S3)
- Add recipients (signers, viewers, approvers)
- Add signature fields (positions on PDF)
- Send document (triggers email job)
- Recipient signs via unique link
seal-documentjob finalizes the PDF- Signing provider cryptographically signs the PDF
- Signed PDF stored back to storage provider
Auth / IAM Integration
Hanzo Sign supports Hanzo IAM (hanzo.id) for production auth:
IAM_URL="https://hanzo.id"
IAM_CLIENT_ID="<your-client-id>"
IAM_CLIENT_SECRET="<your-client-secret>"Also supports Google OAuth, Microsoft OAuth, and generic OIDC providers.
Signing Certificates
For local signing, generate a P12 certificate:
openssl genrsa -out private.key 2048
openssl req -new -x509 -key private.key -out certificate.crt -days 365
read -s -p "Enter certificate password: " CERT_PASS
openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt \
-password env:CERT_PASS -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1Place at apps/remix/resources/certificate.p12.
Environment Variables
| Variable | Purpose | Options |
|---|---|---|
NEXTAUTH_SECRET | Session encryption | Random string |
NEXT_PUBLIC_WEBAPP_URL | Public URL | https://sign.hanzo.ai |
NEXT_PRIVATE_DATABASE_URL | PostgreSQL connection | Connection string |
NEXT_PUBLIC_UPLOAD_TRANSPORT | Storage provider | database, s3 |
NEXT_PRIVATE_SIGNING_TRANSPORT | Signing provider | local, gcloud-hsm |
NEXT_PRIVATE_SMTP_TRANSPORT | Email provider | smtp-auth, smtp-api, resend, mailchannels |
NEXT_PRIVATE_JOBS_PROVIDER | Jobs provider | local, inngest |
IAM_URL | Hanzo IAM endpoint | https://hanzo.id |
Development Services (Docker)
| Service | Port |
|---|---|
| PostgreSQL | 54320 |
| Inbucket (Mail UI) | 9000 |
| Inbucket (SMTP) | 2500 |
| MinIO (S3 Dashboard) | 9001 |
| MinIO (S3 API) | 9002 |
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| No emails received | Using dev quickstart | Check Inbucket at http://localhost:9000 |
| "Failed to get private key bags" | P12 cert has no password | Re-create with password (min 4 chars) |
| Can't see env vars in scripts | Env not loaded | Wrap with npm run with:env -- npm run myscript |
| IPv6 deployment | Default binds IPv4 | Pass npm run start -- -H :: |
| Lingui errors | Translations not compiled | Run npm run translate:compile |
Related Skills
hanzo/hanzo-id.md- IAM and authentication (hanzo.id)hanzo/hanzo-kms.md- Secret managementhanzo/hanzo-platform.md- PaaS deploymenthanzo/hanzo-commerce.md- E-commerce (contracts, checkout)
How is this guide?
Last updated on
Hanzo Reconciliation
Hanzo Reconciliation is an automated transaction matching engine that compares ledger balances against payment provider data to verify financial consistency and identify discrepancies. It runs as a...
Hanzo Treasury
Hanzo Treasury is a programmable financial infrastructure stack providing a double-entry ledger, payment connectors, virtual wallets, reconciliation, and workflow orchestration. Go monorepo (forked...