1 Modular API Architecture with Account-Level Variables

1.1 Overview

This architecture enables multiple Ethical Capital sites (dryvest, labs, future projects) to share common API services while maintaining site-specific configurations. By using Cloudflare account-level environment variables, we achieve true modularity without duplicating infrastructure setup.

1.2 Architecture Pattern

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│ dryvest.ethicic │    │ labs.ethicic    │    │ future-site     │
│ .com            │    │ .com            │    │ .ethicic.com    │
└─────────┬───────┘    └─────────┬───────┘    └─────────┬───────┘
          │                      │                      │
          └──────────────────────┼──────────────────────┘
                                 │
                    ┌─────────────▼──────────────┐
                    │   Account-Level Services   │
                    │  ─────────────────────────  │
                    │  • hook-typst-export       │
                    │  • buttondown-email        │
                    │  • shared tokens           │
                    │  • service URLs            │
                    └────────────────────────────┘

1.3 Implementation

1.3.1 Account-Level Variables (Set Once)

These variables are configured at the Cloudflare account level and automatically available to all sites:

# Core API service authentication
TYPST_EXPORT_TOKEN=kgE2fh/dns2mWmvI6Gm6MHfNXRqXWs/b920ISCXcO0U=
BUTTONDOWN_API_KEY=<your-buttondown-api-key>

# Service endpoint URLs
HOOK_TYPST_EXPORT_URL=https://hook-typst-export.srvo.workers.dev

To set account-level variables:

npx wrangler secret put --account-level TYPST_EXPORT_TOKEN
npx wrangler secret put --account-level BUTTONDOWN_API_KEY
npx wrangler secret put --account-level HOOK_TYPST_EXPORT_URL

1.3.2 Site-Specific Variables

Each site only needs to configure its specific requirements:

1.3.2.1 dryvest.ethicic.com

ALLOWED_ORIGINS=https://dryvest.ethicic.com,http://localhost:5173

1.3.2.2 labs.ethicic.com

ALLOWED_ORIGINS=https://labs.ethicic.com,https://labs-aw1.pages.dev,http://localhost:3000

1.3.2.3 future-site.ethicic.com

ALLOWED_ORIGINS=https://future-site.ethicic.com,http://localhost:8080

To set site-specific variables:

# From each site's repository
npx wrangler secret put ALLOWED_ORIGINS

1.4 Shared API Functions

The same API function code works across all sites without modification:

1.4.1 PDF Generation API (/functions/api/generate-pdf.ts)

interface Env {
  // Account-level (automatically available)
  HOOK_TYPST_EXPORT_URL: string;
  TYPST_EXPORT_TOKEN: string;

  // Site-specific
  ALLOWED_ORIGINS: string;
}

export const onRequestPost = async ({ request, env }: { request: Request; env: Env }) => {
  // Origin validation using site-specific domains
  const allowedOrigins = env.ALLOWED_ORIGINS.split(',');
  const origin = request.headers.get('origin');
  const isValidOrigin = allowedOrigins.some(allowed =>
    origin?.includes(allowed)
  );

  if (!isValidOrigin) {
    return Response.json({ error: 'Unauthorized origin' }, { status: 403 });
  }

  // PDF generation using shared service
  const response = await fetch(env.HOOK_TYPST_EXPORT_URL, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${env.TYPST_EXPORT_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(pdfPayload)
  });

  return new Response(response.body, {
    headers: { 'Content-Type': 'application/pdf' }
  });
};

1.4.2 Email PDF API (/functions/api/send-pdf-email.ts)

interface Env {
  // Account-level (automatically available)
  HOOK_TYPST_EXPORT_URL: string;
  TYPST_EXPORT_TOKEN: string;
  BUTTONDOWN_API_KEY: string;

  // Site-specific
  ALLOWED_ORIGINS: string;
}

