2026-07-09-mailhub-landing-page-design.md 6.2 KB

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