> documenso-multi-env-setup
Configure Documenso across multiple environments (dev, staging, production). Use when setting up environment-specific configurations, managing API keys, or implementing environment promotion workflows. Trigger with phrases like "documenso environments", "documenso staging", "documenso dev setup", "multi-environment documenso".
curl "https://skillshub.wtf/jeremylongshore/claude-code-plugins-plus-skills/documenso-multi-env-setup?format=md"Documenso Multi-Environment Setup
Overview
Configure Documenso across development, staging, and production with environment isolation, secret management, and promotion workflows. Documenso cloud offers a staging environment at stg-app.documenso.com; self-hosted users run separate instances.
Prerequisites
- Documenso accounts or instances for each environment
- Secret management solution (Vault, AWS Secrets Manager, or
.envfiles) - Completed
documenso-install-authsetup
Environment Architecture
┌─────────────────────────────────────────────────────────────┐
│ Development │
│ API: stg-app.documenso.com (or localhost:3000 self-hosted) │
│ Key: DOCUMENSO_API_KEY=api_dev_xxx │
│ Webhooks: ngrok tunnel │
├─────────────────────────────────────────────────────────────┤
│ Staging │
│ API: stg-app.documenso.com │
│ Key: DOCUMENSO_API_KEY=api_stg_xxx │
│ Webhooks: staging.yourapp.com/webhooks/documenso │
├─────────────────────────────────────────────────────────────┤
│ Production │
│ API: app.documenso.com (or sign.yourcompany.com) │
│ Key: DOCUMENSO_API_KEY=api_prod_xxx │
│ Webhooks: api.yourapp.com/webhooks/documenso │
└─────────────────────────────────────────────────────────────┘
Instructions
Step 1: Environment Configuration Files
# .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
NODE_ENV=development
# .env.staging
DOCUMENSO_API_KEY=api_stg_xxxxxxxxxxxx
DOCUMENSO_BASE_URL=https://stg-app.documenso.com/api/v2
DOCUMENSO_WEBHOOK_SECRET=whsec_stg_xxxxxxxxxxxx
LOG_LEVEL=info
NODE_ENV=staging
# .env.production
DOCUMENSO_API_KEY=api_prod_xxxxxxxxxxxx
DOCUMENSO_BASE_URL=https://app.documenso.com/api/v2
DOCUMENSO_WEBHOOK_SECRET=whsec_prod_xxxxxxxxxxxx
LOG_LEVEL=warn
NODE_ENV=production
Step 2: Environment-Aware Client Factory
// src/documenso/factory.ts
import { Documenso } from "@documenso/sdk-typescript";
interface EnvConfig {
apiKey: string;
baseUrl: string;
webhookSecret: string;
}
function getConfig(): EnvConfig {
const apiKey = process.env.DOCUMENSO_API_KEY;
if (!apiKey) throw new Error("DOCUMENSO_API_KEY required");
return {
apiKey,
baseUrl: process.env.DOCUMENSO_BASE_URL ?? "https://app.documenso.com/api/v2",
webhookSecret: process.env.DOCUMENSO_WEBHOOK_SECRET ?? "",
};
}
let client: Documenso | null = null;
export function getClient(): Documenso {
if (!client) {
const config = getConfig();
client = new Documenso({
apiKey: config.apiKey,
serverURL: config.baseUrl,
});
}
return client;
}
export function getWebhookSecret(): string {
return getConfig().webhookSecret;
}
// Reset for testing
export function resetClient(): void {
client = null;
}
Step 3: Environment Guards
// src/guards.ts
function requireProduction() {
if (process.env.NODE_ENV !== "production") {
throw new Error("This operation requires production environment");
}
}
function blockProduction(operation: string) {
if (process.env.NODE_ENV === "production") {
throw new Error(`${operation} is blocked in production`);
}
}
// Usage
async function deleteAllDrafts(client: Documenso) {
blockProduction("deleteAllDrafts"); // Safety guard
// ... only runs in dev/staging
}
async function sendBulkContracts(client: Documenso) {
requireProduction(); // Only send real contracts in prod
// ...
}
Step 4: Mock Client for Development
// src/documenso/mock.ts
import { vi } from "vitest";
export function createMockClient() {
let docCounter = 0;
return {
documents: {
createV0: vi.fn().mockImplementation(async ({ title }) => ({
documentId: ++docCounter,
title,
status: "DRAFT",
})),
setFileV0: vi.fn().mockResolvedValue(undefined),
findV0: vi.fn().mockResolvedValue({ documents: [] }),
getV0: vi.fn().mockResolvedValue({ status: "DRAFT", recipients: [] }),
sendV0: vi.fn().mockResolvedValue(undefined),
deleteV0: vi.fn().mockResolvedValue(undefined),
},
documentsRecipients: {
createV0: vi.fn().mockResolvedValue({ recipientId: 100 }),
},
documentsFields: {
createV0: vi.fn().mockResolvedValue({ fieldId: 200 }),
},
};
}
Step 5: Template Promotion Between Environments
// scripts/promote-template.ts
// Templates can't be copied via API — recreate them per environment
// Keep template configuration in code for consistency
interface TemplateConfig {
title: string;
recipients: Array<{ role: string; placeholder: string }>;
fields: Array<{
recipientIndex: number;
type: string;
pageNumber: number;
pageX: number;
pageY: number;
pageWidth: number;
pageHeight: number;
}>;
}
// Template definitions versioned in git
const SERVICE_AGREEMENT: TemplateConfig = {
title: "Service Agreement Template v2",
recipients: [
{ role: "SIGNER", placeholder: "Client" },
{ role: "APPROVER", placeholder: "Legal" },
],
fields: [
{ recipientIndex: 0, type: "SIGNATURE", pageNumber: 3, pageX: 10, pageY: 80, pageWidth: 30, pageHeight: 5 },
{ recipientIndex: 0, type: "DATE", pageNumber: 3, pageX: 60, pageY: 80, pageWidth: 20, pageHeight: 3 },
{ recipientIndex: 1, type: "SIGNATURE", pageNumber: 3, pageX: 10, pageY: 90, pageWidth: 30, pageHeight: 5 },
],
};
// Apply to any environment by running: ENV=staging tsx scripts/promote-template.ts
Environment Checklist
| Check | Dev | Staging | Production |
|---|---|---|---|
| Separate API key | Yes | Yes | Yes |
| Debug logging | On | On | Off |
| Webhook endpoint | ngrok | staging URL | production URL |
| Secret manager | .env file | .env file | Vault/AWS SM |
| Mock mode available | Yes | No | No |
| Cleanup scripts enabled | Yes | Yes | No |
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Wrong environment data | Missing NODE_ENV | Set explicitly in each environment |
| Key mismatch | Using dev key in prod | Verify env var names per environment |
| Webhook not received | Wrong URL configured | Update webhook URL in each Documenso environment |
| Mock not working | Wrong client injected | Check factory returns mock in test env |
Resources
Next Steps
For monitoring setup, see documenso-observability.
> related_skills --same-repo
> fathom-cost-tuning
Optimize Fathom API usage and plan selection. Trigger with phrases like "fathom cost", "fathom pricing", "fathom plan".
> fathom-core-workflow-b
Sync Fathom meeting data to CRM and build automated follow-up workflows. Use when integrating Fathom with Salesforce, HubSpot, or custom CRMs, or creating automated post-meeting email summaries. Trigger with phrases like "fathom crm sync", "fathom salesforce", "fathom follow-up", "fathom post-meeting workflow".
> fathom-core-workflow-a
Build a meeting analytics pipeline with Fathom transcripts and summaries. Use when extracting insights from meetings, building CRM sync, or creating automated meeting follow-up workflows. Trigger with phrases like "fathom analytics", "fathom meeting pipeline", "fathom transcript analysis", "fathom action items sync".
> fathom-common-errors
Diagnose and fix Fathom API errors including auth failures and missing data. Use when API calls fail, transcripts are empty, or webhooks are not firing. Trigger with phrases like "fathom error", "fathom not working", "fathom api failure", "fix fathom".