Communitygithub.com

david-samurai/LandingPageSkill

Use when building, launching, or improving a marketing landing page, lead magnet, or funnel with Claude Code — triggers on "build me a landing page", "set up a landing page project", "how do I host and deploy this page", "give Claude my brand", "my landing page isn't converting", "add tracking to my page", or reviewing a live page's speed and funnel drop-off.

¿Qué es LandingPageSkill?

LandingPageSkill is a Claude Code agent skill that use when building, launching, or improving a marketing landing page, lead magnet, or funnel with Claude Code — triggers on "build me a landing page", "set up a landing page project", "how do I host and deploy this page", "give Claude my brand", "my landing page isn't converting", "add tracking to my page", or reviewing a live page's speed and funnel drop-off.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/david-samurai/LandingPageSkill/tree/main/landing-page-in-claude-code

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Building a landing page in Claude Code

A working setup for building, shipping and improving marketing pages with Claude Code. Five things do most of the work: a repo, a host, a brand kit, performance, and funnel data. Get those right and everything else is iteration.

Two ways to see the page before it ships (section 4): a local dev server for you and Claude, and Claude Design for anyone non-technical. If you use Design, read section 4's hard rule first — there is no undo there.

The through-line: the job doesn't finish at deployment. A page that's live and untracked is a page you can't improve.

Order of operations

Do these in order. Each one makes the next cheaper.

  1. Repo first — before any code. Version control is the undo button for everything else.
  2. Host + deploy pipeline second — while the site is trivial and a broken deploy costs nothing.
  3. Brand kit third — before writing a word of copy, so the first draft is already on-brand.
  4. Build the page — visual/static first, interactivity second, tracking last.
  5. Ship with minimal tracking on day one — then optimise speed and copy against real data.

1. Use a repo (GitHub or equivalent)

If you're already using Claude Code this is obvious. If you're only dipping a toe in, this is the warm-up: a repo gives you version control, a cloud backup, and — most importantly — a deployment strategy.

main is production and nothing lands there except through a pull request you merge. Put that rule in CLAUDE.md explicitly — see starters/CLAUDE.md.

The loop

This is the whole cycle. Run it for every piece of work, however small.

  1. Agree a version number. Claude recommends one, you agree it — or you just say which one you want. Either way the number is settled before any work starts, and the decision is yours, not Claude's.
  2. Claude creates the branch — git checkout -b v1.03.
  3. You do the work in the branch. Commits land there and nowhere else.
  4. Claude pushes the branch to GitHub.
  5. Claude opens the pull request.
  6. You review and approve it in GitHub, and you merge it. This is the deploy. It is the only moment production changes, and it is always a human decision.
  7. git checkout main then git pull. Do not skip this. Your local main is now behind by exactly one merge, and starting the next branch from a stale main is how you get divergence, phantom conflicts and a git pull that refuses to fast-forward.
  8. Repeat from step 1 with the next version number.

Claude proposes, you decide, Claude executes. Version numbers, merges and deploys are yours; branching, pushing and raising the PR are Claude's. If a call is ambiguous, Claude asks.

Version naming that works: v1.0x for patches (copy, config, small fixes), v1.x for minor work (a new page, a new feature), v2.x for a redesign.

Two review gates worth keeping:

  • Review the whole branch diff before merging, not just each commit. Individually fine commits can combine into a real bug. A full "read everything since the branch point" pass — ideally by a second reviewer or a fresh agent — catches what per-task review structurally cannot.
  • Run a security review before any deploy that collects user data. One review pass on a form-handling branch caught a real vulnerability where a raw object spread let a visitor submit values for server-managed fields. Treat it as a gate, not a nicety.

2. Host it somewhere with a real deploy pipeline

AWS Amplify works well: a free tier that covers a low-traffic landing page, and a small bill beyond it. Check current terms — AWS restructured its free tier in 2025. Netlify, Vercel and Cloudflare Pages give you the same shape.

