Skip to content

feat(landing): conversion-focused redesign of the aoagents.dev landing page#2826

Open
AgentWrapper wants to merge 13 commits into
mainfrom
ao/agent-orchestrator-26/landing-conversion
Open

feat(landing): conversion-focused redesign of the aoagents.dev landing page#2826
AgentWrapper wants to merge 13 commits into
mainfrom
ao/agent-orchestrator-26/landing-conversion

Conversation

@AgentWrapper

Copy link
Copy Markdown
Owner

Summary

Conversion-focused redesign of the public landing page (frontend/src/landing, deployed at aoagents.dev). Every change is aimed at one metric: more visitors starring the repo and trying AO. The stack is unchanged (Next.js + Tailwind + GSAP), and every claim on the page is real and verifiable (8.4k stars, Apache-2.0, nightly releases, the public agentwrapper/tap Homebrew cask).

Before / after

Hero — desktop. Before: headline + two CTAs, nothing that says what AO is; the primary CTA on macOS was a dropdown ("Desktop downloads") instead of a button.

Before After
hero before hero after

Hero — mobile (real iPhone UA). Before: oversized headline and a desktop-download dropdown that is useless on a phone. After: readable scale, subhead, repo-first primary CTA.

Before After
hero mobile before hero mobile after

Social proof. Before: each tweet wrapped in editorializing chrome ("Most important outside validation.") that tells the visitor what to think. After: the real posts speak for themselves; the self-congratulatory official tweet was removed.

Before After
social before social after

New sections. A three-step quickstart that removes the "setup looks heavy" objection, a video facade (Mux iframe no longer blocks first paint), and a closing CTA that repeats the conversion ask with proof.

Quickstart (new) Final CTA (new) Video facade
install cta video

Conversion decisions

  1. Subhead under the headline. The old hero jumped from slogan to buttons; a new visitor had to parse the mockup to learn what AO is. New subhead answers it in ~40 words: "Mission control for a fleet of coding agents. AO runs Claude Code, Codex, Cursor — 23 harnesses — in isolated git worktrees, watches every PR, and routes CI and review feedback back to the agent that owns the branch."
  2. Direct download CTA on every desktop platform. getDownloadTarget() returned null for macOS, so the majority of devs got a dropdown while Windows/Linux got a one-click button. macOS now gets Download for macOS (Apple silicon build; Intel remains one click away via "All platforms"). Portable devices get a repo-first CTA ("Get Agent Orchestrator") since a zip is useless on a phone — the achievable conversion there is a star.
  3. Copy-paste install command in the hero. The public agentwrapper/tap Homebrew cask is real (brew install --cask agentwrapper/tap/agent-orchestrator, verified this session), so macOS visitors get a Warp-style copyable command block with clipboard feedback. Shown again in the quickstart and final CTA.
  4. Live credibility markers. Release pill above the headline (latest stable tag + "nightly builds ship every day" — verifiable in Releases), live star count in the nav (Warp pattern), persistent Download button in the nav, and trust microcopy (Apache 2.0, runs 100% locally).
  5. Quickstart section. Three cards — install (brew + platform buttons), connect (gh auth login, agent CLIs you already have), spawn (ao spawn --prompt …) — directly attacking the "orchestration = complicated" objection.
  6. Final CTA section. The page previously ended with tweets → footer. It now closes with "Your agents are waiting. Put them to work." plus the same download/star/brew trio.
  7. Honest social proof. Removed the editorial label/note layer and the official self-tweet. Five real third-party posts, names/verified badges/dates/likes intact, each linking to the original.
  8. Sharper metadata. Title is now "Agent Orchestrator - Mission control for coding agents", description mirrors the subhead, and metadataBase makes og:image absolute (it previously resolved relative to the host and would break in scrapers). / now carries full OG/Twitter tags, not just /landing.

