Set up local development environment and testing workflow for Documenso. Use when configuring dev environment, setting up test workflows, or establishing rapid iteration patterns with Documenso. Trigger with phrases like "documenso local dev", "documenso development", "test documenso locally", "documenso dev environment".
80
77%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advisory
Suggest reviewing before use
Optimize this skill with Tessl
npx tessl skill review --optimize ./plugins/saas-packs/documenso-pack/skills/documenso-local-dev-loop/SKILL.mdConfigure a fast local development environment for Documenso integrations. Covers project structure, environment configs, self-hosted Documenso via Docker, test utilities, and cleanup scripts.
documenso-install-auth setupmy-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.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// 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;
}# 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// 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();// 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();{
"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/"
}
}| Issue | Cause | Solution |
|---|---|---|
ECONNREFUSED localhost:3000 | Docker not running | Run docker compose up -d |
401 on staging | Wrong API key for env | Check .env.development key matches staging |
| Stale test data | Tests didn't clean up | Run npm run dev:cleanup |
| Rate limited in tests | Too many requests | Add await delay(500) between API calls |
| Emails not arriving | SMTP misconfigured | Check MailHog at localhost:8025 |
Apply patterns in documenso-sdk-patterns for production-ready code structure.
3e83543
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.