# Landing Page Generator - Implementation Guide

## Overview

The **Compliant Landing Page Generator** creates beautiful, TCPA-compliant landing pages for A2P SMS campaigns. Each client gets three professionally designed pages:

1. **Opt-In Page** - SMS consent form
2. **Privacy Policy** - Auto-generated from business info
3. **Terms of Service** - Complete TCPA-compliant terms

## Installation

First, install the required dependency:

```bash
npm install handlebars
# or
yarn add handlebars
```

## File Structure

```
src/pages/
├── templates.ts        # Handlebars template strings
├── generator.ts        # Page generation logic
├── deployer.ts         # Local and Vercel deployment
├── index.ts           # Public exports
└── IMPLEMENTATION.md  # This file

landing-template/
├── opt-in.hbs         # Raw opt-in template
├── privacy-policy.hbs # Raw privacy policy template
├── terms.hbs          # Raw terms template
└── README.md          # Template documentation
```

## Quick Start

```typescript
import { 
  generateLandingPages, 
  createLandingPageConfig,
  deployLocal 
} from './pages';

// 1. Create config from business and campaign data
const config = createLandingPageConfig(
  business,
  campaign,
  'support@business.com',
  '+15551234567',
  'https://comply.yourdomain.com',
  {
    brandColor: '#3B82F6',
    messageFrequency: 'up to 5 messages per week'
  }
);

// 2. Generate the three HTML pages
const pages = generateLandingPages(config, campaign, business);

// 3. Deploy (local or Vercel)
const result = await deployLocal(pages, {
  publicDir: './public',
  baseUrl: 'https://comply.yourdomain.com'
});

// 4. Use the URLs
console.log('Opt-in:', result.optInUrl);
console.log('Privacy:', result.privacyPolicyUrl);
console.log('Terms:', result.termsUrl);
```

## Integration with A2P Pipeline

### Step 1: Generate Pages During Brand Submission

```typescript
// In your brand submission flow
import { generateLandingPages, deployLocal } from './pages';

async function submitBrand(input: RegistrationInput) {
  // Generate landing pages
  const config = createLandingPageConfig(
    input.business,
    input.campaign,
    input.authorizedRep.email,
    input.authorizedRep.phoneNumber,
    process.env.BASE_URL!
  );
  
  const pages = generateLandingPages(config, input.campaign, input.business);
  
  // Deploy pages
  const deployment = await deployLocal(pages, {
    publicDir: './public',
    baseUrl: process.env.BASE_URL
  });
  
  // Store URLs in submission record
  await db.update(submissions).set({
    landingPageUrl: deployment.optInUrl,
    privacyPolicyUrl: deployment.privacyPolicyUrl,
    termsUrl: deployment.termsUrl
  }).where(eq(submissions.id, submissionId));
  
  // Continue with brand registration...
}
```

### Step 2: Include URLs in Campaign Submission

```typescript
// When submitting campaign to TCR
const campaignPayload = {
  CampaignUseCase: input.campaign.useCase,
  Description: input.campaign.description,
  MessageFlow: input.campaign.messageFlow,
  HelpMessage: input.campaign.helpMessage,
  OptInMessage: input.campaign.optInMessage,
  OptOutMessage: input.campaign.optOutMessage,
  
  // URLs from deployed pages
  ReferenceId: submission.landingPageUrl,
  // Privacy policy might be requested separately
  PrivacyPolicyUrl: submission.privacyPolicyUrl,
  TermsOfServiceUrl: submission.termsUrl
};
```

## Deployment Options

### Option 1: Local (Self-Hosted)

```typescript
import { deployLocal } from './pages';

const result = await deployLocal(pages, {
  publicDir: './public',
  baseUrl: 'https://comply.yourdomain.com'
});

// Pages written to:
// ./public/{slug}/index.html
// ./public/{slug}/privacy-policy.html
// ./public/{slug}/terms.html
```

**Setup Express to serve:**

```typescript
import express from 'express';
import path from 'path';

const app = express();
app.use(express.static(path.join(__dirname, '../public')));

app.listen(3000, () => {
  console.log('Landing pages served on http://localhost:3000');
});
```

### Option 2: Vercel

```typescript
import { deployVercel } from './pages';

const result = await deployVercel(pages, {
  apiToken: process.env.VERCEL_TOKEN!,
  projectName: 'a2p-landing-pages',
  subdomain: 'comply',
  teamId: process.env.VERCEL_TEAM_ID
});

// Deployed to: https://comply.vercel.app/{slug}/
```

**Environment Variables for Vercel:**

```bash
VERCEL_TOKEN=your_vercel_api_token
VERCEL_TEAM_ID=your_team_id (optional)
```