The real win is the deploy path: merge a PR, the site rebuilds and goes live.

Connecting the repo to the host is the step people stall on, and it's a click-path, not a config file: in the host's console, create a new web app → authorise it against your GitHub account → pick the repo and the main branch → it detects your build spec → first deploy runs. From then on it rebuilds on every push to that branch. Do this while the site is a single "hello" page, so a broken pipeline costs you nothing to debug.

Set up on day one, while it's cheap:

  • Auto-deploy from main.
  • A custom domain with HTTPS.
  • A billing alarm. You've just put a card against a cloud account. Set a budget alert at a number that would surprise you — takes two minutes, and it converts a low-probability nasty surprise into an email.
  • Security headers — static hosts ship with none by default.
  • Long-cache Cache-Control on content-hashed build assets. Easy, permanent, and otherwise defers forever because it never blocks anything.

Domain and DNS, where the traps are predictable:

  • A bare domain can't use a CNAME — www.example.com can, example.com can't. You need your DNS provider's ALIAS/ANAME record or the host's own apex option. Decide early whether your canonical URL has the www, and redirect the other to it.
  • The HTTPS certificate needs a DNS record to validate and won't issue until that record resolves. Give any DNS change a few hours before deciding it's wrong — propagation delay looks exactly like failure.

Deploy traps that cost real time:

  • Know exactly which parts auto-deploy and which don't. If any piece of your stack (a serverless function, a backend, a worker) deploys by a separate manual command, write that in CLAUDE.md in capital letters. The classic silent failure is merging a branch where the visible site updates, the backend doesn't, and everything looks fine.
  • Auto-deploy removes your last checkpoint. With merge-to-deploy, the PR review is the gate. Verification has to happen before the merge, not after.
  • npm ci on the build host is stricter than your local npm install. A lockfile subtly out of sync with package.json installs fine locally on a newer npm and fails the build on the host's older one. Build fails on the host but not locally? Suspect the lockfile first.
  • Pin your runtime in the build spec, not just in a version file. A .nvmrc alone isn't reliably honoured — invoke the version manager in the build commands too.
  • Every new environment variable needs adding in the host's console, separately from the code that reads it. This is a surprisingly frequent "why is it broken" answer.
  • Content-Security-Policy is the header that will bite you. Every third-party origin your page actually talks to — analytics, tag manager, pixels, fonts, form endpoints — must be allowlisted, in the right directive, or it's silently blocked in production while working perfectly in local dev. Symptom: "tracking works locally, fires nothing live." Check the browser console for CSP violations before debugging anything else.
  • Verify against the deployed artifact, not the source file. Confirm a fix by inspecting the real production response (curl -I, browser dev tools), not by reading the config that was supposed to produce it. Same for "did my change actually deploy" — check the build ID/timestamp, not just that the merge happened.

How the form actually submits

Static hosting has no backend. A plain <form> on a static page does nothing useful — this surprises people on day one, and it's the whole point of the page. Three realistic options:

OptionGood whenWatch out for
A hosted form serviceYou want it working this afternoonMonthly cost per volume; their branding; your data lives with them
A serverless function (Lambda, Netlify/Cloudflare Functions)You want control and near-zero costYou now own validation, spam and CORS
Your CRM's embedded form or webhookThe lead needs to land in a CRM anywayEmbed weight and styling limits; often slow to load

Whichever you pick:

  • CORS will be your first error. A serverless endpoint on a different origin to your page must explicitly allowlist that origin, or the browser blocks the request before it is ever sent. Add localhost to the allowlist too, or you can't test locally.
  • Add a honeypot field (a hidden input that humans never fill and bots do) and reject anything that fills it. Cheapest spam filter that exists.
  • Never spread a raw request body straight into your database write. That's how a visitor ends up setting fields you meant to control server-side. Pick out the fields you want, explicitly.
  • Keep the endpoint warm if you can. A serverless function that cold-starts makes the single most important moment on the page — hitting submit — feel broken.

