Internal · noindex · Project 1 of 3

Landing technical architecture

How apps/landing is built, shipped, and wired for demand. Static multi-page Vite site — no React, no app backend, no @agentpad/* imports. Live at www.mechapad.com.

Vite 6 MPA TypeScript Static HTML Vercel Stripe Payment Link No framework UI No daemon deps

1 · System overview

The landing is Project 1 in the monorepo: marketing + pricing + Founding deposit. Desktop and Hardware are separate products that share narrative, not code.

┌─────────────────────────────────────────────────────────────────────┐
│                         MONOREPO (agentpad)                          │
│                                                                     │
│  apps/landing  ──static──▶  Vercel CDN  ──▶  browser               │
│       │                         │                                   │
│       │                    /api/checkout → Stripe Session           │
│       │                    (USD only, adaptive pricing off)         │
│       │                                                             │
│  apps/desktop · apps/virtual-pad · packages/* · hardware/            │
│  (NOT imported by landing — separate deploy / runtime)              │
└─────────────────────────────────────────────────────────────────────┘

Request path (production)
  DNS  →  Vercel  →  apps/landing/dist/*.html + hashed assets
  public/* (robots, sitemap, llms.txt, SVG) copied as-is

What it is

  • Static multi-page marketing site
  • Package @agentpad/landing
  • Dev server :5180
  • Output apps/landing/dist

What it is not

  • Not the control-center UI (virtual-pad)
  • Not Electron / daemon / cloud gateway
  • Not hardware firmware or bridge
  • No SSR, no edge functions, no DB

2 · Stack & source layout

Deliberately thin: Vite + hand-written HTML + small TS modules + CSS tokens aligned with the desktop app monochrome.

Pages
Root *.html + blog/*.html — each file is a full document (MPA). SEO meta, Open Graph, and JSON-LD live in the page head.
Styles
src/style.css (legacy MechaPad home) · src/megapad.css (go-forward MegaPad + SEO/blog) · src/board.css (war room) · optional industrial / apple experiments.
Scripts
src/main.ts (home / get) · src/megapad.ts (product + SEO + blog) · src/board.ts (checklist / ideate). No framework — DOM + localStorage only.
Public
public/ → root of dist: robots.txt, sitemap.xml, llms.txt, SVG assets.
Build
Vite 6 multi-entry Rollup config in vite.config.ts. Typecheck via tsc --noEmit.
Host
Root vercel.json: install with pnpm, filter-build landing, serve apps/landing/dist.
apps/landing/
├── index.html, megapad.html, get.html, hardware.html, …
├── blog/                  # long-tail SEO guides
├── public/                # robots, sitemap, llms, SVG
├── src/
│   ├── main.ts            # MechaPad home + get
│   ├── megapad.ts         # product / SEO / blog client
│   ├── board.ts           # internal war room
│   ├── style.css          # legacy home skin
│   ├── megapad.css        # primary brand skin
│   └── board.css
├── vite.config.ts         # multi-page inputs
├── package.json           # @agentpad/landing
└── dist/                  # build output → Vercel

3 · Page map

Every public URL is a real HTML file (no client router). Go-forward product surface is /megapad.html; home still carries MechaPad SEO equity.

Money & product

/ MechaPad home · SEO + JSON-LD
/megapad.html Go-forward product · dual CTA
/get.html Founding $99 pay page
/hardware.html Pad-first experiment · hw_hero
/thanks.html Post-checkout · noindex

SEO & content

/codex-micro-alternative.html Tier A — competitor intent
/multi-model-ai-agent.html Tier A — category intent
/blog.html Blog hub
/blog/* Tier C long-tail guides

Internal / experimental

/board.html War room checklist · noindex
/architecture.html This page · noindex
/apple.html Alternate skin experiment

Script binding

main.ts index, get, legacy pages
megapad.ts Product, hardware, SEO, blog
board.ts War room only

4 · Client runtime

All interactivity is progressive enhancement in the browser. No API keys, no auth, no backend on this package.

main.ts / megapad.ts

  • Footer year stamp
  • Scroll reveals via IntersectionObserver on .reveal
  • Waitlist form → localStorage list (mechapad-com-waitlist / megapad-waitlist / megapad-hardware-waitlist)
  • Deposit CTA clicks → megapad-deposit-clicks ring buffer (last 100)

board.ts

  • Checklist state per checkbox data-id
  • Ideate textarea autosave (300ms debounce)
  • Copy-to-clipboard for post templates
  • Stats: done / total in this browser only
Attribution model

Stripe Payment Links use ?client_reference_id=… per surface: sw_primary (software dual CTA), hw_hero (hardware-hero), get_page, SEO/blog ids, pricing footer variants. Client-side data-track logs clicks locally until real analytics ships. See docs/hardware/DEPOSIT-METRICS.md.

5 · Build pipeline

Multi-page application: every HTML entry is listed under build.rollupOptions.input in vite.config.ts. New public pages must be added there or they will not ship.

pnpm dev:landing     # vite dev · http://127.0.0.1:5180
pnpm build:landing   # → apps/landing/dist

vite build
  1. Resolve each HTML entry (main, megapad, get, blog/*, …)
  2. Bundle linked TS modules → dist/assets/*.js (hashed)
  3. Bundle CSS → dist/assets/*.css (hashed)
  4. Copy public/ → dist root
  5. emptyOutDir: true on each full build

Entry inventory (must stay in sync)

Configured in apps/landing/vite.config.ts: index, apple, thanks, megapad, hardware, board, get, codexAlt, multiModel, blog, six blog/* posts, plus this page architecture.

6 · Deploy architecture

Single Vercel project at repo root. Only the landing dist is the production output — desktop packages are not deployed here.

01

Install

pnpm install (workspace-aware)

02

Build

pnpm --filter @agentpad/landing build

03

Publish

Serve apps/landing/dist as static root

04

Edge

CDN + HTTPS · rewrites pass-through static files

vercel.json (repo root)
{
  "framework": null,
  "installCommand": "pnpm install",
  "buildCommand": "pnpm --filter @agentpad/landing build",
  "outputDirectory": "apps/landing/dist",
  "rewrites": [{ "source": "/(.*)", "destination": "/$1" }]
}

Domain: www.mechapad.com
No serverless functions, no env secrets required for static pages

7 · SEO architecture

Intent → dedicated HTML page → Founding CTA. Plan: docs/website/SEO.md.

On every public page

  • One H1 · title ≤ ~60 chars · meta ~150
  • Canonical on https://www.mechapad.com/…
  • OG / Twitter cards
  • Internal links → /get.html + product
  • JSON-LD where relevant (Org, Software, FAQ, Blog)

Crawl surface

  • public/sitemap.xml — public money + blog URLs
  • public/robots.txt — Disallow board / apple / thanks / architecture
  • public/llms.txt — AI crawler map
  • Static HTML = fast Core Web Vitals baseline
Keyword tiers → pages
  Tier A  codex micro alternative     → /codex-micro-alternative.html
  Tier A  multi-model AI agent        → /multi-model-ai-agent.html
  Tier B  command center / macropad   → /megapad.html (+ hardware)
  Tier C  long-tail how-tos           → /blog/*.html → hub /blog.html

CTA sink  every SEO page → Stripe link or /get.html

8 · Conversion funnel

Live cash path is Stripe Payment Link only. Waitlist is browser-local until a form backend exists. Demand experiments split software-first vs pad-first.

Traffic
  organic SEO · social posts · direct
        │
        ▼
Landing surfaces
  /  ·  /megapad.html  ·  /hardware.html  ·  SEO pages  ·  /blog/*
        │
        ├── Primary money ──▶ Stripe Payment Link ($99 Founding)
        │                      client_reference_id = page / experiment
        │                      success → /thanks.html (or Stripe default)
        │
        └── Waitlist form ──▶ localStorage only (dev / interim)
                              keys: megapad-waitlist | megapad-hardware-waitlist

After desktop public: dual CTA = Download installer + Founding deposit

Experiment A — software dual

/megapad.html · client_reference_id=sw_primary · product story first, pad as Founding upside.

Experiment B — hardware hero

/hardware.html · client_reference_id=hw_hero · pad-forward for demand test without PCB orders.

9 · Monorepo boundaries

Hard isolation keeps the marketing deploy simple and prevents accidental coupling to agent runtime.

Landing owns

  • Static HTML / CSS / TS for marketing
  • GTM, brand, competitive narrative (docs under docs/website/)
  • Waitlist + deposit CTAs and attribution IDs
  • SEO assets and crawl policy

Landing does not own

  • Daemon, protocol types, Electron shell
  • Cloud auth / hosted models / in-app Stripe checkout
  • Hardware firmware, bridge, BOM
  • Agent skills / workspace runtime
Contracts
  • Desktop: publish download links + SKUs once installers are public; prefer Download (or dual) over waitlist-only.
  • Hardware: Founding / Edition One messaging only — no firmware or MCU details required on marketing pages.
  • Protocol: lives in Desktop (packages/protocol); never fork message types on the website.

Related repo docs

apps/landing/README.md Package entry + page table
docs/website/SEO.md Keyword map + on-page rules
docs/website/GTM-MEGAPAD.md Go-to-market
docs/website/BRAND-MECHAPAD.md Naming / brand
docs/hardware/DEPOSIT-METRICS.md Deposit KPI + attribution
README.md (root) Three-project monorepo map

Internal architecture page · War room · Product ·