Accessibility & performance

  • --fg-dim (#79796f → #8a8a82) lifts small-label contrast from ~4.3:1 to ~5.4:1 (WCAG AA on the dark background).
  • Global :focus-visible accent ring for all interactive elements in the landing tree (verified by tabbing through the page).
  • Autonomous GSAP intros (hero, tweets) now respect prefers-reduced-motion; CSS reveals already did.
  • Copy blocks are real <button>s with aria-labels that flip to "Copied to clipboard".
  • Video facade: the Mux iframe (and its JS) now loads on click instead of at page load.
  • GitHub API usage: the old code fetched stars per component on a 5-minute poll; hero + nav + CTA would have tripled that. New shared store (useSyncExternalStore) issues one fetch per page load — matters because unauthenticated GitHub API is capped at 60 req/hr/IP and visitors share NAT egress. When the API is unavailable, the star count simply hides instead of showing a stuck "…".
  • First load: ~170 KB JS (build output), system serif for the headline (zero webfont cost).

Verification

  • npx next build passes (63/63 pages); npx tsc --noEmit clean (only the two pre-existing desktop-downloads.test.ts vitest-typing errors that exist on main).
  • Prettier check passes on all touched files.
  • Download-target logic exercised for Windows/Linux/macOS/iPhone/Android/iPad (see desktop-downloads.test.ts update).
  • Click-tested in a real browser: copy button writes the full command to the clipboard and flips to "Copied"; video facade mounts the Mux iframe with autoplay; mobile menu, nav collapse, and social links verified.
  • Screenshot-audited at 1440px and 390px (real iPhone UA) against the production build, including docs pages (unchanged).

Risks / follow-ups

  • macOS download defaults to Apple silicon (UA can't distinguish arch); Intel Mac users use "All platforms" → install docs. Same trade-off Cursor makes.
  • PR screenshots are committed under docs/screenshots/landing-refresh/ so they render permanently; happy to drop them from the branch if you'd rather keep the repo lean.
  • Star count/release tag are client-fetched, so they can lag a release by one page load; acceptable trade for a fully static page.

…g page

Hero now answers 'what is this' in one glance: mission-control subhead,
direct platform download (macOS gets a real button instead of a dropdown),
copyable brew install command, live release pill, and trust microcopy.

- nav: live GitHub star chip + persistent Download button
- new quickstart section: zero-to-fleet in three steps with copy blocks
- new final CTA section before the footer
- social proof: drop editorializing labels/notes, keep real posts only
- video: poster facade, Mux iframe loads on click (faster first paint)
- a11y: AA contrast for dim text, focus-visible rings, reduced-motion
- seo: absolute og:image via metadataBase, sharper title/description
- perf: shared GitHub facts store (one fetch, no per-component polling)
@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

React Doctor found 1 issue in 1 file · 1 warning · score 96 / 100 (Great) · vs main

1 warning

components/LandingHero.tsx

  • ⚠️ L341 Large component is hard to read and change no-giant-component
⚠️ Warning: .github/workflows/react-doctor.yml is configured incorrectly. See below to fix.

React Doctor compares against main to report only the issues this pull request introduces. This run couldn't complete that comparison (usually a shallow CI checkout with no merge base), so it listed every issue in the changed files, including ones that already existed on main.

Add fetch-depth: 0 to the actions/checkout step in .github/workflows/react-doctor.yml so the checkout includes the history React Doctor needs:

 jobs:
   react-doctor:
     steps:
       - uses: actions/checkout@v5
+        with:
+          fetch-depth: 0

       - uses: millionco/react-doctor@v2

To silence this warning, set silence-missing-baseline-warning: true on the React Doctor action.

Reviewed by React Doctor for commit 146567d. See inline comments for fixes.

Shorter release pill and subhead (one breath instead of three lines),
drop the microcopy row (quickstart/final CTA already carry platforms,
license, and local-only trust signals).
Mux player expects boolean URL params as true/false; autoplay=1 was
ignored, so the player waited for a second click inside the iframe.
Below 640px the bar rendered as an empty pill (logo glyph + hamburger
only) - always render the Agent Orchestrator wordmark.
label="ao spawn command"
className="w-full"
/>
<a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/nextjs-no-a-element (warning)

Plain reloads the whole page for internal links, so Next.js loses client-side navigation and prefetching.

Fiximport Link from 'next/link' for client-side navigation, prefetching, and preserved scroll position

Docs

"https://github.com/AgentWrapper/agent-orchestrator/releases/latest",
);

useEffect(() => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/rendering-hydration-no-flicker (warning)

This flashes for your users because useEffect(setState, []) runs after the first paint, so use useSyncExternalStore, or add suppressHydrationWarning

Fix → Use useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) or add suppressHydrationWarning to the element

Docs

aria-label={`Play video: ${videoTitle}`}
className="group absolute inset-0 h-full w-full cursor-pointer"
>
<img

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/nextjs-no-img-element (warning)

Plain ships unoptimized, oversized images.

Fix → Use next/image so users get optimized formats, responsive srcsets, and lazy loading instead of oversized image downloads.

Docs

- platform detection via useSyncExternalStore (shared hook) instead of
  setState-in-effect, removing the mount flash the hydration rule flags
- next/link for internal links (nav logo, Docs link, quickstart link)
- next/image for the video poster (responsive srcset, lazy by default)
- DocsHardNav comment updated: landing->docs client nav is safe because
  globals.css loads on both routes; the guard covers docs->landing
- associate dialog labels with their controls (implicit wrap); read-only
  mock captions become spans instead of label elements
- hoist marquee list to module scope; stable keys without array index
- next/image for marquee logos and tweet avatars (unoptimized: 28px
  third-party favicons/avatars where proxy optimization adds fragility)

Skipped: no-giant-component on HeroDashboardMockup (pre-existing
structure; splitting it is a refactor beyond this PR).
@AgentWrapper

Copy link
Copy Markdown
Owner Author

React Doctor review addressed in commits 253dac2 + 7501416:

Flagged inline comments — fixed:

  • LandingNav.tsx hydration: platform detection now uses a shared useSyncExternalStore hook (lib/use-download-target.ts) instead of setState-in-effect; applied in nav, hero, final CTA, and quickstart.
  • LandingInstall.tsx nextjs-no-a-element: quickstart link now uses next/link (also nav logo + Docs links). Safe direction: globals.css loads on both routes; the docs->landing leak stays guarded by DocsHardNav (comment updated to document this).
  • LandingVideo.tsx nextjs-no-img-element: poster now next/image with responsive srcset.
  • LandingHero.tsx:1218: that element was removed in the earlier hero-simplification commit.

Remaining warnings cleared: dialog labels now implicitly wrap their controls (clicking a label focuses its input — verified), read-only mock captions are spans, marquee list hoisted to module scope, index-free keys, marquee logos + avatars use next/image (unoptimized — 28px third-party favicons/avatars where proxy optimization adds fragility, not speed).

Deliberately skipped: no-giant-component on HeroDashboardMockup — splitting the ~380-line interactive mockup is a refactor beyond this PR's scope.

Score: 65/100 (17 warnings) -> 96/100 (1 warning). All other checks green.

- drop 'one daemon' from the coverage meta row
- split the marquee into two rows (second row scrolls reverse)
- chip restyle: h-12, sans-serif name, subtle gradient, accent hover
Replaces the concept-art mockups (pinned GSAP scroll with hand-built DOM
facsimiles) with three Cursor/Codex-style alternating rows pairing tight
use-case copy with actual captures of the AO desktop app:

- New task dialog (kick off work: worktree + branch + session per task)
- the live session board (fleet status, PR + CI state per card)
- a session inspector (CI failing routed back to the owning session)

Captures taken from the real app (dev:web against a live daemon with a
demo dataset, no sensitive projects). Removes LandingFeaturesScroll and
the older unused LandingFeatures mockups.
…es shots

- primary CTAs switch from saturated blue fill to quiet ivory (blue stays
  for small accents: italic headline, eyebrows, links)
- nav shows the GitHub star chip at all widths (was hidden below 640px)
- features screenshots go full-width with a soft glow (were ~41% scale
  and unreadable); session shot recaptured with a real agent transcript
  showing AO's CI-failure message routed into the session
- TerminalPane web preview: fix invisible plain lines (text-terminal
  resolved to the terminal background color); AO nudge lines render in
  accent color
- quickstart step 2 is one direct action (gh auth login); step 3 shows
  how users actually work - telling the orchestrator what they need in
  plain words instead of running ao spawn
- drop the defensive 'No staged renders' framing
… TUI

- restore the alternating side layout; each screenshot is now cropped to
  its subject (New task dialog, board columns, session terminal + PR
  card) so the product UI is legible at display size
- demo terminal transcript rewritten to match the real Codex TUI:
  header box (model/directory/YOLO), Ran-blocks with transcript
  ellipsis, and AO's CI-failure nudge arriving in accent color
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants