# MailHub Public Landing Page Design

## Goal

Replace the current “anonymous root URL → login/admin app” experience with a **developer-first public marketing homepage** (Resend / Mailjet-inspired). Unauthenticated visitors see product value, API/SMTP/Webhook integration paths, and bilingual CTAs; authenticated users still reach the admin console at `/`.

## Product Decisions

| Item | Choice |
|------|--------|
| Audience | Developers first |
| Scope (MVP) | Single-page landing with in-page anchors |
| Language | zh-CN / en-US toggle (localStorage) |
| Pricing | None |
| Implementation | Static landing entry (Vite `landing` build), decoupled from React admin bundle |
| Visual system | Same Modern SaaS indigo tokens as admin (`#4F46E5`, canvas, ink) |

## Non-Goals (MVP)

- Multi-page docs site, blog, changelog site
- Pricing tables or billing
- Embedding the landing page inside the React admin SPA
- Changing send/webhook business APIs
- Fake customer logos or fabricated social proof

## Current Behavior (to change)

- Unauthenticated browser traffic to protected pages redirects to `/login`.
- `/` maps to `public/index.html` (admin app).
- Login/register assets are public; admin is session-gated.

## Routing & Auth

| Path | Unauthenticated | Authenticated |
|------|-----------------|---------------|
| `GET /` | Serve **landing** (`landing.html`) | Serve **admin** (`index.html`) |
| `/login`, `/register`, `/forgot-password`, `/resend-verification`, `/reset-password` | `login.html` | Optional redirect to admin if already logged in (existing) |
| `/app` (optional alias) | Redirect to `/login` | Admin console |

### Server rules (`src/server.js`)

1. Treat landing HTML/CSS/JS as **login-class public assets** (no session required), same pattern as `/login.html`.
2. For `GET /` (or mapped `/index` root):
   - If `getRequestUser` is present → `index.html` (admin).
   - Else → `landing.html`.
3. Do **not** redirect anonymous `/` to `/login`.
4. Keep `/api/*` auth unchanged.
5. **Caching:** Root HTML responses that depend on session (`GET /` landing vs admin) MUST be non-cacheable: e.g. `Cache-Control: private, no-store` (and prefer the same for `landing.html` / `index.html` HTML documents) so proxies/browsers do not stick a visitor on the wrong shell after login.
6. **`/app` alias:** out of MVP; primary CTAs use `/register` and `/login` only.

## Information Architecture (single page)

### Sticky header

- Brand: MH mark + MailHub  
- Anchor nav: Features · Integrate · API · SMTP · Webhooks  
- Language toggle: 中文 / EN  
- CTAs: Log in (secondary), Sign up / Get started (primary)

### Hero

- Developer-oriented headline + subcopy (self-hosted, DKIM/SPF/DMARC, logs, webhooks)
- Primary CTA → `/register`
- Secondary CTA → `#api` (scroll)
- Visual: dark code panel with curl `POST /api/send` sample

### Trust strip (light)

- Text chips only: Self-hosted · DKIM · SPF · DMARC · Delivery webhooks  
- No fake logos

### Features grid (5–6 cards)

1. Domain + DNS automation  
2. SMTP Submission  
3. HTTP Send API + tokens  
4. Delivery tracking & logs  
5. Webhooks (`sent` / `bounced` / `failed`)  
6. Multi-user isolation  

### Integrate (3 columns)

| Column | Content |
|--------|---------|
| API | Token auth, `POST /api/send`, field list, link to register |
| SMTP | Host/ports aligned with product submission config, example snippet |
| Webhooks | Event types + signature headers summary, “configure after login” |

### Deep sections

- **#api** — curl + JSON body + Authorization header (match existing token docs field names)
- **#smtp** — ports and connection notes consistent with runtime submission  
- **#webhooks** — event type table + `X-MailHub-Signature` one-liner  

### Closing CTA

- Headline + Register + Log in  
- No pricing  

### Footer

- Product name, Log in, Register, optional GitHub link  
- Copyright line  

## Static sample content policy

Landing is **fully static** (no authenticated API on first paint).

- Use **placeholders** for host/base URL: `https://mail.example.com`, host `mail.example.com` (or “your MailHub host” in prose).
- Document **default public SMTP ports** from product defaults: `25` (smtp), `587` (smtp/STARTTLS), `465` (smtps), `2525` (smtp). Do not hardcode a specific production hostname from env.
- **Forbidden in MVP:** unauthenticated config API for landing; build-time injection of production `.env` into landing assets.
- API sample fields match product helpers: `from`, `to`, `subject`, `text`; header `Authorization: Bearer <USER_API_TOKEN>`.
- Webhook samples: events `sent` | `bounced` | `failed`; payload `type` `email.sent` / `email.bounced` / `email.failed`; header `X-MailHub-Signature: t=…,v1=…`.

## Visual Design

- CSS variables aligned with admin redesign:
  - `--mh-primary: #4F46E5`
  - canvas / ink / border / radius / shadow  
- Light marketing layout; dark code blocks for developer feel  
- Comfortable spacing; responsive stack; mobile nav collapse or wrap  
- System font stack (no CDN Inter required)

## Internationalization

- Dictionary module for `zh-CN` and `en-US`
- Persist choice in `localStorage` (key e.g. `mailhub-landing-locale`)
- Default: `navigator.language` starts with `zh` → zh-CN, else en-US
- Toggle updates all `data-i18n` nodes and `document.documentElement.lang`
- Code identifiers remain English; comments/labels in dictionary may switch

## Engineering

### Build (committed path)

**Vite multi-page entry only** (same pipeline as `index` / `login`):

- Source: repo-root `landing.html` + `src/frontend/landing/main.ts` + `landing.css` + i18n dictionary
- `vite.config.ts` input key: `landing`
- Output: `public/landing.html` + hashed assets under `public/assets/`

Do not maintain a parallel hand-written-only `public/landing.html` source of truth outside the Vite build.

### Client behavior

- Smooth scroll for header anchors  
- Copy-to-clipboard on code samples  
- No API calls required for first paint  

### Tests

- Server: anonymous `GET /` body/title or content-type indicates landing (or path resolution helper unit test)
- Server: authenticated session `GET /` resolves to admin index  
- Public: landing assets reachable without cookie  
- Optional: i18n dictionary has both locales for required keys  

## File Map (expected)

| Path | Role |
|------|------|
| `landing.html` (source) | Landing markup |
| `src/frontend/landing/main.ts` | i18n, interactions |
| `src/frontend/landing/landing.css` | Styles |
| `src/frontend/landing/i18n.js` | Copy dictionary |
| `vite.config.ts` | `landing` input |
| `src/server.js` | Root routing + public asset allowlist |
| `test/server-*.test.js` | Route tests |
| `public/landing.html` + assets | Build output |

## Delivery Order

1. Landing static structure + CSS tokens + zh/en copy  
2. Landing JS (i18n, scroll, copy)  
3. Vite entry + build  
4. Server public routing for `/` and assets  
5. Tests + build gate  
6. Deploy per Agents.md  

## Success Criteria

- Anonymous `/` shows marketing landing, not login form as the only chrome  
- Bilingual toggle works and persists  
- Register/Login CTAs work  
- Logged-in `/` still loads admin console  
- Existing auth and API behavior unchanged  
- `npm test` and `npm run build` pass  

## Open Follow-ups

- Full `/docs` site  
- Pricing page  
- Marketing analytics  
- Open Graph / social meta images  
