# ADR-003: Dual Surface Architecture

## Status
Accepted

## Context
CMS-aiChemist needs to serve two distinct types of user interfaces:

1. **Content-focused surfaces**: Marketing pages, documentation, blog posts, case studies - primarily static or lightly dynamic content managed by content editors
2. **Interactive surfaces**: Dashboards, data visualizations, design system showcases, interactive tools - client-side heavy, React component-driven

Single-framework solutions present trade-offs:
- Pure Next.js: Content management requires custom CMS or headless integration
- Pure Astro: Interactive features require more manual wiring
- Pure SPA: SEO and content performance suffer

We need an architecture that optimizes each surface type without compromise.

## Decision
Implement a dual surface architecture with framework specialization:

### Content Surfaces (cms-content)
- **Framework**: Astro 6
- **CMS**: EmDash (SQLite-backed, admin UI included)
- **Port**: 3501
- **Domain**: cms-content.chem.dev
- **Use cases**: Marketing pages, documentation, blog, content-heavy routes

### Interactive Surfaces (cms-web)
- **Framework**: Next.js 15
- **Rendering**: App Router with client components
- **Port**: 3500
- **Domain**: cms.chem.dev
- **Use cases**: Dashboard, design system catalog, interactive demos, data visualization

### Shared Foundation
Both surfaces consume:
- **packages/ui/** - React component primitives (9 components: Button, Card, Tabs, Alert, PricingTable, TestimonialWall, MetricsPanel, AuthorBioCard, FeatureComparisonTable)
- **packages/tokens/** - DTCG design tokens (171 tokens in CSS custom properties)
- **Design system**: Same visual language, tokens, and components

## Consequences

### Positive
- **Optimized tools**: Each framework does what it does best
- **Content team**: EmDash admin UI for content editors, no custom CMS needed
- **Performance**: Astro's zero-JS default for content, React's interactivity for apps
- **Flexibility**: Can add more surfaces (Svelte, Vue) without affecting existing ones
- **Independent deploy**: Build and deploy each surface separately

### Negative
- **Two build pipelines**: Must build both apps separately
- **Two PM2 processes**: cms-web and cms-content both require monitoring
- **Two Caddy virtual hosts**: Separate reverse proxy configuration
- **Increased complexity**: Developers must understand two frameworks
- **Shared component constraints**: UI components must work in both environments

### Neutral
- **9 routes in cms-web**: /, /dashboard, /design-system, /kaleido-life, /pricing, /testimonials, /metrics, /authors, /compare
- **cms-content incomplete**: Currently returns 302 (EmDash first-run setup not finished)
- **Build commands**:
  - cms-web: `cd apps/web && pnpm build`
  - cms-content: `cd apps/cms-theme && pnpm build`
- **Production restart**: `pm2 restart cms-web && pm2 restart cms-content`

### Integration Points
- Shared design tokens ensure visual consistency
- Component library provides unified primitives
- Both apps can cross-link (marketing → app, app → content)
- Static exports from either can be served via Caddy file_server
- EmDash content can be consumed by Next.js via API if needed
