Skip to main content ホーム クリエイター dicklesworthstone pi_agent_rust documenso-migration-deep-dive
documenso-migration-deep-dive Execute comprehensive Documenso migration strategies for platform switches.
Use when migrating from other signing platforms, re-platforming to Documenso,
or performing major infrastructure changes.
Trigger with phrases like "migrate to documenso", "documenso migration",
"switch to documenso", "documenso replatform", "replace docusign".
インストールへ移動 Skills Marketplace コミュニティが作成したAIスキルを発見・探索
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/Dicklesworthstone/pi_agent_rust --skill documenso-migration-deep-diveコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Zipをダウンロード ダウンロード中... name documenso-migration-deep-dive description Execute comprehensive Documenso migration strategies for platform switches.
Use when migrating from other signing platforms, re-platforming to Documenso,
or performing major infrastructure changes.
Trigger with phrases like "migrate to documenso", "documenso migration",
"switch to documenso", "documenso replatform", "replace docusign".
allowed-tools Read, Write, Edit, Bash(npm:*), Bash(node:*) version 1.0.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io>
Documenso Migration Deep Dive
Overview
Comprehensive guide for migrating to Documenso from other e-signature platforms or implementing major architectural changes.
Prerequisites
Current system documentation
Documenso account configured
Feature flag infrastructure
Rollback strategy tested
Migration Types
Migration Type Complexity Duration Risk
Fresh start Low Days Low DocuSign migration Medium Weeks Medium HelloSign migration Medium Weeks Medium Adobe Sign migration High Months High Self-hosted migration Medium Weeks Medium
Migration Strategy: Strangler Fig Pattern Phase 1: Parallel Systems
┌─────────────────────────────────────────────────────────┐
│ Your Application │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Legacy │ 100% │ Documenso │ 0% │
│ │ (DocuSign) │ ◀────── │ (New) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
Phase 2: Traffic Shifting
┌─────────────────────────────────────────────────────────┐
│ Your Application │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Legacy │ 50% │ Documenso │ 50% │
│ │ (DocuSign) │ ◀─────▶ │ (New) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
Phase 3: Complete Migration
┌─────────────────────────────────────────────────────────┐
│ Your Application │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Legacy │ 0% │ Documenso │ 100% │
│ │ (Retired) │ ──────▶ │ (Active) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
Pre-Migration Assessment
Step 1: Document Current State
interface MigrationAssessment {
documentsTotal : number ;
documentsActive : number ;
templatesTotal : number ;
integrationPoints : string [];
customizations : string [];
dependencies : string [];
estimatedMigrationHours : number ;
}
async function assessCurrentSystem ( ): Promise <MigrationAssessment > {
const codebaseAnalysis = await analyzeCodebase ();
const documentStats = await getCurrentDocumentStats ();
const integrations = await findIntegrationPoints ();
return {
documentsTotal : documentStats.total ,
documentsActive : documentStats.active ,
templatesTotal : documentStats.templates ,
integrationPoints : integrations,
customizations : codebaseAnalysis.customizations ,
dependencies : codebaseAnalysis.dependencies ,
estimatedMigrationHours : calculateEstimate (codebaseAnalysis),
};
}
async function analyzeCodebase ( ) {
return {
customizations : [
"Custom email templates" ,
"Webhook processing" ,
"PDF preprocessing" ,
],
dependencies : ["@docusign/esign" , "docusign-esign" ],
};
}
Step 2: Feature Mapping
interface FeatureMapping {
existingFeature : string ;
documensoEquivalent : string ;
migrationNotes : string ;
complexity : "low" | "medium" | "high" ;
}
const FEATURE_MAPPING : FeatureMapping [] = [
{
existingFeature : "DocuSign envelope" ,
documensoEquivalent : "Documenso document/envelope" ,
migrationNotes : "Direct mapping, similar concept" ,
complexity : "low" ,
},
{
existingFeature : "DocuSign template" ,
documensoEquivalent : "Documenso template" ,
migrationNotes : "Recreate templates, export/import not supported" ,
complexity : "medium" ,
},
{
existingFeature : "PowerForms" ,
documensoEquivalent : "Direct templates" ,
migrationNotes : "Use Documenso direct template links" ,
complexity : "low" ,
},
{
existingFeature : "Bulk send" ,
documensoEquivalent : "Batch API calls" ,
migrationNotes : "Implement batch processing with queue" ,
complexity : "medium" ,
},
{
existingFeature : "Connect (webhooks)" ,
documensoEquivalent : "Documenso webhooks" ,
migrationNotes : "Similar events, different payload structure" ,
complexity : "medium" ,
},
{
existingFeature : "Embedded signing" ,
documensoEquivalent : "Embed components" ,
migrationNotes : "Use @documenso/embed-react or similar" ,
complexity : "low" ,
},
];
Implementation Plan
Phase 1: Setup (Week 1-2)
{
"dependencies" : {
"docusign-esign" : "^6.0.0" ,
"@documenso/sdk-typescript" : "^0.3.0"
}
}
export interface SigningService {
createDocument (input : CreateDocumentInput ): Promise <DocumentResult >;
addRecipient (docId : string , recipient : RecipientInput ): Promise <string >;
addField (docId : string , field : FieldInput ): Promise <string >;
sendDocument (docId : string ): Promise <void >;
getDocumentStatus (docId : string ): Promise <DocumentStatus >;
downloadDocument (docId : string ): Promise <Buffer >;
}
export class DocuSignAdapter implements SigningService {
}
export class DocumensoAdapter implements SigningService {
}
Phase 2: Adapter Implementation (Week 3-4)
import { Documenso } from "@documenso/sdk-typescript" ;
import { SigningService , CreateDocumentInput } from "../interface" ;
export class DocumensoAdapter implements SigningService {
private client : Documenso ;
constructor (apiKey : string , baseUrl ?: string ) {
this .client = new Documenso ({
apiKey,
serverURL : baseUrl,
});
}
async createDocument (input : CreateDocumentInput ): Promise <DocumentResult > {
const doc = await this .client .documents .createV0 ({
title : input.title ,
file : input.file ,
});
return {
id : doc.documentId !,
status : "DRAFT" ,
provider : "documenso" ,
};
}
async addRecipient (
docId : string ,
recipient : RecipientInput
): Promise <string > {
const result = await this .client .documentsRecipients .createV0 ({
documentId : docId,
email : recipient.email ,
name : recipient.name ,
role : this .mapRole (recipient.role ),
});
return result.recipientId !;
}
async addField (docId : string , field : FieldInput ): Promise <string > {
const result = await this .client .documentsFields .createV0 ({
documentId : docId,
recipientId : field.recipientId ,
type : this .mapFieldType (field.type ),
page : field.page ,
positionX : field.x ,
positionY : field.y ,
width : field.width ,
height : field.height ,
});
return result.fieldId !;
}
async sendDocument (docId : string ): Promise <void > {
await this .client .documents .sendV0 ({ documentId : docId });
}
async getDocumentStatus (docId : string ): Promise <DocumentStatus > {
const doc = await this .client .documents .getV0 ({ documentId : docId });
return {
id : doc.id !,
status : this .mapStatus (doc.status !),
recipients : doc.recipients ?.map ((r ) => ({
email : r.email !,
status : this .mapRecipientStatus (r.signingStatus !),
})) ?? [],
};
}
async downloadDocument (docId : string ): Promise <Buffer > {
const result = await this .client .documents .downloadV0 ({
documentId : docId,
});
return Buffer .from (result as ArrayBuffer );
}
private mapRole (role : string ): string {
const mapping : Record <string , string > = {
signer : "SIGNER" ,
cc : "CC" ,
viewer : "VIEWER" ,
approver : "APPROVER" ,
};
return mapping[role.toLowerCase ()] ?? "SIGNER" ;
}
private mapFieldType (type : string ): string {
const mapping : Record <string , string > = {
signHere : "SIGNATURE" ,
initialHere : "INITIALS" ,
dateSigned : "DATE" ,
fullName : "NAME" ,
email : "EMAIL" ,
text : "TEXT" ,
checkbox : "CHECKBOX" ,
};
return mapping[type ] ?? "TEXT" ;
}
private mapStatus (status : string ): string {
const mapping : Record <string , string > = {
DRAFT : "draft" ,
PENDING : "sent" ,
COMPLETED : "completed" ,
CANCELLED : "voided" ,
REJECTED : "declined" ,
};
return mapping[status] ?? status.toLowerCase ();
}
private mapRecipientStatus (status : string ): string {
const mapping : Record <string , string > = {
NOT_SIGNED : "pending" ,
SIGNED : "completed" ,
REJECTED : "declined" ,
};
return mapping[status] ?? "pending" ;
}
}
Phase 3: Service Factory with Feature Flags (Week 5)
import { SigningService } from "./interface" ;
import { DocuSignAdapter } from "./adapters/docusign" ;
import { DocumensoAdapter } from "./adapters/documenso" ;
interface FeatureFlags {
isEnabled (flag : string ): Promise <boolean >;
getPercentage (flag : string ): Promise <number >;
}
export class SigningServiceFactory {
constructor (
private featureFlags : FeatureFlags ,
private config : {
docusign: { apiKey: string ; accountId: string };
documenso: { apiKey: string ; baseUrl?: string };
}
) {}
async getService (context ?: { userId ?: string }): Promise <SigningService > {
const documensoEnabled = await this .featureFlags .isEnabled ("documenso_full" );
if (documensoEnabled) {
return new DocumensoAdapter (
this .config .documenso .apiKey ,
this .config .documenso .baseUrl
);
}
const percentage = await this .featureFlags .getPercentage ("documenso_rollout" );
if (Math .random () * 100 < percentage) {
return new DocumensoAdapter (
this .config .documenso .apiKey ,
this .config .documenso .baseUrl
);
}
return new DocuSignAdapter (
this .config .docusign .apiKey ,
this .config .docusign .accountId
);
}
}
Phase 4: Data Migration (Week 6-7)
interface TemplateMigrationPlan {
legacyTemplateId : string ;
name : string ;
description : string ;
recipientRoles : string [];
fields : FieldDefinition [];
recreated : boolean ;
documensoTemplateId ?: string ;
}
async function generateTemplateMigrationPlan ( ): Promise <TemplateMigrationPlan []> {
const legacyTemplates = await getLegacyTemplates ();
const plans : TemplateMigrationPlan [] = [];
for (const template of legacyTemplates) {
plans.push ({
legacyTemplateId : template.id ,
name : template.name ,
description : template.description ,
recipientRoles : template.recipients .map ((r ) => r.roleName ),
fields : template.fields .map ((f ) => ({
type : f.type ,
page : f.pageNumber ,
x : f.xPosition ,
y : f.yPosition ,
width : f.width ,
height : f.height ,
recipientRole : f.recipientRole ,
})),
recreated : false ,
});
}
await fs.writeFile (
"migration/template-plan.json" ,
JSON .stringify (plans, null , 2 )
);
return plans;
}
interface DocumentMapping {
legacyId : string ;
documensoId ?: string ;
title : string ;
status : string ;
completedAt ?: string ;
signedDocumentUrl ?: string ;
}
async function createDocumentMapping ( ): Promise <void > {
await db.execute (`
CREATE TABLE IF NOT EXISTS document_mapping (
id SERIAL PRIMARY KEY,
legacy_id VARCHAR(255),
documenso_id VARCHAR(255),
title VARCHAR(500),
status VARCHAR(50),
completed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
)
` );
}
Phase 5: Webhook Migration (Week 8)
import express from "express" ;
const router = express.Router ();
router.post ("/webhooks/documenso" , (req, res ) => {
const { event, payload } = req.body ;
const normalizedEvent = normalizeDocumensoEvent (event, payload);
processSigningEvent (normalizedEvent);
res.json ({ received : true });
});
router.post ("/webhooks/docusign" , (req, res ) => {
const { event, data } = req.body ;
const normalizedEvent = normalizeDocuSignEvent (event, data);
processSigningEvent (normalizedEvent);
res.json ({ status : "ok" });
});
interface NormalizedSigningEvent {
eventType : "created" | "sent" | "signed" | "completed" | "declined" ;
documentId : string ;
provider : "documenso" | "docusign" ;
signerEmail ?: string ;
timestamp : Date ;
}
async function processSigningEvent (event : NormalizedSigningEvent ): Promise <void > {
console .log (`Processing ${event.provider} event: ${event.eventType} ` );
switch (event.eventType ) {
case "completed" :
await handleDocumentCompleted (event);
break ;
case "declined" :
await handleDocumentDeclined (event);
break ;
}
}
Phase 6: Rollout & Monitoring (Week 9-10)
const ROLLOUT_SCHEDULE = [
{ day : 1 , percentage : 5 , description : "Internal users" },
{ day : 3 , percentage : 10 , description : "Early adopters" },
{ day : 7 , percentage : 25 , description : "Quarter traffic" },
{ day : 14 , percentage : 50 , description : "Half traffic" },
{ day : 21 , percentage : 75 , description : "Most traffic" },
{ day : 28 , percentage : 100 , description : "Full migration" },
];
interface MigrationMetrics {
documentsCreated : { legacy : number ; documenso : number };
errorRate : { legacy : number ; documenso : number };
latencyP95 : { legacy : number ; documenso : number };
completionRate : { legacy : number ; documenso : number };
}
async function checkMigrationHealth ( ): Promise <{
healthy : boolean ;
metrics : MigrationMetrics ;
}> {
const metrics = await collectMetrics ();
const errorDiff = metrics.errorRate .documenso - metrics.errorRate .legacy ;
const healthy = errorDiff < 0.02 ;
return { healthy, metrics };
}
Rollback Procedure #!/bin/bash
echo "Rolling back Documenso migration..."
curl -X POST $FEATURE_FLAG_API /flags \
-d '{"flag": "documenso_rollout", "value": 0}'
sleep 10
curl -s https://your-app.com/health | jq '.signing.provider'
echo "Rollback complete. All traffic now using legacy provider."
Output
Migration assessment complete
Unified interface implemented
Gradual rollout configured
Rollback procedure tested
Error Handling Migration Issue Cause Solution Field mapping failed Different coordinates Adjust position calculation Webhook format Different payload Normalize events Template missing Not recreated Create in Documenso High error rate Integration bug Pause rollout, investigate
Resources
Congratulations! You have completed the Documenso Skill Pack. Review other skills as needed for ongoing operations.