3. Give Claude a brand kit — and force it to load

This is the highest-leverage thing in the list. At minimum the kit holds:

your offer · your target market / client profile · your messaging strategy · your colours · your fonts · your logo

Put it in a folder (brand/). Template: starters/brand-kit/brand.md.

Then make it load automatically. An instruction in CLAUDE.md saying "read the brand kit" is advisory — it gets followed inconsistently. A SessionStart hook that cats the files into context is not optional and does not get skipped. That single change is the difference between "sometimes on-brand" and "on-brand by default." See starters/settings.json.

Load at session start: the brand kit, a short architecture doc (how the site is built, hosted, deployed), and the most recent session log.

Structuring it well:

  • Split "how the brand looks" from "how the brand talks." Keep the always-on file lean — palette, fonts, logos, offer, audience. Point to deeper voice/messaging material as "read this when doing copy work." Everything auto-loaded costs context on every session, forever.
  • Give colours roles, not just hex codes ("primary accent — used for the main CTA"). Roles are what stop Claude inventing a colour when it needs one. State the rule plainly: no colour outside the kit appears anywhere. Off-brand defaults from templates and generators slip in silently otherwise.
  • Two or three before/after tone examples teach voice faster than any list of adjectives.
  • If your messaging is commercially sensitive, gitignore it but still reference it from CLAUDE.md — you get consistent loading without publishing strategy or pricing to a repo.
  • Externally-synced brand docs go stale. If a voice or audience document is copied from a shared drive, re-verify it against its source before a copy pass — marketing decisions get made in conversations that never make it back into the doc.

Copy discipline the brand kit should enforce:

  • Never promise "no signup / no email required" on a page whose job is capturing an email. It reads as friction-reducing right up until the form appears, and then it's a contradiction at the exact moment you need trust. Reassure on time, cost and payoff instead — "2 minutes · free · your result emailed straight away."
  • Re-audit reassurance microcopy whenever the offer changes. It gets copied between page variants and outlives the offer it was written for, precisely because it sounds helpful.
  • The ad's promise, the page's promise, and the form's actual ask must all agree. A mismatch shows up as drop-off at the step where the truth arrives, not the step where the mismatch was introduced. When a step leaks, suspect the step before it.

4. See it before you ship it

Two ways to look at a page without deploying it. Use both — they're for different people.

Local dev server

For you and Claude, mid-build. Claude can start the dev server, drive a real browser, screenshot the result, and read the console and network logs — so "does this render correctly" is answered by looking, not by inspecting code.

  • Never run two dev servers for the same project at once. Check for an existing process first and kill it before starting another — especially if parallel agents might each spin one up.
  • Cap automated retry loops at ~3 attempts. An open-ended "keep reloading and trying different timing until it works" loop wrapped around a dev server plus browser automation is a genuine resource-exhaustion risk, not just an annoyance — it has crashed a machine outright.
  • Verify cleanup rather than trusting it. "I stopped the server and closed the tabs" is an unverified claim like any other — check the process list.
  • Expect local to differ from production by design. Anything gated behind a real analytics ID or a live API endpoint is typically a no-op locally. That's expected behaviour, not a bug — document it so it isn't re-diagnosed every few weeks.
  • Keep your end-to-end tests pointed at localhost by default, with pointing them at the real deployed URL a deliberate, separate act — otherwise a routine test run performs a real submission against production.

Claude Design (claude.ai/design)

For everyone else. Claude can push a page into a Claude Design project, giving you a shareable URL where a client, a designer or a non-technical partner can edit copy and layout visually in the browser with zero local setup. Excellent for sign-off before a page gets wired into the real site.

The one hard rule: never blind-write to Design

Before writing anything into a Claude Design project, Claude must fetch the current remote version, diff it, and check with you before overwriting. Every time.

There is no version history, no undo and no trash on the Design side — a canvas file is more fragile than an untracked local one. A blind overwrite of a collaborator's edits is permanently unrecoverable, and it has already cost a full evening of hand-written copy.

  • Author the page as self-contained static HTML/CSS/JS. The Design preview sandbox runs static files — it can't execute your bundler.
  • Decide direction of ownership per page and write it down. While a human is editing in the canvas, that direction is authoritative and one-way (canvas → code), and automated pushes to it stop. Put the rule in a comment at the top of the file and in CLAUDE.md, not just in a conversation.
  • Don't copy drag-to-resize output back into your codebase. Visual canvas edits bake in absolute pixel values that looked right at one width. Take the intent, re-implement it as responsive CSS.
  • Design is never the deploy target. Reconcile into the repo, commit, deploy normally.

5. Optimise for performance

If your page is slow, people bounce. If it breaks in a social app's in-app browser, you get no leads at all — and you won't see it happening. Once the site is live, tools like pagespeed.dev and Lighthouse show you where the blind spots are.

Three numbers matter, industry-wide: LCP (how fast the biggest visible thing paints), INP (how fast the page responds to a tap — almost always a JavaScript problem), CLS (whether things jump around while loading).

The rules that do most of the work. Apply these while building — they're cheap up front and expensive to retrofit:

  • Self-host your fonts (.woff2 + local @font-face) instead of loading them from a font CDN. A CDN setup chains two separate servers before a single letter appears, and it blocks rendering the whole time. Set font-display: swap so text shows immediately in a fallback, and only ship the weights you actually use.
  • Inline the critical first-paint CSS — background colour, basic layout — as the very first thing in <head>, with the colour hardcoded. CSS variables aren't resolved that early.
  • defer every non-critical script, and keep tracking scripts out of the top of <head>. Note that async/defer stops a script blocking parsing but it still competes for bandwidth and main-thread time while your page is trying to paint.
  • Set explicit width/height (or aspect-ratio) on every image, serve them at the size they actually display, and lazy-load anything below the fold. This is most of CLS, solved.
  • Fewer connections beats fewer bytes on a slow phone. Every separate file or server the page fetches pays its own setup cost — DNS, connection, TLS — before any content arrives. Bundling CSS/JS at build time and consolidating requests is usually a bigger win than shaving kilobytes off individual files. Same reason to avoid redirect chains: each one is a full extra round-trip before the real page starts loading.
  • Long-cache, immutable Cache-Control on content-hashed assets.
  • Wrap rendering in an error boundary or fallback. Without one, a JavaScript error while drawing the screen gives the visitor a blank page — with no error shown and no analytics recorded, indistinguishable from someone who never arrived.
  • If it's a multi-step flow, persist progress to sessionStorage. In-app browsers reload the page when someone switches apps, silently wiping anything held only in memory.

How to think about it:

  • Lab tools test the wrong environment for social ad traffic. PageSpeed, Lighthouse and browser-automation tools all run in a normal browser. If your traffic arrives from a tap inside Instagram, Facebook or TikTok, it renders in that app's embedded in-app browser — a materially more restricted environment that can be dramatically worse on the identical page. The only real test is tapping your actual link from inside the app and staying in-app. Typing the URL into your phone's normal browser gives a false pass. Budget real time for this: there's no visible dev console in there.
  • Ship your own real-user timing from day one rather than inferring from lab scores. A great score on a fresh URL has zero real-user data behind it.
  • Segment analytics by browser. In-app browsers disguise themselves as ordinary mobile browsers in reports. Splitting session duration and bounce rate by browser is a cheap, decisive diagnostic — a cohort bouncing at 95% with a sub-second average session is not a content problem.
  • A fast First Contentful Paint can hide a slow page. A static shell paints instantly while the real content waits on a JS bundle. The gap between FCP and LCP is essentially "time to app mount."
  • Compression only helps download time, not execution time. The phone still parses and runs the full uncompressed code. The only lever there is shipping less of it.
  • Triage against the funnel, not the score. A mediocre LCP is not worth fixing twice while the first screen converts nobody. Fix the biggest funnel problem first.
  • A performance fix on one page does not apply to the next page you build. Re-check fonts, image sizing, caching and headers explicitly every time. Fixed problems silently reappear on fresh pages, and nothing points back at the earlier fix.

