|
|
@@ -0,0 +1,181 @@
|
|
|
+# 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. Optional: `GET /app` → admin when authed, else `/login` (deep link from landing CTAs if desired). Landing primary CTAs may simply use `/register` and `/login`.
|
|
|
+
|
|
|
+## 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
|
|
|
+
|
|
|
+## 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
|
|
|
+
|
|
|
+Add Vite multi-page entry alongside existing `index` and `login`:
|
|
|
+
|
|
|
+- Source: `landing.html` at repo root (or under a dedicated path) + `src/frontend/landing/main.ts` + `landing.css`
|
|
|
+- Output: `public/landing.html` + hashed assets under `public/assets/`
|
|
|
+
|
|
|
+Alternatively pure static files under `public/` without TS if simpler—prefer Vite entry for consistency with login/admin pipeline.
|
|
|
+
|
|
|
+### 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
|