Use when building a landing, pricing, or launch page: hero structure, section rhythm, social proof, scroll behavior, CTA hierarchy, and plan comparison tables.
A marketing page is read once by someone who did not ask to be there, which inverts most product-UI defaults: the animation budget goes up, the information density goes down, and the page proves one claim instead of exposing every capability. Default to a short page — one claim, one primary CTA repeated verbatim, evidence beside each promise rather than pooled at the bottom. The larger motion budget is an allowance, not a licence: anything that moves without the visitor causing it reads as the page performing at them while they are trying to decide. This skill builds one page inside a system it does not own — if the open question is which accent, typeface, illustration voice, or tone the page speaks in, that is brand-identity; here those are already decided and only arranged.
Detect the stack before writing a line. Read how the project already builds pages — framework and rendering mode (static export, ISR, server components), styling system (Tailwind, CSS Modules, custom properties, CSS-in-JS), the existing section and container components, and the animation library if one is present. Write the page in that system. A landing page is the most common place a parallel styling layer or a second animation library gets bolted on, and it is never justified: if the project ships CSS transitions, the hero does not import a motion library for one fade.
Quick Reference
Topic
File
Building or ordering a specific section — hero, logo wall, feature block, demo, testimonial, FAQ, final CTA, or an attached blog/changelog/docs surface. Open it when you know the page needs a section but not what belongs inside it.
section-catalog.md
Anything with a price on it: tier count, highlighted plan, annual/monthly toggle, feature comparison table, or a page that has to answer objections. Open it whenever the page shows money.
pricing-and-conversion.md
Core Principles
Motion still has to map to user input. No scroll-triggered fade-ups, no scroll hijacking, no auto-advancing carousel, no parallax that is not 1:1 with scroll position. Motion the visitor did not cause reads as a performance, and a self-advancing carousel moves the thing being read. Exception: a reveal scrubbed by scroll position — reversible, running backwards when you scroll up — is direct manipulation, not a trigger, and is allowed.
Spend the extra animation budget on one sequence, not on every section. Product UI stays under 300ms (Emil Kowalski's duration table, whose only "can be longer" row is marketing/explanatory). One hero or explanatory sequence may run out to Benji Taylor's published --duration-swift: 800ms / cubic-bezier(.175,.885,.32,1.275). Note the live disagreement: Benji's snappy and swift curves overshoot past 1, Emil's three all settle — pick one family for the project and never mix them (see motion/references/techniques.md). Exception: anything clickable stays under the product ceiling. A CTA that takes 800ms to acknowledge a press is broken on any page type.
The intro animation plays once per session. Gate it on sessionStorage, not localStorage — a genuinely new visit should see it, an internal navigation should not. The page animates in once and then stops moving. Exception: under prefers-reduced-motion: reduce, skip the intro entirely, first visit included; reduced motion means gentler, not delayed.
The hero says what it is, who it is for, and shows it working. One claim sentence, one qualifying sentence, one primary CTA, one secondary escape hatch (docs, demo, pricing), and one piece of evidence that is the actual product — not an abstract gradient blob. Cropping, framing, and loading of that evidence belong to imagery. Exception: a pre-launch or waitlist page with nothing to show — there the email field is the hero.
One primary CTA, same verb every time it appears. "Get started" in the nav and "Try it free" in the footer read as two different offers. Ship 1 visually primary action per viewport, repeats identical in wording and destination. CTAs also read auth state: logged out gets Get Started, logged in gets Go to Dashboard — telling a signed-in user to sign up is a dead end. Exception: the pricing page, where each tier card carries its own primary and the hierarchy moves to the highlighted tier.
Proof goes next to the claim it proves. A "trusted by" band at the bottom proves nothing about a feature described three screens above it. Attach the logo, quote, or number to the section making the claim. Exception: a first-viewport logo wall earns its place only when the logos are recognizable to this specific reader; otherwise it reads as filler and belongs below the first feature section.
Ship 5-7 sections and cut the eighth (house default). Each extra section dilutes the one claim and pushes the closing CTA further away. A capability that cannot earn a section belongs in docs. Exception: developer tools, where a code block plus its output often needs one section per concept.
Everything a crawler or screen reader needs is in the DOM at rest. Hover-revealed nav submenus are visually hidden with aria-expanded on the trigger, never conditionally mounted — mount-on-hover markup does not exist for a crawler and cannot be reached by a keyboard. Exception: a menu large enough to bloat first paint may lazy-mount, but only behind a real <button>, with its links duplicated in the footer.
Pre-render, preload, and lock the space. Content pages are statically generated with revalidation (export const revalidate = 3600), never fetched at request time; fonts and the above-the-fold hero image are preloaded; headings get text-wrap: balance so no title strands a single word. Exception: per-visitor content (the auth-aware CTA, a live counter) hydrates on the client over pre-rendered markup — it does not make the page a request-time render.
Decorative illustrations built from DOM elements need a name and no pointer surface. Give them role="img" with an aria-label, plus user-select: none and pointer-events: none, or they get selected mid-drag and announced as a pile of empty divs. Exception: an interactive illustration keeps its pointer events, and then owes a keyboard path too.
Smell / Fix
Smell
Fix
Sections fade up as they enter the viewport
Delete the observer. Render them visible; motion that fires on scroll fires on every scroll direction and fights the reader
Hero carousel rotating through three value props
You have three claims and therefore no claim. Pick one, demote the rest to feature sections
A wall of unfamiliar logos under a "Trusted by" caption
Replace with one named quote plus a number, or move it below the first feature section
localStorage guarding the intro animation
sessionStorage — the intro returns on a real new visit
Blog or changelog fetched at request time
Static generation plus revalidation; these change hourly at most
Webfont swaps in and the hero reflows
Preload the font file and declare a metric-matched fallback stack
Pricing table only readable by scrolling sideways on mobile
Reflow to one card per tier — see pricing-and-conversion.md
A motion library imported for one hero fade
Use the project's existing transitions; the library outweighs the effect
<div> with an onClick acting as the CTA
A real <a> or <button> — the CTA is the one element that must survive a crawler, a middle-click, and a keyboard
Output Format
When proposing or reviewing a page, emit a section manifest before any code — one row per section, in scroll order:
#
Section
The one claim it makes
Evidence on screen
CTA
1
Hero
Deploys in one command
12-second product recording
primary
2
Logo wall
Four teams you recognize already use it
6 marks, greyscale
none
3
Feature
Rollbacks are instant
Annotated screenshot of the rollback
inline link
A row with no claim is a section to cut. A row whose evidence reads "illustration" is a claim with no proof. Two primary CTAs with different wording is a defect, not a variant.
Checklist
One claim, stated in the hero in one sentence, with the product visible
5-7 sections, each with a claim and its own evidence
One primary CTA, identical wording and destination everywhere it repeats
CTA copy and href switch on auth state
No scroll-triggered reveals, scroll hijacking, non-1:1 parallax, or auto-advancing carousel
One curve family across the page; no clickable element animates over 300ms
Intro animation gated on sessionStorage and skipped under prefers-reduced-motion
Statically generated with revalidation; fonts and hero image preloaded; no layout shift
Nav submenu markup present in the DOM when closed, aria-expanded on the trigger
text-wrap: balance on headings; code-built illustrations have aria-label, user-select: none, pointer-events: none
Pricing, if present, reviewed against pricing-and-conversion.md
1---2name: marketing-pages3description: Use when building a landing, pricing, or launch page: hero structure, section rhythm, social proof, scroll behavior, CTA hierarchy, and plan comparison tables.4---567# Marketing Pages89A marketing page is read once by someone who did not ask to be there, which inverts most product-UI defaults: the animation budget goes up, the information density goes down, and the page proves one claim instead of exposing every capability. Default to a short page — one claim, one primary CTA repeated verbatim, evidence beside each promise rather than pooled at the bottom. The larger motion budget is an allowance, not a licence: anything that moves without the visitor causing it reads as the page performing at them while they are trying to decide. This skill builds one page inside a system it does not own — if the open question is which accent, typeface, illustration voice, or tone the page speaks in, that is `brand-identity`; here those are already decided and only arranged.1011**Detect the stack before writing a line.** Read how the project already builds pages — framework and rendering mode (static export, ISR, server components), styling system (Tailwind, CSS Modules, custom properties, CSS-in-JS), the existing section and container components, and the animation library if one is present. Write the page in that system. A landing page is the most common place a parallel styling layer or a second animation library gets bolted on, and it is never justified: if the project ships CSS transitions, the hero does not import a motion library for one fade.1213## Quick Reference1415| Topic | File |16| --- | --- |17| Building or ordering a specific section — hero, logo wall, feature block, demo, testimonial, FAQ, final CTA, or an attached blog/changelog/docs surface. Open it when you know the page needs a section but not what belongs inside it. | [section-catalog.md](references/section-catalog.md) |18| Anything with a price on it: tier count, highlighted plan, annual/monthly toggle, feature comparison table, or a page that has to answer objections. Open it whenever the page shows money. | [pricing-and-conversion.md](references/pricing-and-conversion.md) |1920## Core Principles21221. **Motion still has to map to user input.** No scroll-triggered fade-ups, no scroll hijacking, no auto-advancing carousel, no parallax that is not `1:1` with scroll position. Motion the visitor did not cause reads as a performance, and a self-advancing carousel moves the thing being read. *Exception:* a reveal scrubbed by scroll position — reversible, running backwards when you scroll up — is direct manipulation, not a trigger, and is allowed.232. **Spend the extra animation budget on one sequence, not on every section.** Product UI stays under `300ms` (Emil Kowalski's duration table, whose only "can be longer" row is marketing/explanatory). One hero or explanatory sequence may run out to Benji Taylor's published `--duration-swift: 800ms / cubic-bezier(.175,.885,.32,1.275)`. Note the live disagreement: Benji's `snappy` and `swift` curves overshoot past 1, Emil's three all settle — pick one family for the project and never mix them (see `motion/references/techniques.md`). *Exception:* anything clickable stays under the product ceiling. A CTA that takes 800ms to acknowledge a press is broken on any page type.243. **The intro animation plays once per session.** Gate it on `sessionStorage`, not `localStorage` — a genuinely new visit should see it, an internal navigation should not. The page animates in once and then stops moving. *Exception:* under `prefers-reduced-motion: reduce`, skip the intro entirely, first visit included; reduced motion means gentler, not delayed.254. **The hero says what it is, who it is for, and shows it working.** One claim sentence, one qualifying sentence, one primary CTA, one secondary escape hatch (docs, demo, pricing), and one piece of evidence that is the actual product — not an abstract gradient blob. Cropping, framing, and loading of that evidence belong to `imagery`. *Exception:* a pre-launch or waitlist page with nothing to show — there the email field is the hero.265. **One primary CTA, same verb every time it appears.** "Get started" in the nav and "Try it free" in the footer read as two different offers. Ship `1` visually primary action per viewport, repeats identical in wording and destination. CTAs also read auth state: logged out gets `Get Started`, logged in gets `Go to Dashboard` — telling a signed-in user to sign up is a dead end. *Exception:* the pricing page, where each tier card carries its own primary and the hierarchy moves to the highlighted tier.276. **Proof goes next to the claim it proves.** A "trusted by" band at the bottom proves nothing about a feature described three screens above it. Attach the logo, quote, or number to the section making the claim. *Exception:* a first-viewport logo wall earns its place only when the logos are recognizable to this specific reader; otherwise it reads as filler and belongs below the first feature section.287. **Ship `5-7` sections and cut the eighth** (house default). Each extra section dilutes the one claim and pushes the closing CTA further away. A capability that cannot earn a section belongs in docs. *Exception:* developer tools, where a code block plus its output often needs one section per concept.298. **Everything a crawler or screen reader needs is in the DOM at rest.** Hover-revealed nav submenus are visually hidden with `aria-expanded` on the trigger, never conditionally mounted — mount-on-hover markup does not exist for a crawler and cannot be reached by a keyboard. *Exception:* a menu large enough to bloat first paint may lazy-mount, but only behind a real `<button>`, with its links duplicated in the footer.309. **Pre-render, preload, and lock the space.** Content pages are statically generated with revalidation (`export const revalidate = 3600`), never fetched at request time; fonts and the above-the-fold hero image are preloaded; headings get `text-wrap: balance` so no title strands a single word. *Exception:* per-visitor content (the auth-aware CTA, a live counter) hydrates on the client over pre-rendered markup — it does not make the page a request-time render.3110. **Decorative illustrations built from DOM elements need a name and no pointer surface.** Give them `role="img"` with an `aria-label`, plus `user-select: none` and `pointer-events: none`, or they get selected mid-drag and announced as a pile of empty divs. *Exception:* an interactive illustration keeps its pointer events, and then owes a keyboard path too.3233## Smell / Fix3435| Smell | Fix |36| --- | --- |37| Sections fade up as they enter the viewport | Delete the observer. Render them visible; motion that fires on scroll fires on every scroll direction and fights the reader |38| Hero carousel rotating through three value props | You have three claims and therefore no claim. Pick one, demote the rest to feature sections |39| Nav says "Get started", hero says "Start free trial", footer says "Sign up" | One verb, one destination, repeated verbatim |40| A wall of unfamiliar logos under a "Trusted by" caption | Replace with one named quote plus a number, or move it below the first feature section |41| `localStorage` guarding the intro animation | `sessionStorage` — the intro returns on a real new visit |42| Blog or changelog fetched at request time | Static generation plus revalidation; these change hourly at most |43| Webfont swaps in and the hero reflows | Preload the font file and declare a metric-matched fallback stack |44| Pricing table only readable by scrolling sideways on mobile | Reflow to one card per tier — see [pricing-and-conversion.md](references/pricing-and-conversion.md) |45| A motion library imported for one hero fade | Use the project's existing transitions; the library outweighs the effect |46| `<div>` with an `onClick` acting as the CTA | A real `<a>` or `<button>` — the CTA is the one element that must survive a crawler, a middle-click, and a keyboard |4748## Output Format4950When proposing or reviewing a page, emit a section manifest before any code — one row per section, in scroll order:5152| # | Section | The one claim it makes | Evidence on screen | CTA |53| --- | --- | --- | --- | --- |54| 1 | Hero | Deploys in one command | 12-second product recording | primary |55| 2 | Logo wall | Four teams you recognize already use it | 6 marks, greyscale | none |56| 3 | Feature | Rollbacks are instant | Annotated screenshot of the rollback | inline link |5758A row with no claim is a section to cut. A row whose evidence reads "illustration" is a claim with no proof. Two primary CTAs with different wording is a defect, not a variant.5960## Checklist6162- [ ] One claim, stated in the hero in one sentence, with the product visible63- [ ] `5-7` sections, each with a claim and its own evidence64- [ ] One primary CTA, identical wording and destination everywhere it repeats65- [ ] CTA copy and href switch on auth state66- [ ] No scroll-triggered reveals, scroll hijacking, non-`1:1` parallax, or auto-advancing carousel67- [ ] One curve family across the page; no clickable element animates over `300ms`68- [ ] Intro animation gated on `sessionStorage` and skipped under `prefers-reduced-motion`69- [ ] Statically generated with revalidation; fonts and hero image preloaded; no layout shift70- [ ] Nav submenu markup present in the DOM when closed, `aria-expanded` on the trigger71- [ ] `text-wrap: balance` on headings; code-built illustrations have `aria-label`, `user-select: none`, `pointer-events: none`72- [ ] Pricing, if present, reviewed against [pricing-and-conversion.md](references/pricing-and-conversion.md)
Run npx skillmds@latest add agentsorg/marketing-pages in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Use when building a landing, pricing, or launch page: hero structure, section rhythm, social proof, scroll behavior, CTA hierarchy, and plan comparison tables. It is listed under Marketing & Growth on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
agentsorg (@agentsorg) published this skill. Their other Agent Skills are listed on their SkillMD profile.