# @claude-view/landing — Technical Architecture

> Astro 5 + Starlight static site. Zero client-side framework JS. Deployed to Cloudflare Pages.

**Design doc:** `docs/plans/2026-02-28-landing-page-design.md`
**Implementation plan:** `docs/plans/2026-02-28-landing-page-impl.md`

---

## Stack

| Layer | Technology | Why |
|-------|-----------|-----|
| Framework | Astro 5 (SSG) | Content-first, zero JS by default, zero-config Cloudflare Pages deploy |
| Docs engine | Starlight | Built-in search/sidebar, Content Collections, MDX |
| Styling | Tailwind CSS 4 (CSS-first config) | No `tailwind.config.mjs` — all via `@theme {}` in CSS |
| Hosting | Cloudflare Pages | `wrangler pages deploy dist`, edge CDN, optional Markdown for Agents (paid plan) |
| Icons | Lucide (inline SVG) | No icon library bundle, no React dependency |
| Fonts | Outfit + IBM Plex Sans + JetBrains Mono | Google Fonts with `display=swap` |
| Interactivity | Vanilla `<script>` tags | No React, no hydration, no framework runtime |

**Not using:** React, Next.js, shadcn/ui, any client-side framework.

---

## SEO, GEO & Agent Discoverability Architecture

This section catalogs every optimization technique applied across five layers: Agent/LLM discoverability, Generative Engine Optimization (GEO), traditional SEO, performance (Core Web Vitals as ranking signal), and accessibility.

### Layer 1: Agent / LLM Discoverability

Makes the site parseable and citable by AI agents (Claude, ChatGPT, Gemini, Perplexity).

