# Website Implementation Guide for Embedded Documenso Signing

## Task Summary

Implement embedded Documenso signing on the Port Nimara website to provide a seamless, branded signing experience for Expression of Interest (EOI) documents.

## Context

The Port Nimara client portal (separate repository) generates EOI documents via a self-hosted Documenso instance and now creates embedded signing URLs that should be handled by the main website at `portnimara.com`.

## Technical Specifications

### Website Stack
- **Framework**: Nuxt 3 (v3.15.4) with Vue 3
- **Styling**: Tailwind CSS
- **TypeScript**: Enabled
- **Package to Install**: `@documenso/embed-vue`

### Documenso Configuration
- **Host**: `https://signatures.portnimara.dev`
- **Self-hosted community edition** (full embedding features available)
- **Authentication**: Handled via tokens (no API keys needed on website)

### Brand Assets
- **Logos**: `/images/logo-full.png`, `/images/logo-no-text.png`, `/images/logo-no-text-white.png`
- **Primary Color**: `#0056b3`
- **Background**: `#ffffff`, `#f8f9fa`
- **Fonts**: Custom fonts in `/public/fonts/` (Bill Corporate, Garamond, Runalto)

## URL Structure to Implement

### Route Pattern
```
/sign/[type]/[token]
```

### URL Examples
```
Client signing: https://portnimara.com/sign/client/ABC123
CC approval: https://portnimara.com/sign/cc/DEF456
Developer signing: https://portnimara.com/sign/developer/GHI789
```

### Route Parameters
- **type**: `'client' | 'cc' | 'developer'`
- **token**: Alphanumeric string from Documenso (e.g., `ABC123`, `mK9N2pL5vX8`)

## Required Implementation

### 1. Install Dependencies

```bash
npm install @documenso/embed-vue
```

### 2. Create Main Signing Page

**File**: `pages/sign/[type]/[token].vue`

**Key Requirements**:
- Validate route parameters (type and token)
- Extract token and signer type from route
- Display appropriate messaging per signer type
- Embed Documenso signing interface
- Handle successful signing with redirect
- Apply Port Nimara branding throughout

**Signer Type Messages**:
```javascript
const signerMessages = {
  client: {
    title: 'Sign Your Expression of Interest',
    subtitle: 'Please review and sign your Port Nimara berth EOI'
  },
  cc: {
    title: 'Approve Expression of Interest',
    subtitle: 'Please review and approve this Port Nimara berth EOI'
  },
  developer: {
    title: 'Review and Sign Expression of Interest',
    subtitle: 'Please review and sign this Port Nimara berth EOI'
  }
};
```

**Embed Configuration**:
```javascript
// Use these exact values
const documensoHost = 'https://signatures.portnimara.dev';

// CSS variables for brand consistency
const cssVars = {
  primary: '#0056b3',
  primaryForeground: '#ffffff',
  background: '#ffffff',
  foreground: '#1a1a1a',
  secondary: '#f8f9fa',
  secondaryForeground: '#1a1a1a',
  accent: '#e9ecef',
  accentForeground: '#1a1a1a',
  destructive: '#dc3545',
  destructiveForeground: '#ffffff',
  border: '#dee2e6',
  input: '#ffffff',
  ring: '#0056b3',
  radius: '0.5rem'
};
```

### 3. Create Success Page

**File**: `pages/sign/success.vue`

**Requirements**:
- Thank you message
- Confirmation that document was signed
- Link back to main Port Nimara website
- Professional, clean design

### 4. Create Error Page

**File**: `pages/sign/error.vue`

**Requirements**:
- Handle invalid/expired tokens
- Provide contact information
- Link to support or main website

### 5. Add Environment Configuration

Add to your `.env` file:
```env
WEBHOOK_SECRET_SIGNING=96BQQRiKkTIN2w0rHbqo7yHggV/sT8702HtHih3uNSY=
```

## Implementation Template

### Main Signing Page Structure

```vue
<template>
  <div class="min-h-screen bg-gray-50">
    <!-- Header with Port Nimara branding -->
    <header class="bg-white shadow-sm border-b">
      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
        <div class="flex items-center justify-between">
          <img src="/images/logo-full.png" alt="Port Nimara" class="h-12" />
          <div class="text-right">
            <h1 class="text-2xl font-bold text-gray-900">{{ pageTitle }}</h1>
            <p class="text-sm text-gray-600">{{ pageSubtitle }}</p>
          </div>
        </div>
      </div>
    </header>

    <!-- Main signing interface -->
    <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
      <div class="bg-white rounded-lg shadow-lg overflow-hidden">
        <!-- Loading state -->
        <div v-if="loading" class="flex items-center justify-center h-96">
          <div class="text-center">
            <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
            <p class="mt-4 text-gray-600">Loading document...</p>
          </div>
        </div>
        
        <!-- Embedded Documenso interface -->
        <EmbedSignDocument
          v-else
          :token="token"
          :host="documensoHost"
          :on-document-signed="handleDocumentSigned"
          :on-document-viewed="handleDocumentViewed"
          :dark-mode-disabled="false"
          class="w-full h-[800px]"
          :css-vars="cssVars"
        />
      </div>
    </main>
  </div>
</template>

<script setup>
import { EmbedSignDocument } from '@documenso/embed-vue';
// ... implementation details in full guide
</script>
```