export const onRequestPost = async ({ request, env }: { request: Request; env: Env }) => {
  // Same origin validation pattern
  const allowedOrigins = env.ALLOWED_ORIGINS.split(',');

  // Generate PDF using shared service
  const pdfResponse = await fetch(env.HOOK_TYPST_EXPORT_URL, {
    headers: { 'Authorization': `Bearer ${env.TYPST_EXPORT_TOKEN}` }
  });

  // Send email using shared Buttondown service
  const emailResponse = await fetch('https://api.buttondown.com/v1/emails', {
    headers: { 'Authorization': `Token ${env.BUTTONDOWN_API_KEY}` }
  });

  return Response.json({ success: true });
};

1.5 Benefits

1.5.1 1. True Modularity

  • Core services defined once, used everywhere
  • New sites inherit all shared functionality automatically
  • No duplication of API service setup

1.5.2 2. Centralized Management

  • Update service URLs once, affects all sites
  • Rotate tokens once, affects all sites
  • Add new shared services easily

1.5.3 3. Site Independence

  • Each site maintains its own domain restrictions
  • Sites can have different rate limits or features
  • Independent deployment and configuration

1.5.4 4. Security

  • Sensitive tokens managed at account level
  • Site-specific origin validation prevents abuse
  • Centralized credential rotation

1.5.5 5. Developer Experience

  • Same API code works across all sites
  • New sites require minimal environment setup
  • Consistent behavior across projects

1.6 Adding New Sites

To add a new site to this architecture:

  1. Create the site repository

  2. Copy shared API functions (generate-pdf.ts, send-pdf-email.ts)

  3. Set site-specific variables only:

    npx wrangler secret put ALLOWED_ORIGINS
    # Enter: https://new-site.ethicic.com,http://localhost:PORT
  4. Deploy - all shared services work immediately

1.7 Shared Service URLs

Current shared services available to all sites:

  • PDF Generation: https://hook-typst-export.srvo.workers.dev
  • Email Service: Buttondown API (https://api.buttondown.com/v1/)
  • Future Services: Add to account-level variables as needed

1.8 Rate Limiting Strategy

Rate limits can be configured per-site while using shared services:

// Different limits per site
const RATE_LIMITS = {
  'dryvest.ethicic.com': 5,    // 5 per hour
  'labs.ethicic.com': 10,      // 10 per hour
  'premium-site.com': 25       // 25 per hour
};

const siteLimit = RATE_LIMITS[siteHostname] || 3; // default

1.9 Monitoring and Debugging

1.9.1 Shared Service Health

  • Monitor hook-typst-export service for all sites
  • Buttondown API usage affects all sites
  • Account-level token rotation requires coordination

1.9.2 Site-Specific Issues

  • Origin validation failures are site-specific
  • Check ALLOWED_ORIGINS configuration per site
  • Local development ports differ per site

1.9.3 Logging Strategy

console.log('PDF generation request:', {
  site: request.headers.get('referer'),
  service: env.HOOK_TYPST_EXPORT_URL,
  // Don't log tokens, just confirm they exist
  hasToken: !!env.TYPST_EXPORT_TOKEN
});

1.10 Future Enhancements

1.10.1 Additional Shared Services

  • Authentication service (auth-service.workers.dev)
  • File storage service (storage-service.workers.dev)
  • Analytics service (analytics-service.workers.dev)

1.10.2 Advanced Configuration

  • Environment-specific overrides (staging vs production)
  • Feature flags for different sites
  • A/B testing infrastructure

1.10.3 Service Discovery

  • Automatic service registration
  • Health checking across shared services
  • Failover and redundancy

1.11 Security Considerations

1.11.1 Token Security

  • Account-level tokens have broad access - rotate regularly
  • Monitor usage patterns across all sites
  • Use least-privilege principle for new services

1.11.2 Origin Validation

  • Keep ALLOWED_ORIGINS restrictive per site
  • Include only necessary development URLs
  • Validate both origin and referer headers

1.11.3 Service Communication

  • All inter-service communication uses Bearer tokens
  • Services validate request source headers
  • Rate limiting prevents service abuse

1.12 Deployment Checklist

When adding new sites or services:

This architecture provides a scalable foundation for Ethical Capital’s growing suite of web applications while maintaining security and simplicity.