- Architecture overview (Blazor Auto Server+WASM hybrid) - Critical development commands (both API and WebUI must run) - Route structure with render mode requirements - Coordinate system conversions (INCHES in DB) - API architecture quirks and missing endpoints - Status color coding from legacy VB.NET app - Common mistakes to avoid - Configuration locations and migration status
8.5 KiB
EnvelopeGenerator - Agent Guide
Must Read First
COPILOT_CONTEXT.md- Architecture, coordinate systems, migration statusFORM_APPLICATION_CONTEXT.md- Legacy VB.NET features to migrate
Active Architecture (Post-Migration)
Frontend: Blazor Auto (Server+WASM hybrid)
- WebUI (Server):
@rendermode InteractiveServer- PDF viewers requiring DevExpress backend - WebUI.Client (WASM):
@rendermode InteractiveWebAssembly- Login, dashboards, business logic
Backend: EnvelopeGenerator.API (ASP.NET Core 8.0)
Proxy: YARP in WebUI routes /api/* → localhost:8088 (API)
Deprecated Projects - DO NOT USE
EnvelopeGenerator.ReceiverUI- Pure WASM (migrated to WebUI)EnvelopeGenerator.Web- Razor Pages (replaced by WebUI)- VB.NET projects (
Form,Service,BBTests) - Legacy, read-only for reference
Development Commands
Run Both Projects (Required)
# Terminal 1 - API Backend
cd EnvelopeGenerator.API
dotnet run
# Terminal 2 - Blazor Frontend
cd EnvelopeGenerator.WebUI\EnvelopeGenerator.WebUI
dotnet run
Critical: Both must run simultaneously. WebUI proxy forwards /api/* to API.
Build
dotnet build EnvelopeGenerator.sln
Project Boundaries
EnvelopeGenerator.Domain/ # Entities (Envelope, Receiver, Document, etc.)
EnvelopeGenerator.Application/ # MediatR CQRS (Commands, Queries, Handlers)
EnvelopeGenerator.Infrastructure/ # EF Core, SQL executors, repositories
EnvelopeGenerator.API/ # Controllers, endpoints
EnvelopeGenerator.WebUI/ # Server-side Blazor components
├─ Components/Pages/ # @rendermode InteractiveServer
EnvelopeGenerator.WebUI.Client/ # Client-side WASM components
├─ Pages/ # @rendermode InteractiveWebAssembly
├─ Services/ # HTTP API clients
├─ Models/ # DTOs
Route Structure (Critical)
| Route | File Location | Render Mode | Purpose |
|---|---|---|---|
/ |
WebUI.Client/Pages/Index.razor |
WASM | Landing page |
/sender/login |
WebUI.Client/Pages/LoginSenderPage.razor |
WASM | Sender auth |
/sender |
WebUI.Client/Pages/EnvelopeSenderPage.razor |
WASM | Sender dashboard |
/envelope/login/{key} |
WebUI.Client/Pages/LoginReceiverPage.razor |
WASM | Receiver auth |
/envelope/{key} |
WebUI/Components/Pages/EnvelopeReceiverPage.razor |
Server | PDF viewer + signing |
Rule: PDF viewers MUST use @rendermode InteractiveServer (DevExpress backend requirement). Everything else uses WASM.
Coordinate System (CRITICAL)
Database stores INCHES (GdPicture14 native). Origin: top-left, Y-axis down.
Conversions
// Database (INCHES) → PDF Points
float points = inches * 72;
// Database (INCHES) → DevExpress DX
float dx = inches * 100;
// PDF.js Pixels → Database (INCHES)
float inches = (pixelX / canvasWidth) * pageWidthInches;
A4 Page: 8.27" wide × 11.69" tall = 595pt × 842pt
Signature Field Size: 1.77" × 1.96" (FIXED, do not change)
Evidence: See COPILOT_CONTEXT.md lines 158-185, EnvelopeGenerator.Form/frmFieldEditor.vb
API Architecture Quirks
Monolithic Endpoint (Avoid for UI)
POST /api/EnvelopeReceiver - Creates envelope+document+receivers+fields atomically.
- Use case: External API consumers
- Not suitable for: Step-by-step UI workflow (no draft support, no partial updates)
Missing Granular Endpoints (Need to Create)
POST /api/Envelope/draft # Create draft envelope
PUT /api/Envelope/{id} # Update metadata
DELETE /api/Envelope/{id} # Delete with reason
POST /api/Envelope/{id}/document # Upload PDF
POST /api/Envelope/{id}/receivers # Add receiver
POST /api/Envelope/{id}/signature-fields # Place signature field
POST /api/Envelope/{id}/send # Send to receivers
See FORM_APPLICATION_CONTEXT.md for detailed workflow requirements.
Status Color Coding
Form app uses DevExpress CustomDrawCell. WebUI needs CSS:
.envelope-row.status-partly-signed { background-color: #81C784; } /* GREEN_300 */
.envelope-row.status-queued,
.envelope-row.status-sent { background-color: #FFB74D; } /* ORANGE_300 */
.envelope-row.status-completed { background-color: #81C784; }
.envelope-row.status-deleted,
.envelope-row.status-rejected { background-color: #E57373; } /* RED_300 */
Configuration
YARP Proxy (WebUI/yarp.json)
Routes /api/*, /swagger/*, /openapi/*, /scalar/* → https://localhost:8088
PDF.js Settings (WebUI/wwwroot/appsettings.json)
{
"PdfViewerOptions": {
"ThumbnailBaseScale": 0.75,
"ThumbnailEnableHiDPI": true,
"MainCanvasEnableHiDPI": true,
"ZoomStepPercentage": 5
}
}
API Config (API/appsettings.json)
ConnectionStrings:Default- SQL Server DBAllowedOrigins- CORS (includeshttp://localhost:5131,http://localhost:7192)Cache:SignatureCacheExpiration- Signature persistence timeoutPSPDFKitLicenseKey- DEPRECATED (use PDF.js instead)
Migration Status
Complete ✅
- Receiver login/authentication
- PDF viewing with PDF.js (HiDPI, zoom, thumbnails)
- Signature capture (draw/type/image)
- Signature caching (Redis/SQL)
- Sender login
Missing (High Priority) ❌
- Sender dashboard (
/sender) - Empty stub - Envelope editor (
/sender/envelope/{id}) - Signature field placement tool (PDF.js + draggable overlays)
- Granular API endpoints (draft, receivers, fields)
- Master-detail grids for receivers/history
Common Mistakes (DO NOT REPEAT)
| Mistake | Why Wrong |
|---|---|
| Using iText7 in receiver pages | GPL license issue. Use PDF.js overlays. |
| Using PSPDFKit | Removed from architecture. Use PDF.js + DevExpress. |
@rendermode InteractiveWebAssembly on PDF viewers |
DevExpress DxPdfViewer requires server-side rendering. |
| Hardcoded quality in PDF.js | Use appsettings.json PdfViewerOptions. |
| Coordinates in points/pixels for DB | Database uses INCHES. Convert before save. |
BottomMarginBand for signatures |
Repeats on every page. Use DetailBand. |
Testing
No automated tests exist yet.
Manual testing workflow:
- Start API (
dotnet runinEnvelopeGenerator.API) - Start WebUI (
dotnet runinEnvelopeGenerator.WebUI\EnvelopeGenerator.WebUI) - Navigate to
https://localhost:5131(or check console output for port) - Test sender login at
/sender/login - Test receiver flow at
/envelope/login/{envelopeKey}
Database
SQL Server (DD_ECM)
- Connection string in
API/appsettings.json - EF Core migrations NOT used (manual SQL scripts)
- Stored procedures:
PRSIG_*prefix
Key Tables:
TBSIG_ENVELOPE- Envelope metadataTBSIG_ENVELOPE_RECEIVER- Receiver assignmentsTBSIG_DOC_RECEIVER_ELEMENT- Signature fields (X, Y in INCHES)TBSIG_RECEIVER- Receiver registryTBSIG_DOCUMENT- PDF binary dataTBSIG_ENVELOPE_HISTORY- Audit trail
DevExpress
License: Commercial (v25.2.3) Components Used:
DxGrid- Master-detail gridsDxPdfViewer- Server-side PDF renderingDxPopup- Modal dialogsDxToolbar- Action barsDxFormLayout- Forms
Theme: Blazing Berry (default)
JavaScript Interop
PDF Viewer: wwwroot/js/pdf-viewer.js
window.pdfViewer = {
initialize(canvasId, pdfDataUrl, dotNetRef),
renderPage(num),
renderSignatureButtons(signatures, pageNum, dotNetRef),
applySignature(signatureId, dataUrl, fullName, position, place),
zoomIn(), zoomOut(), dispose()
}
Signature Pad: wwwroot/js/receiver-signature.js
window.receiverSignature = {
initializeDrawPad(canvasId, dotNetRef),
getSignatureDataUrl(canvasId),
clearPad(canvasId)
}
Multi-Envelope Support
Receivers can login to multiple envelopes simultaneously via per-envelope cookies:
AuthTokenSignFLOWReceiver.{envelopeKey}
Each envelope maintains independent authentication state.
External Dependencies
CDN:
- PDF.js 3.11.174:
https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js
NuGet (WebUI.Client):
DevExpress.Blazor.*25.2.3SkiaSharp.*3.119.1 (WASM rendering)
External Services:
- LDAP/AD authentication (optional)
- GTX Messaging (SMS 2FA)
- Email dispatcher (signFlow)
Environment Variables
None required. All config in appsettings.json.
Local dev ports:
- API:
https://localhost:8088 - WebUI:
https://localhost:5131orhttp://localhost:7192