## Validation Requirements

### Route Parameter Validation
```javascript
// Validate signer type
const validSignerTypes = ['client', 'cc', 'developer'];
if (!validSignerTypes.includes(signerType.value)) {
  router.push('/sign/error');
}

// Validate token format (basic)
const tokenPattern = /^[a-zA-Z0-9_-]+$/;
if (!tokenPattern.test(token.value)) {
  router.push('/sign/error');
}
```

## Event Handling

### Document Signed Handler
```javascript
const handleDocumentSigned = async () => {
  console.log('Document signed successfully');
  
  // Optional: Webhook notification (Phase 2)
  // [Webhook code - initially commented out]
  
  // Always redirect to success
  router.push('/sign/success');
};
```

### Document Viewed Handler
```javascript
const handleDocumentViewed = () => {
  console.log('Document viewed:', { token: token.value, type: signerType.value });
  // Optional: Analytics tracking
};
```

## Mobile Responsiveness

Ensure the implementation works well on mobile devices:

```css
/* Example responsive adjustments */
@media (max-width: 768px) {
  .signing-header h1 {
    font-size: 1.25rem;
  }
  
  .documenso-embed {
    height: 600px; /* Reduced height for mobile */
  }
}
```

## Testing Approach

### 1. Manual Testing
Once implemented, you can test with these example URLs:
- `http://localhost:3000/sign/client/test123`
- `http://localhost:3000/sign/cc/test456`
- `http://localhost:3000/sign/developer/test789`

### 2. Real Token Testing
After the client portal generates a real EOI, you'll receive actual tokens to test with.

## CORS Requirements

The Documenso instance needs CORS headers to allow embedding. This is handled manually via nginx configuration on the server.

**Expected CORS headers from `signatures.portnimara.dev`**:
```
Access-Control-Allow-Origin: https://portnimara.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Credentials: true
```

## Error Handling

### Common Scenarios
1. **Invalid token**: Redirect to error page
2. **Invalid signer type**: Redirect to error page
3. **Expired token**: Documenso will handle this within the embed
4. **Network issues**: Show loading state, let Documenso handle retries

## Success Criteria

✅ **Functionality**:
- Signing interface loads correctly
- Different messaging for each signer type
- Successful signing redirects to success page
- Invalid URLs redirect to error page

✅ **User Experience**:
- Port Nimara branding throughout
- Mobile responsive design
- Fast loading times
- Clear error messages

✅ **Technical**:
- Clean URL structure
- Proper error handling
- Console logging for debugging
- Ready for webhook integration

## Webhook Integration (Phase 2)

*Initially implement with webhook code commented out*

```javascript
// Future webhook endpoint: 
// https://client-portal.portnimara.com/api/webhook/document-signed

const notifyPortal = async () => {
  try {
    await $fetch('https://client-portal.portnimara.com/api/webhook/document-signed', {
      method: 'POST',
      headers: {
        'x-webhook-secret': process.env.WEBHOOK_SECRET_SIGNING
      },
      body: {
        token: token.value,
        signerType: signerType.value,
        signedAt: new Date().toISOString()
      }
    });
  } catch (error) {
    console.error('Webhook failed:', error);
    // Don't block user flow
  }
};
```

## Questions & Support

If you encounter any issues during implementation:

1. **CORS errors**: The server-side CORS configuration may need adjustment
2. **Token format issues**: Check that tokens are being extracted correctly
3. **Embedding not loading**: Verify the Documenso host URL and package installation
4. **Styling issues**: Refer to the CSS variables provided for brand consistency

## Next Steps After Implementation

1. **Test with real tokens** from generated EOIs
2. **Verify mobile experience** on actual devices
3. **Coordinate with client portal** for email template updates
4. **Monitor for any CORS issues** in production
5. **Prepare for webhook integration** in Phase 2

---

*This guide provides everything needed to implement embedded signing on the Port Nimara website. The client portal changes are already complete and ready to generate the embedded URLs this implementation will handle.*
