The Static Landing Page Playbook: From Idea to Deploy
Most indie products fail before anyone sees a landing page. Not because the idea is bad, but because founders spend weeks on authentication, dashboards, and billing before they have proof that strangers care. A static landing page flips that order. You ship a single HTML file (or a small folder of files), put it on a free host, and learn whether the problem and offer resonate. This playbook walks you through that path end to end—no framework churn, no premature SaaS architecture.
Static does not mean amateur. Stripe, Linear, and plenty of YC companies launched on simple pages with a headline, three bullets, and an email field. The constraint is the feature: you are building a decision surface, not a product. Every section below maps to a decision you can make in an afternoon and ship the same week.
Phase 1: Clarify the bet before you open an editor
Start with one sentence: who hurts, what they do today, and what changes after your product exists. Example: "Solo founders waste hours wiring waitlist forms; they need a deploy-ready static page with working signup in under ten minutes." If you cannot write that without jargon, the page will confuse visitors too. Write the sentence on paper. Sleep on it. That sentence becomes your hero subhead.
Next, define the single primary action. For pre-launch, it is almost always email capture or calendar booking—not "learn more" scattered across five buttons. Secondary links (pricing FAQ, changelog) can wait. One CTA reduces bounce and makes analytics honest: did they sign up or not?
- I can name the visitor (role + context) in one line
- I wrote the before/after outcome without feature buzzwords
- Primary CTA is one action: join waitlist, book call, or download kit
- I know what I will do if fewer than 20 people sign up in two weeks
- I have a 48-hour ship deadline, not a "when it's perfect" deadline
Phase 2: Structure that converts without a designer
High-performing static landers share a predictable scroll order: hero, social proof or problem agitation, how it works, objection handling, FAQ, final CTA. You do not need all seven on day one, but you do need hero + proof + CTA. Skipping proof is the most common solo-founder mistake: you assume the headline is self-evident. It is not. Add one concrete detail—time saved, error avoided, or a quote from a beta user.
Hero block
Headline: outcome, not category. Weak: "Modern analytics platform." Strong: "See which landing page copy actually drives signups." Subhead: expand who it is for and the mechanism in one breath. CTA button: verb + outcome ("Join the waitlist", "Get the checklist"). Under the button, one trust line: "Free. No spam. Unsubscribe anytime." or "Used by 40+ indie hackers in beta."
Body sections
- Problem: describe the current workflow in visceral terms your reader recognizes
- Solution: three bullets max; each bullet starts with a verb
- How it works: three numbered steps; avoid architecture diagrams on v1
- Pricing teaser: even "pricing TBD—early access discount for waitlist" sets expectations
- FAQ: kill the top three objections you hear in DMs (security, lock-in, timeline)
Keep paragraphs short. On mobile, a four-line paragraph feels like a wall. One idea per paragraph. Use subheads every two screens so skimmers still get the story.
Phase 3: Pick a stack you can maintain alone
You need HTML, CSS, and a form endpoint. That is the whole production stack for v1. React, Astro, or Eleventy are fine if you already use them daily. If not, plain HTML plus a single CSS file ships faster and debugs faster at 2 a.m. when your form breaks. Bias toward what you can edit in VS Code and deploy with git push.
| Option | Best for | Tradeoff |
|---|---|---|
| Plain HTML + CSS | Fastest ship, full control | Manual includes for shared headers |
| Eleventy / Hugo | Multiple pages + blog later | Build step to learn |
| Astro | Components without heavy JS | Slightly more tooling |
| Tailwind CDN | Rapid layout experiments | Harder to keep CSS tiny long-term |
Forms are the one dynamic piece. Use a hosted form backend (Formspree, Getform, Basin, or Cloudflare Workers + KV) so you never touch PHP or server admin. Wire the form action URL, add a honeypot field for bots, test from your phone on cellular—not just localhost.
<form action="https://formspree.io/f/your-id" method="POST">
<input type="email" name="email" required placeholder="you@company.com">
<input type="text" name="_gotcha" style="display:none" tabindex="-1">
<button type="submit">Join waitlist</button>
</form>
Phase 4: Copy and assets in one sitting
Block three hours. Hour one: headline and bullets from your bet sentence. Hour two: FAQ from real conversations or r/indiehackers posts in your niche. Hour three: visuals. Use one hero screenshot or illustration, not a carousel. Export WebP at 2x for retina; keep hero under 120 KB. Favicon and OG image are not optional—they affect trust when you paste the link in Slack or X.
- Draft copy in a doc, not directly in HTML—easier to edit and get feedback
- Read aloud; cut any sentence you stumble on
- Run Hemingway or similar once, then stop—perfectionism delays shipping
- Create 1200×630 OG image with headline text readable at thumbnail size
- Add alt text on every meaningful image for accessibility and SEO
Phase 5: Performance and trust by default
Static pages should load in under two seconds on 4G. If they do not, you lose signups before the form renders. Defer non-critical JS. Inline critical CSS for above-the-fold content or keep total CSS under 15 KB. Self-host fonts or use system stacks. Lazy-load below-fold images. Add privacy policy and terms links in the footer before you run paid traffic—payment processors and ad platforms expect them.
- Lighthouse performance score 90+ on mobile
- HTTPS on custom domain (not bare IP)
- Form success and error states tested
- 404 page exists with link back to home
- Contact email or form linked in footer
Phase 6: Deploy and verify
Connect GitHub to Cloudflare Pages or Netlify. Production branch: main. Build command: none for plain HTML, or npm run build for SSG. Set custom domain early so shared links use the real brand. After deploy, click every link, submit the form twice (duplicate handling), and view source to confirm meta tags. Set up uptime monitoring with a free ping service—silence is how you learn the site was down for a week.
Tag the release in git. Screenshot the live page for your build-in-public thread. You are done when the URL is public and the form hits your inbox or spreadsheet.
Phase 7: Measure and iterate weekly
Track unique visitors, scroll depth if your analytics support it, and form submissions. Plausible or Fathom keeps you GDPR-friendly without cookie banners in many cases; Google Analytics 4 works if you configure consent. Calculate conversion rate: signups divided by unique visitors. Below 2% usually means message mismatch; above 8% on targeted traffic means you can narrow positioning.
Change one variable per week: headline, hero image, CTA label, or social proof block. Keep a changelog in the repo README so you know what moved the needle. If traffic is zero, distribution is the problem—not the font. Post where your user already hangs out; do not wait for SEO on a brand-new domain.
Phase 8: Distribution the same day you deploy
A live URL is not launch. Block two hours for distribution the day you deploy. Post a short build log to communities where founders already discuss your problem—Indie Hackers, niche subreddits, Slack groups you genuinely participate in. Lead with the problem and one screenshot, not a product tour. Ask a specific question: "Does this headline match how you'd describe the pain?" Comments are copy research; upvotes are optional.
Prepare three distribution assets in advance: a one-sentence pitch, a 280-character post, and a slightly longer LinkedIn or blog paragraph. Reuse the same CTA link everywhere so analytics stay clean. If you run small paid tests, cap spend until organic messaging converts. Fifty dollars on bad copy teaches less than ten honest replies from target users.
- Share in one community where you are a known participant, not a drive-by link drop
- Email five people who match your ICP and ask for a 60-second skim review
- Add the link to your X bio, GitHub profile, and email signature the same day
- Submit to one relevant directory only after the page has proof and FAQ
- Schedule a follow-up post seven days later with what you learned from signups
A minimal file layout you can copy
Keep the repo boring. A typical v1 static landing project fits in five files: index.html, styles.css, favicon.ico, og-image.png, and robots.txt. Optional: privacy.html and terms.html linked from the footer. Store form configuration in HTML comments at the top of index.html so you remember which endpoint and list ID you used. Avoid nesting assets ten folders deep—you will mis-path images under stress.
project/
index.html
privacy.html
assets/
css/main.css
img/hero.webp
img/og.png
robots.txt
sitemap.xml
Version-control everything except secrets. API keys belong in your host environment or form provider dashboard, never committed. If you need A/B headlines later, duplicate index.html to index-b.html and split traffic with a simple redirect rule on your host—no need for a full experimentation framework on day one.
Common mistakes that waste a weekend
- Building a blog before the landing page converts
- Custom CMS for content that changes monthly
- Embedding five analytics scripts that slow first paint
- Hiding pricing anxiety instead of addressing it in FAQ
- Using noreply@ as the only contact—signals "don't talk to us"
- Shipping desktop-only layouts; 60%+ of indie traffic is mobile
When to graduate past a static page
Move to a dynamic app when you need authenticated dashboards, paid subscriptions with webhooks, or user-generated content. Until then, static plus a form backend and maybe a single serverless function handles waitlists, beta invites, and manual onboarding. The playbook goal is learning speed, not eternal stasis. Ship the static page this week; let data tell you what to build next.
Bookmark this sequence as your default sprint: clarify bet, draft structure, pick plain HTML or familiar SSG, write copy in a doc, wire one form endpoint, deploy to Cloudflare Pages, verify on mobile, share in one community, measure for seven days, change one variable. Repeat until signups justify the next layer of product—not the other way around.
Related: Landing page templates Deploy guides Free static landing kit Step-by-step how-tos Recommended tools
How long should my first static landing page take to build?
A focused solo founder can ship in one to three days: day one for copy and structure, day two for HTML/CSS and form wiring, day three for domain, OG tags, and mobile polish. If you are past a week without traffic, you are overbuilding.
Do I need a custom domain before sharing?
Not for friends-and-family feedback—a pages.dev subdomain is fine. For public launch, product directories, and paid ads, use a custom domain. It improves trust and makes email deliverability easier when you mail waitlist subscribers.
What conversion rate should I expect on a waitlist page?
Cold traffic often lands at 1–3%. Warm communities (your newsletter, niche Discords) can hit 8–15%. Compare channels separately; one blended number hides what works.
Plain HTML or a static site generator?
Plain HTML if you have one page and want the fewest moving parts. Use Eleventy or Hugo when you already plan multiple guides or changelog posts and want includes for header/footer without copy-paste.
How do I collect emails without building a backend?
Point your form to Formspree, Basin, or a Cloudflare Worker that writes to Airtable or Google Sheets. Test submissions from an incognito window after deploy—cached success pages often hide broken endpoints.
Ship your page this week
Grab a template, wire your form, and deploy to Cloudflare Pages in an afternoon. Momentum beats polish for your first validation loop.
Get the free kit Browse templates