| Technique | File(s) | Spec/Standard | What It Does |
|-----------|---------|---------------|-------------|
| **llms.txt** | `public/llms.txt` | [llmstxt.org v1.0](https://llmstxt.org/) | Structured site summary for LLMs: H1 name, blockquote summary, H2 sections with doc links. ~2-10k tokens of curated context vs 500k+ from HTML crawl. |
| **llms-full.txt** | `public/llms-full.txt` (auto-generated) | llmstxt.org | Full docs concatenated into single markdown file. Auto-generated by `scripts/generate-llms-full.mjs` on every build (`prebuild` script). Single ingestion point for all documentation. |
| **AI crawler allow rules** | `public/robots.txt` | RFC 9309 | Explicit `User-agent: ClaudeBot/GPTBot/PerplexityBot` allow rules — prevents accidental blocking via WAF. |
| **Cloudflare Markdown for Agents** | CF Dashboard toggle | [Cloudflare docs](https://developers.cloudflare.com/fundamentals/reference/markdown-for-agents/) | Auto-converts HTML to markdown when `Accept: text/markdown` header sent. Up to 80% token reduction (Cloudflare's figure). Must be explicitly enabled. **Requires paid plan (Pro+, $20/mo).** Pages compatibility undocumented. Fallback: `llms.txt` serves agent-readable content regardless. |

### Layer 2: Generative Engine Optimization (GEO)

Optimizes for AI-generated search results (Google AI Overviews, ChatGPT search, Perplexity). Pages with Schema.org markup are ~36% more likely to appear in AI-generated summaries (WPRiders/LLMrefs research; industry analysis, not peer-reviewed). Content-level techniques (fluency, statistics, citations) have even stronger evidence per the Princeton GEO paper.

| Technique | File(s) | Schema Type | Scope |
|-----------|---------|-------------|-------|
| **SoftwareApplication** | `MarketingLayout.astro` `<head>` | `schema.org/SoftwareApplication` | All marketing pages — identifies claude-view as a developer tool with name, category, OS, pricing |
| **TechArticle** | `astro.config.mjs` Starlight `head` | `schema.org/TechArticle` | All Starlight doc pages — links each article to parent SoftwareApplication entity |
| **FAQPage** | `pages/pricing.astro` | `schema.org/FAQPage` | Pricing page — 4 FAQ questions (free?, Pro features?, install?, multi-session?). Pricing questions are top AI-search queries for dev tools. |
| **BlogPosting** | `layouts/BlogLayout.astro` | `schema.org/BlogPosting` | Every blog post — headline, datePublished, author, publisher, parent Blog entity |
| **HowTo** | `docs/installation.mdx` | `schema.org/HowTo` | Installation docs — step-by-step `npx claude-view` setup. Eligible for rich snippets in Google search and AI overviews. |
| **BreadcrumbList** | `MarketingLayout.astro`, Starlight | `schema.org/BreadcrumbList` | Site hierarchy breadcrumbs (Home > Docs > Features > ...). Improves navigation display in search results. |

All structured data is JSON-LD injected in `<head>` via Astro's `set:html` directive.

### Layer 3: Traditional SEO

| Technique | File(s) | Standard | Notes |
|-----------|---------|----------|-------|
| **Canonical URLs** | `MarketingLayout.astro` | `<link rel="canonical">` | Derived from `Astro.site` + `Astro.url.pathname`. `site` set in `astro.config.mjs`. |
| **Meta description** | `MarketingLayout.astro` | `<meta name="description">` | Per-page via props, defaults to "Mission Control for AI coding agents" |
| **Sitemap** | Auto-generated by `@astrojs/sitemap` | `sitemap.xml` | Referenced in `robots.txt`. Includes all pages. |
| **robots.txt** | `public/robots.txt` | Standard | `Allow: /`, Sitemap ref, AI crawler allow rules (ClaudeBot, GPTBot, PerplexityBot) |
| **Semantic HTML** | All `.astro` components | HTML5 | Proper heading hierarchy, `<nav>`, `<main>`, `<footer>`, `<article>`, `<section>`, `<time>` |
| **Open Graph** | `MarketingLayout.astro` | [ogp.me](https://ogp.me/) | `og:type` (website or article), `og:title`, `og:description`, `og:image`, `og:url` on every page |
| **OG article tags** | `BlogLayout.astro` | OG article namespace | `article:published_time`, `article:author` on blog posts (not marketing pages) |
| **Twitter Cards** | `MarketingLayout.astro` | Twitter Card spec | `summary_large_image`, `twitter:site` (@claude_view), title/description/image |
| **OG image** | `public/og-image.png` | 1200x630 PNG | Dark bg, "claude-view" in Outfit Bold, subtitle, green accent. Referenced by all pages as default. |
| **Favicon** | `public/favicon.svg` | SVG favicon | Green terminal cursor on dark background |

### Layer 4: Performance (Core Web Vitals = SEO Signal)

| Technique | File(s) | Target | Notes |
|-----------|---------|--------|-------|
| **Zero-JS architecture** | Entire site | 0 KB framework JS | No React, no hydration. All interactivity via vanilla `<script>` tags (~1-2KB total). Astro deduplicates scripts. |
| **Google Fonts preconnect** | `MarketingLayout.astro` `<head>` | LCP ~100ms typical, up to 300ms in high-latency conditions | `<link rel="preconnect" href="fonts.googleapis.com">` + `fonts.gstatic.com` with `crossorigin`. Saves DNS+TCP+TLS latency. Consider self-hosting WOFF2 post-V1 for further gains. |
| **Font display swap** | `global.css` Google Fonts URL | CLS: minimal | `display=swap` prevents FOIT (invisible text) but causes brief FOUT (flash of unstyled text) as the fallback font swaps to the web font — this contributes a small CLS. True CLS: 0 is not achievable with `display=swap`. |
| **Static Site Generation** | Astro SSG | TTFB < 50ms | Pre-rendered HTML served from Cloudflare edge. No server-side rendering, no cold starts. |
| **CSS-only animations** | All animated components | No JS animation lib | Typewriter, pulse, slide-in, fade — all `@keyframes` + `animation-delay`. No GSAP, no Framer Motion. |
| **Reduced motion** | Every animated component | `prefers-reduced-motion` | All animations have `@media (prefers-reduced-motion: reduce)` with static fallbacks. Both scoped `<style>` and global `global.css`. |
| **Tailwind JIT purge safelist** | `global.css` | Bundle size | `@source inline(...)` safelists Nav scroll-effect classes that only appear in JavaScript (would be purged otherwise). |
| **Lighthouse target** | All pages | 95+ all 4 metrics | Performance, Accessibility, Best Practices, SEO |
| **LCP target** | | < 1.5s | Hero text is static HTML — no JS blocking, no layout shift |
| **CLS target** | | < 0.1 | All dimensions pre-set, no dynamic content injection above fold. Google "Good" threshold. |
| **INP target** | | < 200ms | Core Web Vital (replaced FID March 2024). Static SSG with minimal JS passes easily. |
| **Speculation Rules** | `astro.config.mjs` | Prefetch/prerender on hover | Chromium browsers prerender linked pages on hover via Speculation Rules API; Firefox/Safari fall back to standard `<link rel="prefetch">`. Progressive enhancement — no impact on non-supporting browsers. |
| **View Transitions** | `MarketingLayout.astro` | Smooth page navigation | CSS View Transitions API for seamless same-origin navigation. Progressive enhancement — browsers without support get standard navigation. |
| **AVIF images** | `src/assets/` | ~50% smaller than JPEG | AVIF format with WebP and PNG fallbacks via `<picture>` element. Astro's `<Image>` component handles format negotiation. |

### Layer 5: Accessibility (WCAG 2.2 AA)

| Technique | File(s) | Standard | Notes |
|-----------|---------|----------|-------|
| **Skip-to-content link** | `MarketingLayout.astro` | WCAG 2.4.1 | `sr-only` link before `<Nav>`, visible on focus. Targets `#main-content` on `<main>`. |
| **Focus-visible ring** | `MarketingLayout.astro` `<style>` | WCAG 2.4.7 | `outline: 2px solid #22c55e; outline-offset: 2px` — green ring visible on dark background. |
| **Color contrast** | Design tokens | WCAG 1.4.3 | 4.5:1 minimum. Primary text `#F8FAFC` on `#0F172A` = 15.3:1. Secondary `#94A3B8` on `#0F172A` = 5.5:1. |
| **Touch targets** | All interactive elements | WCAG 2.5.5 AAA | 44x44px target (AA minimum: 24x24px per WCAG 2.2 SC 2.5.8) |
| **Cursor pointer** | All clickable elements | UX convention | Every `<a>`, `<button>`, clickable `<div>` has `cursor-pointer` |
| **Semantic landmarks** | All layouts | WCAG 1.3.1 | `<nav>`, `<main>`, `<footer>`, `<article>`, `<section>` properly nested |
| **Responsive** | All components | Tested breakpoints | 375px, 768px, 1024px, 1440px. No horizontal scroll. Hamburger nav on mobile. |

---

## Content Architecture

| Route | Layout | Content Source | Schema |
|-------|--------|---------------|--------|
| `/` | MarketingLayout | `pages/index.astro` | SoftwareApplication |
| `/pricing` | MarketingLayout | `pages/pricing.astro` | FAQPage |
| `/blog` | MarketingLayout | `pages/blog/index.astro` | — |
| `/blog/[slug]` | BlogLayout | `content/blog/*.mdx` | BlogPosting |
| `/changelog` | MarketingLayout | `pages/changelog.astro` | — |
| `/docs/**` | Starlight | `content/docs/**/*.mdx` | TechArticle |

## Static Assets

| File | Purpose | Referenced By |
|------|---------|--------------|
| `public/llms.txt` | LLM site summary | robots.txt, AI crawlers |
| `public/llms-full.txt` | Full docs for AI ingestion | AI crawlers |
| `public/robots.txt` | Crawl directives + Sitemap + AI crawler allow rules | Search engines, AI crawlers |
| `public/favicon.svg` | Browser tab icon | MarketingLayout `<head>` |
| `public/og-image.png` | Social share image (1200x630) | All OG tags (default) |

## Font Stack

| Role | Font | Weights | CSS Variable |
|------|------|---------|-------------|
| Headings | Outfit | 400-700 | `--font-heading` |
| Body | IBM Plex Sans | 300-600 | `--font-body` |
| Code | JetBrains Mono | 400-600 | `--font-mono` |

## Color Tokens

| Token | Value | Tailwind | Usage |
|-------|-------|----------|-------|
| `--color-bg` | `#0F172A` | slate-900 | Page background |
| `--color-surface` | `#1E293B` | slate-800 | Cards, elevated surfaces |
| `--color-border` | `#334155` | slate-700 | Borders |
| `--color-text` | `#F8FAFC` | slate-50 | Primary text |
| `--color-text-secondary` | `#94A3B8` | slate-400 | Secondary text |
| `--color-cta` | `#22C55E` | green-500 | CTA buttons, active status |
| `--color-attention` | `#F59E0B` | amber-500 | Warnings, "waiting" status |
| `--color-accent` | `#3B82F6` | blue-500 | Links, secondary accent |

---

## Verification Checklist

### Agent SEO / GEO

```bash
# Cloudflare Markdown for Agents — must return markdown, not HTML
curl -s -H "Accept: text/markdown" https://claudeview.ai/ | head -5

# llms.txt accessible
curl -s https://claudeview.ai/llms.txt | head -5

# llms-full.txt accessible
curl -s https://claudeview.ai/llms-full.txt | wc -l

# robots.txt has AI crawler allow rules
curl -s https://claudeview.ai/robots.txt | grep -A1 'ClaudeBot'

# sitemap.xml generated
curl -s https://claudeview.ai/sitemap.xml | head -5

# Structured data present (check for JSON-LD)
curl -s https://claudeview.ai/ | grep -c 'application/ld+json'
curl -s https://claudeview.ai/pricing | grep -c 'FAQPage'
curl -s https://claudeview.ai/docs/ | grep -c 'TechArticle'
```

### Open Graph

```bash
# Homepage OG tags
curl -s https://claudeview.ai/ | grep 'og:type'
# Expected: content="website"

# Blog post OG tags
curl -s https://claudeview.ai/blog/introducing-claude-view | grep 'og:type'
# Expected: content="article"

# article:published_time present on blog
curl -s https://claudeview.ai/blog/introducing-claude-view | grep 'article:published_time'
```

### Performance

```bash
# No framework JS shipped (only vanilla scripts)
ls -la dist/_astro/*.js 2>/dev/null | wc -l
# Expected: 0-2 tiny files (vanilla scripts only)

# Total JS size
du -sh dist/_astro/*.js 2>/dev/null
# Expected: < 5KB total
```

---

## Dev Commands

| Command | What |
|---------|------|
| `bun run dev` | Astro dev server with HMR |
| `bun run build` | Build to `dist/` (runs `prebuild` first for llms-full.txt) |
| `bun run preview` | Preview built site locally |
| `bun run typecheck` | `astro check` (requires initial build for `.astro/types.d.ts`) |
| `bun run deploy` | `wrangler pages deploy dist` |

## Deployment

Cloudflare Pages via existing `wrangler.toml`. Static `dist/` directory. No SSR adapter needed.

Post-deploy: toggle Markdown for Agents in CF Dashboard (Zone > Quick Actions).
