Skillshub documenso-local-dev-loop
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-local-dev-loop" ~/.claude/skills/comeonoliver-skillshub-documenso-local-dev-loop && rm -rf "$T"
manifest:
skills/jeremylongshore/claude-code-plugins-plus-skills/documenso-local-dev-loop/SKILL.mdsource content
Documenso Local Dev Loop
Overview
Configure a fast local development environment for Documenso integrations. Covers project structure, environment configs, self-hosted Documenso via Docker, test utilities, and cleanup scripts.
Prerequisites
- Completed
setupdocumenso-install-auth - Node.js 18+ with TypeScript
- Docker (for self-hosted local Documenso)
Instructions
Step 1: Project Structure
my-signing-app/ ├── src/ │ └── documenso/ │ ├── client.ts # Configured SDK client │ ├── documents.ts # Document operations │ ├── recipients.ts # Recipient management │ └── webhooks.ts # Webhook handlers ├── scripts/ │ ├── verify-connection.ts # Quick health check │ ├── create-test-doc.ts # Generate test documents │ └── cleanup-test-docs.ts # Remove test data ├── tests/ │ └── integration/ │ ├── document.test.ts │ └── template.test.ts ├── .env.development ├── .env.test └── .env.production
Step 2: Environment Configuration
.env.development:
DOCUMENSO_API_KEY=api_dev_xxxxxxxxxxxx DOCUMENSO_BASE_URL=https://stg-app.documenso.com/api/v2 DOCUMENSO_WEBHOOK_SECRET=whsec_dev_xxxxxxxxxxxx LOG_LEVEL=debug
.env.test:
DOCUMENSO_API_KEY=api_test_xxxxxxxxxxxx DOCUMENSO_BASE_URL=https://stg-app.documenso.com/api/v2 DOCUMENSO_WEBHOOK_SECRET=whsec_test_xxxxxxxxxxxx LOG_LEVEL=warn
Step 3: Client Wrapper with Dev Helpers
// src/documenso/client.ts import { Documenso } from "@documenso/sdk-typescript"; let _client: Documenso | null = null; export function getClient(): Documenso { if (!_client) { _client = new Documenso({ apiKey: process.env.DOCUMENSO_API_KEY!, ...(process.env.DOCUMENSO_BASE_URL && { serverURL: process.env.DOCUMENSO_BASE_URL, }), }); } return _client; } // Dev helper: list recent documents for debugging export async function listRecentDocs(limit = 5) { const client = getClient(); const { documents } = await client.documents.findV0({ page: 1, perPage: limit, orderByColumn: "createdAt", orderByDirection: "desc", }); return documents; }
Step 4: Self-Hosted Local Documenso (Docker)
# Pull the official Documenso Docker image docker pull documenso/documenso:latest # Create docker-compose.local.yml
# docker-compose.local.yml services: documenso: image: documenso/documenso:latest ports: - "3000:3000" environment: - NEXTAUTH_URL=http://localhost:3000 - NEXTAUTH_SECRET=local-dev-secret-change-me - NEXT_PRIVATE_ENCRYPTION_KEY=local-encryption-key - NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=local-secondary-key - NEXT_PUBLIC_WEBAPP_URL=http://localhost:3000 - NEXT_PRIVATE_DATABASE_URL=postgresql://documenso:password@db:5432/documenso - NEXT_PRIVATE_DIRECT_DATABASE_URL=postgresql://documenso:password@db:5432/documenso - NEXT_PRIVATE_SMTP_TRANSPORT=smtp-auth - NEXT_PRIVATE_SMTP_HOST=mailhog - NEXT_PRIVATE_SMTP_PORT=1025 depends_on: - db - mailhog db: image: postgres:16-alpine environment: POSTGRES_USER: documenso POSTGRES_PASSWORD: password POSTGRES_DB: documenso volumes: - pgdata:/var/lib/postgresql/data mailhog: image: mailhog/mailhog ports: - "8025:8025" # Web UI for email inspection - "1025:1025" volumes: pgdata:
docker compose -f docker-compose.local.yml up -d # Documenso at http://localhost:3000 # MailHog at http://localhost:8025 (view sent emails)
.env.local (for self-hosted dev):
DOCUMENSO_API_KEY=api_local_xxxxxxxxxxxx DOCUMENSO_BASE_URL=http://localhost:3000/api/v2
Step 5: Quick Verification Script
// scripts/verify-connection.ts import { getClient } from "../src/documenso/client"; async function verify() { const client = getClient(); try { const { documents } = await client.documents.findV0({ page: 1, perPage: 1 }); console.log("Connection OK"); console.log(`Documents accessible: ${documents.length >= 0 ? "yes" : "no"}`); } catch (err: any) { console.error(`Connection FAILED: ${err.message}`); if (err.statusCode === 401) console.error("Check DOCUMENSO_API_KEY"); process.exit(1); } } verify();
Step 6: Test Cleanup Script
// scripts/cleanup-test-docs.ts import { getClient } from "../src/documenso/client"; async function cleanup() { const client = getClient(); const { documents } = await client.documents.findV0({ page: 1, perPage: 100 }); const testDocs = documents.filter((d: any) => d.title.startsWith("[TEST]") || d.title.startsWith("Hello World") ); for (const doc of testDocs) { if (doc.status === "DRAFT") { await client.documents.deleteV0(doc.id); console.log(`Deleted: ${doc.title} (${doc.id})`); } else { console.log(`Skipped (${doc.status}): ${doc.title}`); } } console.log(`Cleaned up ${testDocs.filter((d: any) => d.status === "DRAFT").length} test docs`); } cleanup();
Step 7: Development Scripts (package.json)
{ "scripts": { "dev:verify": "tsx scripts/verify-connection.ts", "dev:test-doc": "tsx scripts/create-test-doc.ts", "dev:cleanup": "tsx scripts/cleanup-test-docs.ts", "dev:local": "docker compose -f docker-compose.local.yml up -d", "dev:local:stop": "docker compose -f docker-compose.local.yml down", "test:integration": "vitest run tests/integration/" } }
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Docker not running | Run |
| Wrong API key for env | Check key matches staging |
| Stale test data | Tests didn't clean up | Run |
| Rate limited in tests | Too many requests | Add between API calls |
| Emails not arriving | SMTP misconfigured | Check MailHog at |
Resources
Next Steps
Apply patterns in
documenso-sdk-patterns for production-ready code structure.