## Customization

### Brand Colors

```typescript
const config = createLandingPageConfig(
  business,
  campaign,
  email,
  phone,
  baseUrl,
  {
    brandColor: '#FF6B35', // Custom orange
    logoUrl: 'https://cdn.example.com/logo.png'
  }
);
```

### Message Frequency

```typescript
const config = createLandingPageConfig(
  business,
  campaign,
  email,
  phone,
  baseUrl,
  {
    messageFrequency: 'up to 10 messages per month'
  }
);
```

### Custom Templates

Edit the raw `.hbs` files in `landing-template/` and regenerate:

```typescript
import Handlebars from 'handlebars';
import fs from 'fs/promises';

const customTemplate = await fs.readFile('landing-template/opt-in.hbs', 'utf-8');
const compiled = Handlebars.compile(customTemplate);
const html = compiled(templateData);
```

## API Integration

### Express Route Example

```typescript
import express from 'express';
import { generateLandingPages, deployLocal } from './pages';

const router = express.Router();

router.post('/api/landing-pages', async (req, res) => {
  try {
    const { business, campaign, email, phone } = req.body;
    
    const config = createLandingPageConfig(
      business,
      campaign,
      email,
      phone,
      process.env.BASE_URL!
    );
    
    const pages = generateLandingPages(config, campaign, business);
    
    const result = await deployLocal(pages, {
      publicDir: './public',
      baseUrl: process.env.BASE_URL
    });
    
    res.json({
      success: true,
      urls: {
        optIn: result.optInUrl,
        privacy: result.privacyPolicyUrl,
        terms: result.termsUrl
      }
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

export default router;
```

## Testing

```typescript
import { generateLandingPages } from './pages';

// Test with mock data
const mockConfig = {
  businessName: 'Test Business Inc',
  businessSlug: 'test-business-inc',
  useCase: 'Account Notification',
  useCaseDescription: 'Account alerts and updates',
  messageFrequency: 'up to 5 per week',
  privacyPolicyUrl: '/test/privacy.html',
  termsUrl: '/test/terms.html',
  contactEmail: 'test@example.com',
  contactPhone: '+15551234567',
  brandColor: '#3B82F6'
};

const mockCampaign = {
  useCase: 'ACCOUNT_NOTIFICATION',
  description: 'Test campaign',
  // ... other fields
};

const mockBusiness = {
  businessName: 'Test Business Inc',
  websiteUrl: 'https://test.com',
  // ... other fields
};

const pages = generateLandingPages(mockConfig, mockCampaign, mockBusiness);

// Write to test directory
await fs.writeFile('./test-output/opt-in.html', pages.optInHtml);
```

## Compliance Checklist

Before deploying to production:

- ✅ All TCPA-compliant language is present
- ✅ Consent checkbox is NOT pre-checked
- ✅ Message frequency is accurate
- ✅ Contact information is correct
- ✅ STOP/HELP instructions are clear
- ✅ Privacy policy covers all data usage
- ✅ Terms include carrier disclaimers
- ✅ Pages are mobile-responsive
- ✅ Legal review completed

## Performance Notes

- Templates are compiled once and reused
- Deployment is async and non-blocking
- Local deployment: ~50ms per site
- Vercel deployment: ~2-5 seconds (API latency)
- Pages are static HTML (no server-side rendering needed)

## Error Handling

```typescript
try {
  const pages = generateLandingPages(config, campaign, business);
  const result = await deployLocal(pages, options);
} catch (error) {
  if (error.code === 'EACCES') {
    console.error('Permission denied writing to public directory');
  } else if (error.code === 'ENOSPC') {
    console.error('No disk space left');
  } else {
    console.error('Deployment failed:', error);
  }
}
```

## Security Considerations

1. **Input Sanitization**: Handlebars auto-escapes HTML by default
2. **XSS Protection**: No user-generated content in templates
3. **HTTPS Required**: Always deploy over HTTPS for compliance
4. **No Sensitive Data**: Templates don't store personal information
5. **CORS**: Configure appropriately for API endpoints

## Next Steps

1. ✅ Install `handlebars` package
2. ✅ Configure deployment environment (local or Vercel)
3. ✅ Set environment variables (BASE_URL, VERCEL_TOKEN if needed)
4. ✅ Integrate into brand submission pipeline
5. ✅ Test with sample data
6. ✅ Get legal review
7. ✅ Deploy to production

## Support

For questions or issues with the landing page generator:
- Check the template documentation in `landing-template/README.md`
- Review generated HTML output for compliance
- Test on multiple devices and browsers
- Ensure all URLs are HTTPS in production
