Skillshub documenso-reference-architecture

install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/jeremylongshore/claude-code-plugins-plus-skills/documenso-reference-architecture" ~/.claude/skills/comeonoliver-skillshub-documenso-reference-architecture && rm -rf "$T"
manifest: skills/jeremylongshore/claude-code-plugins-plus-skills/documenso-reference-architecture/SKILL.md
source content

Documenso Reference Architecture

Overview

Production-ready architecture for Documenso document signing integrations. Covers project layout, layered service architecture, webhook processing, and data flow.

Prerequisites

  • Understanding of layered architecture principles
  • Documenso SDK knowledge (see
    documenso-sdk-patterns
    )
  • TypeScript project with Node.js 18+

Recommended Project Structure

my-signing-app/
├── src/
│   ├── documenso/
│   │   ├── client.ts              # Singleton SDK client
│   │   ├── errors.ts              # Custom error classes
│   │   ├── retry.ts               # Retry/backoff logic
│   │   └── types.ts               # Shared types
│   ├── services/
│   │   ├── document-service.ts    # Document CRUD operations
│   │   ├── template-service.ts    # Template-based workflows
│   │   └── signing-service.ts     # Orchestrates signing flows
│   ├── webhooks/
│   │   ├── handler.ts             # Express webhook router
│   │   ├── verify.ts              # Secret verification
│   │   └── processors/
│   │       ├── document-completed.ts
│   │       ├── document-signed.ts
│   │       └── document-rejected.ts
│   ├── api/
│   │   ├── health.ts              # Health check endpoint
│   │   └── routes.ts              # API routes
│   └── config/
│       └── index.ts               # Environment configuration
├── scripts/
│   ├── verify-connection.ts       # Quick health check
│   ├── create-test-doc.ts         # Test document generator
│   └── cleanup-test-docs.ts       # Test data cleanup
├── tests/
│   ├── unit/
│   │   └── document-service.test.ts
│   ├── integration/
│   │   └── document-lifecycle.test.ts
│   └── mocks/
│       └── documenso.ts           # Mock client factory
├── .env.development
├── .env.production
├── docker-compose.yml             # Self-hosted Documenso (dev)
└── package.json

Layer Architecture

┌─────────────────────────────────────────────────────────┐
│  API / Controllers                                       │
│  Routes, request validation, response formatting         │
├─────────────────────────────────────────────────────────┤
│  Service Layer                                           │
│  Business logic, orchestration, authorization            │
│  (document-service, template-service, signing-service)   │
├─────────────────────────────────────────────────────────┤
│  Documenso Client Layer                                  │
│  SDK wrapper, retry, error handling, caching             │
│  (client.ts, retry.ts, errors.ts)                       │
├─────────────────────────────────────────────────────────┤
│  External Services                                       │
│  Documenso API, S3/GCS storage, email, database         │
└─────────────────────────────────────────────────────────┘

Rules:

  • Controllers never call Documenso directly -- always go through services
  • Services never import
    @documenso/sdk-typescript
    directly -- use the client wrapper
  • Webhook processors are isolated -- one file per event type
  • Error handling happens at the client layer, not in controllers

Data Flow

User Request
     │
     ▼
┌──────────┐   POST /api/sign
│   API    │──────────────────────────────┐
│  Router  │                              │
└──────────┘                              ▼
                                   ┌──────────────┐
                                   │   Signing    │
                                   │   Service    │
                                   └──────┬───────┘
                                          │
                    ┌─────────────────────┼─────────────────────┐
                    ▼                     ▼                     ▼
             ┌──────────┐         ┌──────────┐          ┌──────────┐
             │ Template │         │ Document │          │   Your   │
             │ Service  │         │ Service  │          │    DB    │
             └────┬─────┘         └────┬─────┘          └──────────┘
                  │                    │
                  └────────┬───────────┘
                           ▼
                    ┌──────────────┐
                    │  Documenso   │
                    │  Client      │──→ Documenso API
                    │  (singleton) │
                    └──────────────┘

Webhook Flow:
Documenso API ──POST──→ /webhooks/documenso
                             │
                        ┌────▼────┐
                        │ Verify  │──→ Check X-Documenso-Secret
                        │ Secret  │
                        └────┬────┘
                             │
                        ┌────▼────┐
                        │ Router  │──→ Route by event type
                        └────┬────┘
                             │
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
        completed.ts    signed.ts     rejected.ts
        (archive PDF)  (update DB)  (alert sender)

Setup Script

#!/bin/bash
set -euo pipefail

mkdir -p src/{documenso,services,webhooks/processors,api,config}
mkdir -p scripts tests/{unit,integration,mocks}

# Create .env.example
cat > .env.example << 'EOF'
DOCUMENSO_API_KEY=
DOCUMENSO_BASE_URL=https://app.documenso.com/api/v2
DOCUMENSO_WEBHOOK_SECRET=
LOG_LEVEL=info
NODE_ENV=development
EOF

echo "Project scaffolded. Copy .env.example to .env and fill in values."

Key Design Decisions

DecisionRationale
Singleton clientAvoids re-initialization overhead per request
Service layerSeparates business logic from API details
One processor per webhook eventIsolates side effects, easy to test
Mock client for testsFast unit tests without API calls
Template-first approachFewer API calls, consistent field placement

Error Handling

IssueCauseSolution
Circular dependenciesWrong layeringServices import client, never the reverse
Config not loadingWrong env fileVerify
NODE_ENV
matches config loader
Webhook processor crashUnhandled error in processorWrap each processor in try/catch
Test isolationShared client stateCall
resetClient()
in
beforeEach

Resources

Next Steps

For multi-environment setup, see

documenso-multi-env-setup
.