6. Collect as much funnel drop-off data as you can

The job doesn't finish at deployment. To improve your marketing you need to know where people leave — are they reading, scrolling, staying? Do you need to change the copy, or does the message not match the ad?

GA4 does an OK job and Claude can place the tags for you. Microsoft Clarity gives you more: session recordings and heatmaps, free, and it answers "what were they actually doing" in a way event counts never will. Plan: starters/funnel-tracking-plan.md.

Instrument every step, not just start and finish. A funnel showing near-zero completions looks identical whether it's a broken pipeline or a wrong offer — and you cannot tell which without per-step data. Knowing which screen someone abandoned on is the difference between a week of guessing and an afternoon of fixing.

Hard-won lessons:

  • A conversion event firing is not proof of a real lead. Your own smoke tests and your own submissions generate identical-looking events. Cross-check the actual identity — the email, the contact record in your CRM or database — before quoting any conversion number, and exclude your own testing explicitly rather than folding it in. This is the single easiest number in marketing to get wrong.
  • Measure arrivals, not departures. A click event fired as the browser navigates away races the navigation and gets lost on nearly every real departure. Fire the event on the destination page instead — arrival is far harder to lose.
  • Never tie an event to a hardcoded step number. Reorder the funnel and the event silently starts counting something else, with no error. Derive it from one canonical step-order definition. Same for saved client-side progress: version it against step order, or returning visitors land on the wrong screen after a deploy.
  • Fixing a drop-off often just moves it. Removing an intro screen relocated a 90% cliff from "tap Start" onto "answer question 1" — which proved the problem was the nature of the first ask, not the screen. Always re-measure after a fix.
  • Make the first step factual, not reflective. "How many staff do you have" costs nothing. "What's your biggest challenge" asks someone to evaluate their own life before they've committed to anything. Put sensitive questions (revenue, budget) later, after you've delivered some value, sitting alongside other contact fields where they read as ordinary.
  • Segment out bot and crawler traffic before drawing conclusions, and be aware some "sessions" from social platforms are automated link-preview fetches, not humans.
  • Compare the ad's literal words against the literal first thing a visitor sees. They get built and reviewed separately and drift apart without anyone noticing. This costs five minutes and no dashboard will surface it.

The habits underneath all of it

  • Write a session log at the end of every session — one file per day, appended to, auto-loaded at the next session's start. What changed, what deployed, what broke, what you learned, and what's next with the exact resume commands. It's how the next session starts informed instead of starting over. Log the mistakes honestly, not just what shipped — that's what stops them recurring.
  • Plan, get the plan reviewed, then build. Treat "plan approved" and "code written" as separate gates. Fixing a wrong assumption in a document is far cheaper than in tested code.
  • Verify by executing. Docs, --help output and valid syntax are not proof something works. Only running the real thing end to end is.

Starter files

FileWhat it's for
starters/CLAUDE.mdProject instructions template
starters/settings.jsonSessionStart hook that force-loads your brand kit
starters/brand-kit/brand.mdBrand kit template
starters/funnel-tracking-plan.mdEvent plan — fill in before writing tracking code
starters/launch-checklist.mdPre-launch and post-launch verification

Consent, privacy and the boring legal bit

Not legal advice, and this varies by where your visitors are — but a public playbook shouldn't stay silent on it. If you're collecting email addresses and running analytics and ad pixels:

  • Link a privacy policy from the form — what you collect, why, who you share it with. Ad platforms increasingly require one to run traffic at all.
  • UK or EU visitors mean consent handling before analytics and pixels fire, not after. GA4 and the major ad platforms have a consent mode for this; wire it up rather than hoping.
  • Say what happens next when someone hands over an email, and make unsubscribing easy.

Skills relacionados