CU-10: Landing page + marketing + static pages + mobile responsiveness
Priority: P1 Accounts/sessions: None — fully anonymous, read-only. The browser must NOT be logged into Calendo for the landing-page steps (see Preconditions). Parallel-safe: Yes — pure read-only, zero writes to any account or database. Safe to run concurrently with every other suite. Exclusive (rewrites global host availability?): No. Estimated time: 15 minutes. L3 reality checks: None — this suite touches no calendars and sends no email. There is nothing external to verify.
Goal
This suite proves that an anonymous visitor — a prospective customer who has never heard of Calendo — gets a working, professional first impression. It verifies that the marketing landing page (https://calendo.dev/) renders its AI-focused hero, all six feature cards, the pricing section, and the primary call-to-action buttons; that every navigation and footer link resolves to a real page (no 404, no broken anchor); that the Privacy, Terms, and Docs pages render; that the Log In and Register pages render with their forms; that the browser console is free of errors; and that the entire experience is usable on a 375px-wide phone (hamburger menu works, no horizontal overflow, tap targets are reachable). This is the top of the funnel — if it is broken or ugly, no one signs up, so it is a launch-critical surface.
Preconditions
- No active Calendo session in this browser tab. The landing page (
/) runs a script on load that callsGET /api/auth/me; if a valid session exists it immediatelywindow.location.replace('/dashboard/'), so a logged-in agent would never see the marketing page. Before starting, openhttps://calendo.dev/and confirm you land on the marketing page (hero heading visible), NOT the dashboard. If you are redirected to/dashboard/, you are logged in — open a fresh incognito/private browser context (or clear thesessioncookie forcalendo.dev) and retry. If you cannot get an anonymous context, FLAG this as a precondition failure and stop — do not attempt to log out of P1, and do not improvise, because logging out could disrupt other suites that depend on the persisted P1 session. - No baseline host availability, event types, or data are required — this suite reads only static, public pages.
- OAuth buttons on the auth pages are conditionally shown based on
GET /api/config. In production both Google and Microsoft are configured, so the buttons are expected to be visible; if/api/configreturns no OAuth providers the buttons are hidden by design (not a failure) — note it but do not fail the run on it. - See
00-setup-preconditions.mdfor the shared environment and session model. This suite is the one suite that REQUIRES the absence of a session rather than its presence.
Test data
- RUNID: pick a fresh UTC token at execution time, e.g.
20260601-1530. This suite creates NO data (no accounts, bookings, event types, forms, or emails), so RUNID is used ONLY to name the screenshot/evidence files (e.g.cu10-<RUNID>-landing-desktop.png) so reruns do not overwrite prior evidence. Do NOT type RUNID into any form field — submitting the register form is explicitly out of scope (see Steps 16–17). - No emails, slugs, or accounts are created.
Steps
Order note: do the desktop pass (Steps 1–18) first at a normal desktop viewport (≥1280px wide), then switch to the 375px mobile viewport for Steps 19–24. Keep the browser devtools Console open from Step 1 onward so console errors are caught across the whole run (Step 18 reviews them).
- Action: Open the browser devtools Console and clear it, then navigate to
https://calendo.dev/at a desktop viewport of at least 1280×800. Expect: The marketing landing page loads (NOT the dashboard). The page tab title is "Calendo - Smart Scheduling, Powered by AI". The sticky header (header.header) shows the Calendo logo with icon (a.logo) at top-left. [L1]
- Action: Read the hero section (
section.hero). Expect: The heroh1reads "Your scheduling. An AI assistant for your invitees." with "AI assistant" rendered in blue (span.highlight). The subtitle (p.subtitle) mentions "Stop emailing back and forth" and contains an underlined "Always free" link. Two hero CTA buttons are visible (.hero-ctas): a blue "Get Started Free" (a.btn.btn-primary, href/auth/register.html) and an outlined "See Features" (a.btn.btn-outline, href#features). Below them the fine print reads "No credit card needed. Set up in under 2 minutes." Capture screenshot:cu10-<RUNID>-hero-desktop. [L1]
- Action: Scroll to the Features section (
section.features#features). Expect: Section label "Features", title "Everything you need to schedule smarter". The features grid (.features-grid) shows exactly SIX feature cards (.feature-card), each with an icon, anh3, and a paragraph. Verify each title is present, in order: (1) "AI-Powered Booking", (2) "Calendar Sync + Conflict Detection", (3) "Team Scheduling", (4) "Payments & Coupons", (5) "Email Sequences", (6) "Analytics & Export". Capture screenshot:cu10-<RUNID>-features-desktop. [L1]
- Action: Scroll to the How It Works section (
section.how-it-works#how-it-works). Expect: Section label "How It Works", title "Up and running in 3 steps", and exactly THREE numbered steps (.step): "Create your account", "Share your link", "Get booked". [L1]
- Action: Scroll to the Pricing section (
section.pricing#pricing). Expect: Section label "Pricing", title "Simple pricing. No surprises." The pricing grid (.pricing-grid) shows exactly TWO plan cards: a "Free" card (.pricing-card.popular) carrying a "Most Popular" badge (.popular-badge), price "$0", with a feature list and a blue "Get Started Free" button (href/auth/register.html); and a "Pro" card with price "$2/mo" and an "Upgrade to Pro" button (a.btn.btn-outline, href/dashboard/?tab=settings). Below the grid is the line "Core scheduling costs us fractions of a penny per user. We pass those savings to you." Capture screenshot:cu10-<RUNID>-pricing-desktop. [L1]
- Action: Scroll to the "Why it's free" section (
section.open-source#why-free). Expect: Title "Scheduling costs pennies to run. We charge accordingly." and a "Get Started Free" button (a.btn-github, href/auth/register.html). [L1]
- Action: Scroll to the footer (
footer.footer). Expect: Footer shows the "Calendo" wordmark and the line "Made with care by Ravi", plus a footer-links nav (.footer-links) with five links: "Docs" (/docs), "Log In" (/auth/login.html), "Sign Up" (/auth/register.html), "Privacy" (/privacy), "Terms" (/terms). Capture screenshot:cu10-<RUNID>-footer-desktop. [L1]
- Action: In the header nav, click "Features" (
nav.nav-links a[href="#features"]). Expect: The page smooth-scrolls to the Features section; the URL becomeshttps://calendo.dev/#features; no navigation/404 occurs. [L1]
- Action: In the header nav, click "Pricing" (
a[href="#pricing"]). Expect: The page scrolls to the Pricing section; URL becomes.../#pricing; no 404. [L1]
- Action: In the header nav, click "Docs" (
a[href="/docs/"]). Expect: Navigates tohttps://calendo.dev/docs/. The API documentation page renders: tab title "Calendo API Documentation", a left sidebar (aside.sidebar) with "API Docs" logo and a "v1" badge, sidebar sections "Getting Started"/"Endpoints"/"Reference"/"Guides", and a main heading "Calendo API" (h1#introduction). No 404. Capture screenshot:cu10-<RUNID>-docs-desktop. [L2]
- Action: On the Docs page, click an endpoint card header (e.g. the first one,
/api/auth/register) and then click a sidebar anchor such as "Bookings" (a.sidebar-link[href="#bookings"]). Expect: The endpoint card expands/collapses on click, and the sidebar anchor scrolls to the matchingh2(e.g.h2#bookings). This confirms the docs page is interactive, not a broken shell. [L1]
- Action: From the Docs sidebar "Guides" section, click "Embed Widget" (
a.sidebar-link[href="/docs/embed.html"]). Expect: Navigates tohttps://calendo.dev/docs/embed.htmland a guide page renders (no 404, content visible). Then click the "Back to Calendo" link (a.sidebar-back, href/) — but since clicking/while anonymous returns to the landing page, expect to be back onhttps://calendo.dev/showing the hero. [L2]
- Action: Navigate to the footer "Privacy" link by going to
https://calendo.dev/privacy(clean URL, no.html). Expect: The Privacy Policy page renders: tab title "Privacy Policy - Calendo",h1"Privacy Policy", an "Last updated: May 2026" line, a green summary box starting "The short version:", and section headings including "What We Collect", "How We Use Google Calendar Data", and "How We Use Microsoft Calendar Data". HTTP status is 200 (page content present, not a 404 page). Capture screenshot:cu10-<RUNID>-privacy-desktop. [L2]
- Action: Navigate to
https://calendo.dev/terms(clean URL). Expect: Terms of Service page renders: tab title "Terms of Service - Calendo",h1"Terms of Service", "Last updated: April 2026" line, a blue summary box "The short version:", and section headings including "Acceptable Use", "Free and Paid Tiers", and "Limitation of Liability". The "Privacy Policy" inline link (a[href="/privacy"]) is present. No 404. Capture screenshot:cu10-<RUNID>-terms-desktop. [L2]
- Action: Confirm both clean-URL and
.html-suffixed forms work by also loadinghttps://calendo.dev/docs(no trailing slash) andhttps://calendo.dev/privacy.html. Expect:https://calendo.dev/docsresolves to the docs index (footer uses/docs; nav uses/docs/— both must work), andhttps://calendo.dev/privacy.htmlrenders the same Privacy page. Neither returns a 404. (Ifhttps://calendo.dev/docswithout the slash returns a 404 while/docs/works, FLAG it — the footer link is broken.) [L2]
- Action: Navigate to
https://calendo.dev/auth/login.html. Expect: Login page renders: tab title "Login - Calendo", Calendo logo linking home, a card withh1"Welcome back" and subtitle "Sign in to your account". Below it, OAuth buttons "Sign in with Google" (a.oauth-google, href/api/auth/oauth/google) and "Sign in with Microsoft" (a.oauth-microsoft, href/api/auth/oauth/microsoft), an "or" divider, then an email field (#email), a password field (#password), a "Forgot your password?" link (/auth/reset-password.html), and a blue "Sign in" submit button (#submitBtn). A footer link "Sign up" points to/auth/register.html. DO NOT type credentials or submit — rendering only. Capture screenshot:cu10-<RUNID>-login-desktop. [L1]
- Action: Navigate to
https://calendo.dev/auth/register.html. Expect: Register page renders: tab title "Sign Up - Calendo",h1"Create your account", subtitle "Start scheduling in under a minute", "Sign up with Google"/"Sign up with Microsoft" OAuth buttons, an "or" divider, and a form with Full name (#name), Email (#email), and Password (#password, hint "Must be at least 8 characters") fields plus a "Create account" submit button (#submitBtn). A footer link "Sign in" points to/auth/login.html. DO NOT fill or submit the form — creating an account is out of scope for this suite. Capture screenshot:cu10-<RUNID>-register-desktop. [L1]
- Action: Review the browser devtools Console for the entire desktop pass (Steps 1–17). Expect: No uncaught JavaScript errors and no failed-resource errors (no red console entries, no 404/500 network errors for page assets such as
/calendo-logo-256.png,/favicon-32.png, or the OAuth-configGET /api/configcall). Benign informational logs are acceptable. Record the exact text of any console error you see. Capture screenshot:cu10-<RUNID>-console-desktop(devtools Console panel). [L1]
- Action: Switch the browser to a mobile viewport of 375×812 (emulate iPhone width) and reload
https://calendo.dev/. Expect: The page reflows to a single-column mobile layout. The desktop nav links ("Features"/"Pricing"/"Docs") collapse (.nav-link-desktophidden) and a hamburger menu button (button.mobile-menu-btn) appears at top-right. Capture screenshot:cu10-<RUNID>-landing-mobile. [L1]
- Action: Verify there is no horizontal overflow on mobile: attempt to scroll the page horizontally and inspect the document width. Expect: The page does not scroll sideways; content fits within 375px (no element bleeds past the right edge). The hero
h1is reduced in size and remains fully readable. [L1]
- Action: Tap the hamburger button (
button.mobile-menu-btn). Expect: The mobile nav drawer (nav#mobile-nav.mobile-nav) opens (gains classopen), showing stacked full-width links: "Features", "How It Works", "Pricing", "Docs", "Log In", "Sign Up". The button'saria-expandedflips totrue. Capture screenshot:cu10-<RUNID>-mobile-menu-open. [L1]
- Action: In the open mobile drawer, tap "Docs" (
#mobile-nav a[href="/docs/"]). Expect: Navigates tohttps://calendo.dev/docs/. On mobile the docs sidebar is hidden by default and a floating menu button (button#mobile-menu-btn, the ☰ FAB bottom-right) is present; tapping it slides the sidebar in (.sidebar.open) over an overlay. Confirm the docs content is readable in a single column with no horizontal overflow. Capture screenshot:cu10-<RUNID>-docs-mobile. [L1]
- Action: Return to
https://calendo.dev/on mobile and scroll through Features, Pricing, and the footer. Expect: Feature cards stack one per column (.features-grid→ single column), pricing cards stack vertically and the "Most Popular" card no longer scales up (transform: none), and the footer stacks/centers (.footer-innercolumn,.footer-linkscentered). All footer links remain tappable with adequate spacing (each ≥ ~36px tall). Capture screenshot:cu10-<RUNID>-footer-mobile. [L1]
- Action: On mobile, load
https://calendo.dev/auth/login.htmlandhttps://calendo.dev/auth/register.html. Expect: Both auth cards are centered, fit within 375px with no horizontal overflow, and all inputs and buttons are full-width and tappable. Re-check the Console: no new errors introduced on mobile. Capture screenshot:cu10-<RUNID>-login-mobile. [L1]
L3 reality checks
None — this suite performs no bookings, sends no email, and touches no Google/Outlook calendar. There is nothing in external reality to confirm. Pass/fail is determined entirely by in-page rendering and the absence of console errors (see Pass/Fail criteria).
Cleanup
Nothing to clean up — this suite creates zero data (no account, no booking, no event type, no form, no poll, no email, no calendar event). Do NOT submit the register or login forms; if you accidentally did, FLAG it for the human (a throwaway account may have been created under whatever email you typed) rather than attempting to delete it yourself. Close the incognito/private context used for the anonymous pass so the persisted P1 session is untouched for other suites.
Pass/Fail criteria
The run PASSES only if ALL of the following are true:
- The landing page loads anonymously (no redirect to
/dashboard/) with the correct hero heading "Your scheduling. An AI assistant for your invitees." - Exactly six feature cards render with the six expected titles, in order.
- The pricing section renders both the Free ($0, "Most Popular") and Pro ($2/mo) cards with working CTA buttons.
- All header nav anchors (Features, Pricing) scroll correctly, and "Docs" navigates to a rendered docs page.
- All five footer links resolve to rendered pages (no 404): Docs, Log In, Sign Up, Privacy, Terms.
- Privacy (
/privacy), Terms (/terms), and Docs (/docs/AND/docs) all render with their expected headings and return 200 (not the 404/"Not found" page). - Login (
/auth/login.html) and Register (/auth/register.html) pages render with their forms and (in production) OAuth buttons. - The browser console shows no uncaught JS errors and no failed page-asset/network requests across the desktop and mobile passes.
- At 375px width: the hamburger button appears, the mobile drawer opens with the stacked links, there is no horizontal overflow, and feature/pricing/footer sections stack into a usable single-column layout.
The run FAILS if any page returns a 404, any expected element/text is missing, any console error appears, or the mobile layout overflows horizontally or leaves the hamburger non-functional.
Evidence to capture
- Screenshots (named with RUNID):
cu10-<RUNID>-hero-desktop,-features-desktop,-pricing-desktop,-footer-desktop,-docs-desktop,-privacy-desktop,-terms-desktop,-login-desktop,-register-desktop,-console-desktop,-landing-mobile,-mobile-menu-open,-docs-mobile,-footer-mobile,-login-mobile. - A written note recording: the verbatim text of any console error (or "none"); the HTTP status / render result for
/privacy,/terms,/docs,/docs/; whether OAuth buttons were visible on the auth pages; and a yes/no for "no horizontal overflow at 375px". - The exact list of the six feature-card titles and the two pricing plan names observed, to confirm against the expected set.
Manual residue / cannot-verify
- Visual/aesthetic quality (font rendering, color fidelity, image sharpness of the logo, overall "looks professional") is subjective — the agent can confirm elements are present but the human should eyeball the captured screenshots for polish.
- SEO/meta correctness (the
<meta name="description">, Open Graph/social-share preview, favicon and apple-touch-icon actually appearing in the OS/browser tab and on social cards) cannot be fully verified in-browser — hand to the human. - Real OAuth login flows (clicking "Sign in with Google"/"Microsoft" and completing consent) are intentionally NOT exercised here; cold OAuth login is forbidden in this environment and is covered by the auth suites.
- Cross-browser/real-device rendering (actual Safari on a physical iPhone, Android Chrome) is out of scope; this run uses one emulated viewport.
- The
/docsno-trailing-slash clean URL depends on Cloudflare static-asset routing; if it 404s while/docs/works, that is a real footer-link bug to surface to the human rather than something the agent can fix.