Build premium static landing pages with the Stomme/PolyTrader design system. Glass morphism, CSS custom properties, separated copy, responsive, Cloudflare Pa...
---
name: landing-page-builder
description: Build premium static landing pages with the Stomme/PolyTrader design system. Glass morphism, CSS custom properties, separated copy, responsive, Cloudflare Pages-ready. Use when building a website, landing page, marketing site, or product page. Produces static HTML/CSS/JS with no framework dependencies.
---
# Landing Page Builder
Build premium static landing pages using the proven design system from polytrader.ai.
## Stack
- Static HTML/CSS/JS — no frameworks, no build tools
- CSS custom properties for all theming
- Google Fonts via preconnect
- Cloudflare Pages deployment target
## Procedure
1. **Read content sources** — all copy must come from provided markdown files, never invented
2. **Read the design system reference** — `read references/design-system.md` for the full CSS pattern library
3. **Separate copy from layout** — define ALL text in a `js/copy.js` data file, reference from HTML via `data-copy` attributes or JS injection. This enables i18n later.
4. **Build pages** using the section patterns from the design system
5. **Include**: `_headers` (security headers), `_redirects`, `robots.txt`, `sitemap.xml`, `.gitignore`
6. **Generate validation scripts** — adapt `references/pre-push-check-template.sh` and `references/validate-live-template.js` for the specific site (selectors, locales, CSS vars). Place in `scripts/`. Set up `.githooks/pre-push`. Wire into CI workflow.
7. **Test**: open in browser at desktop AND mobile viewports. Run `bash scripts/pre-push-check.sh`. Verify theme toggle (3 full cycles), lang switcher (all locales), contrast on all interactive elements.
8. **Git init + commit** (hooks path set to `.githooks/`)
9. **Write BUILD-NOTES.md** with Cloudflare Pages deployment instructions
## Design System Principles
The reference file has the full implementation. Key principles:
- **Dual theme** — dark premium default + light mode. Auto-detects `prefers-color-scheme`, user toggle in nav, `localStorage` persistence, inline `<head>` script prevents flash
- **Glass morphism** — `.glass` cards with backdrop-filter, subtle borders, inset shadows — adapts to both themes
- **CSS custom properties** — every color, spacing value, and font through variables. Dark values in `:root`, light overrides in `[data-theme="light"]`
- **Gold/brand accent** — gradient CTAs, accent moments, section kickers. Slightly deepened in light mode for contrast
- **Ambient backgrounds** — layered radial-gradients for depth, NOT solid colors — both themes use them
- **Typography** — Google Fonts (Plus Jakarta Sans or similar geometric sans), tight tracking on headings (-0.035em), generous body line-height (1.75)
- **Interactions** — subtle translateY lifts on hover, gradient buttons with glow shadows
- **Theme toggle** — sun/moon SVG icons in nav, `localStorage` key for persistence, OS change listener
## Section Patterns (in order)
1. **Sticky nav** — frosted glass, pill shape or clean bar, brand + links + theme toggle + CTA
2. **Hero** — large headline, subheadline, dual CTAs (gradient primary + outline secondary), trust signals in glass card grid below
3. **Value proposition** — narrative text section explaining the core differentiator
4. **How it works** — numbered steps (01, 02, 03...) in glass cards, 2-column layout
5. **Features** — alternating layout (text left/visual right, then swap), glass cards
6. **Pricing** — tier cards with ring highlight on featured plan, checklist items with check icons
7. **FAQ** — 2-column glass card grid, question + answer
8. **Bottom CTA** — full-width banner, headline + CTA + supporting line
9. **Footer** — minimal, border-top, brand + links + legal
## Theme Architecture
Every page must include:
1. **Inline `<head>` script** (blocking, before CSS loads) — reads `localStorage` key, falls back to `prefers-color-scheme`, sets `data-theme="light"` on `<html>` if light
2. **`:root`** — dark theme variables (default)
3. **`[data-theme="light"]`** — light theme variable overrides
4. **`--body-bg-gradient`** variable — ambient background through a custom property so it switches with theme
5. **Theme toggle button** in nav with sun/moon SVG icons, visibility driven by CSS `--theme-icon-sun` / `--theme-icon-moon` variables
6. **JS in main.js** — `initTheme()` function: toggle click handler, `localStorage.setItem`, OS `change` listener (respects manual override)
7. **Smooth transitions** — 300ms ease on `color`, `background`, `border-color`, `box-shadow` for themed elements
8. **`--btn-primary-text`** — button text color variable (dark on dark theme where bg is gold, white on light theme)
## File Structure
```
site-root/
├── index.html
├── pricing.html
├── privacy.html
├── terms.html
├── 404.html
├── css/
│ └── style.css # Full design system + page styles (dark + light themes)
├── js/
│ ├── copy.js # ALL text content as exportable object
│ └── main.js # Nav toggle, smooth scroll, theme toggle, minor interactions
├── img/
│ ├── favicon.svg
│ └── og-placeholder.png
├── _headers # Cloudflare security headers
├── _redirects # Cloudflare redirects
├── robots.txt
├── sitemap.xml
├── .gitignore
└── BUILD-NOTES.md
```
## Post-Build Validation (MANDATORY)
Every build **must** include a `scripts/` directory with two validation scripts. These are not optional — they are part of the deliverable, like _headers or sitemap.xml.
### 1. `scripts/pre-push-check.sh` — Static pre-push gate
Runs before every `git push` (via `.githooks/pre-push`). Checks:
- All `<script src>` and `<link href>` tags have cache-bust version params (`?v=HASH`)
- No hardcoded hex colors in style.css (all colors via CSS custom properties)
- copy.js and main.js parse without syntax errors
- `applyTheme()` is called on DOM load (not just on toggle click)
- CTA buttons have explicit color override (prevents inheritance from ancestor selectors like `.nav-links a`)
- No `removeAttribute('data-theme')` in any HTML file (must always set theme explicitly)
- Exit 1 on any failure — blocks the push
### 2. `scripts/validate-live.js` — Post-deploy browser validation
Runs in CI after every Cloudflare Pages deploy, using Playwright. Tests at **both** desktop (1440px) and mobile (375px) viewports:
- CSS custom properties resolve to non-empty values
- Contrast ratios on all interactive elements meet WCAG AA (4.5:1 normal text, 3.0:1 large)
- Theme toggle: 3 full cycles (6 clicks), verifies alternation and `localStorage` sync
- Language switcher: all locales produce non-empty hero text and correct `localStorage` value
- All `<script>` and `<link>` tags have version params
- No broken internal links (`href="#"`, empty, or undefined)
- Meta tags present: title, description, og:title
### 3. Git hook setup
```bash
mkdir -p .githooks
echo '#!/bin/bash' > .githooks/pre-push
echo 'bash "$(git rev-parse --show-toplevel)/scripts/pre-push-check.sh"' >> .githooks/pre-push
chmod +x .githooks/pre-push
git config core.hooksPath .githooks
```
### 4. CI workflow must include validation job
The GitHub Actions workflow must have a `validate` job that runs **after** the deploy job:
```yaml
validate:
needs: deploy
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '22' }
- name: Install Playwright
run: npx playwright install chromium --with-deps
- name: Wait for deploy propagation
run: sleep 30
- name: Run post-deploy validation
run: node scripts/validate-live.js https://$DOMAIN
```
**Why this exists:** We shipped a grey-on-red CTA button and a broken theme toggle to production because we relied on visual review alone. Computed style checks catch what eyes miss. Mobile Safari caching broke deploys because we tested desktop only. These scripts encode every lesson into automated gates.
## Constraints
- No Tailwind, no Bootstrap, no React — hand-written CSS
- No external CDN for JS (except Google Fonts CSS)
- No analytics scripts (added separately later)
- No invented features — only what's in the content source files
- All file permissions 0o644 (static files, not secrets)
- Must pass Lighthouse performance >90
don't have the plugin yet? install it then click "run inline in claude" again.
added explicit inputs (content sources, cloudflare setup, playwright), decision points (multi-language, ci workflow, contrast validation), output contract (file structure, css/js specs, success criteria), and outcome signal (8 concrete verification steps). preserved original author's 9-step procedure, design system principles, and validation scripts requirement.
build production-grade static landing pages using the stomme/polytrader design system. use this skill when you're shipping a website, landing page, marketing site, or product page that needs premium aesthetics without framework overhead. produces vanilla html/css/js with glass morphism, dual-theme support, and cloudflare pages deployment ready. the output is a complete static site with validation scripts, deployment config, and zero runtime dependencies.
content sources:
references/design-system.md (full css pattern library, color palette, spacing scale, typography rules).js/locales/).external files (templates to adapt):
references/pre-push-check-template.sh (static validation gate, customized per site).references/validate-live-template.js (post-deploy browser validation, customized per site and viewport configs).cloudflare pages connection:
CF_DOMAIN (your deployed domain, used in ci validation job).local environment:
npx playwright install chromium --with-deps for ci).edge cases & assumptions:
read content sources , extract all copy from provided markdown files into a single source of truth. do not invent text. document which file maps to which page section (hero headline comes from content/hero.md, pricing tier names from content/pricing.md, etc.).
output: a content inventory (can be plain text or comment block in js/copy.js).
read design system reference , open references/design-system.md and absorb the full css pattern library. note the color tokens (e.g., --color-gold, --color-text-primary), spacing scale (e.g., --space-2, --space-4), typography rules (plus jakarta sans, 1.75 line-height on body), and all dual-theme overrides.
output: mental model of the design system. no file produced yet.
separate copy from layout , define all text as a js object in js/copy.js, exported as const COPY = { hero: { headline: "...", subheadline: "..." }, ... }. reference copy in html via data-copy attributes or js injection (e.g., <h1 data-copy="hero.headline"></h1> or document.querySelector('h1').textContent = COPY.hero.headline). this enables i18n and a/b testing later.
output: js/copy.js file with all site text as exportable object.
build pages using section patterns , for each page (index.html, pricing.html, terms.html, etc.), use these patterns in order: sticky nav, hero, value proposition, how it works, features, pricing, faq, bottom cta, footer. each section uses glass cards, css custom properties, and the responsive grid layout from the design system. do not deviate from the pattern order.
output: one html file per page (index.html, pricing.html, etc.). each page includes the theme-toggle inline script in <head> and references css/style.css and js/main.js.
include static config files , create the following at site root: _headers (cloudflare security headers, enforce csp, x-frame-options, etc.), _redirects (cloudflare redirect rules if any), robots.txt (allow all, point to sitemap), sitemap.xml (list all pages), .gitignore (exclude node_modules, .env, os junk). these are non-negotiable for production.
output: four files at root level.
generate and wire validation scripts , adapt references/pre-push-check-template.sh for your site (set correct selectors, locales, css var names). adapt references/validate-live-template.js for your domain and viewport list. place both in scripts/ directory. set up git hook by running: mkdir -p .githooks && echo '#!/bin/bash' > .githooks/pre-push && echo 'bash "$(git rev-parse --show-toplevel)/scripts/pre-push-check.sh"' >> .githooks/pre-push && chmod +x .githooks/pre-push && git config core.hooksPath .githooks. wire validate-live.js into ci workflow (see decision points for ci template).
output: scripts/pre-push-check.sh, scripts/validate-live.js, .githooks/pre-push, updated .github/workflows/deploy.yml with validation job.
test locally , open each page in a browser at desktop (1440px) and mobile (375px) viewports. verify: theme toggle works (3 full dark/light cycles, no flash on load, localStorage persists across reload), language switcher updates all text correctly, glass cards render without visual glitches, all links are clickable and go to the right place. run bash scripts/pre-push-check.sh and verify it exits 0.
output: bug list (if any) logged and fixed. validation script passes.
git init and commit with hooks , initialize git repo (if new), add all files, commit with message "initial: landing page build". confirm that .githooks/pre-push runs on git push and blocks if validation fails.
output: git repo initialized, first commit with hooks wired.
write build-notes.md , document the cloudflare pages deployment steps: repo connection, auto-deploy on push to main, domain setup, env vars (if any), how to trigger manual redeploy, and link to ci workflow dashboard. include a "validation checklist" section reminding the next person to run pre-push tests and wait for ci validation to pass.
output: BUILD-NOTES.md at site root.
if multi-language support is required:
js/locales/en.js, js/locales/es.js, etc., each exporting const COPY_LOCALE_EN = { ... }.js/main.js, add initLocale() function that reads localStorage.getItem('locale'), defaults to navigator.language.split('-')[0].validate-live.js) tests all locales, verifies non-empty hero text and correct localStorage value per language.else (single language, english):
js/copy.js, no locales subdirectory.if ci workflow does not yet exist:
.github/workflows/deploy.yml with two jobs: build (runs on push to main, builds and deploys to cloudflare pages) and validate (depends on build, runs scripts/validate-live.js against deployed domain after 30s delay).else (ci workflow already exists):
CF_DOMAIN env var is set.if cloudflare pages is not yet connected to the repo:
main branch as auto-deploy trigger, set build command to echo "no build step needed" (or leave blank), and root directory to / (since everything is static).else (cloudflare pages is connected):
if browser supports prefers-color-scheme media query and localStorage:
<head> script reads localStorage key 'theme', falls back to prefers-color-scheme, sets data-theme on html element. nav button toggles and persists. OS theme change is respected if user has not manually toggled.else (older browser, no localStorage):
if all <script> and <link> tags have version params (e.g., ?v=abc123):
else:
if contrast ratio on all interactive elements (buttons, links, form inputs) is >= 4.5:1 (normal text) or >= 3.0:1 (large ui):
else:
if all internal links are valid (no href="#", no empty, no undefined):
else:
if lighthouse performance score is >= 90:
else:
loading="lazy"), css minification (inline or asset pipeline), reduce js bundle, defer non-critical font loads. retest before deploy.file structure:
site-root/
├── index.html
├── pricing.html
├── privacy.html
├── terms.html
├── 404.html
├── css/
│ └── style.css
├── js/
│ ├── copy.js
│ ├── main.js
│ └── locales/ [optional, only if multi-language]
│ ├── en.js
│ ├── es.js
│ └── ...
├── img/
│ ├── favicon.svg
│ └── og-placeholder.png
├── scripts/
│ ├── pre-push-check.sh
│ └── validate-live.js
├── .githooks/
│ └── pre-push
├── _headers
├── _redirects
├── robots.txt
├── sitemap.xml
├── .gitignore
├── BUILD-NOTES.md
└── .github/workflows/
└── deploy.yml [ci workflow with validate job]
css/style.css:
:root and [data-theme="light"] override block), all section styles (nav, hero, value prop, how it works, features, pricing, faq, bottom cta, footer), glass morphism effects, smooth theme transitions (300ms ease on color, background, border, shadow), no hardcoded hex colors (all via css custom properties), responsive grid (2 columns on desktop, 1 on mobile).js/copy.js:
const COPY = { siteTitle: "...", nav: { links: [...] }, hero: { headline: "...", subheadline: "...", cta1: "...", cta2: "..." }, ... }.js/main.js:
initTheme() function (toggle click handler, localStorage persistence, os change listener).initLocale() function if locales exist (toggle locale, inject locale-specific copy, persist in localStorage).validation scripts:
scripts/pre-push-check.sh: bash script, runs before every git push, exits 0 if all checks pass, exits 1 if any check fails (blocks push).scripts/validate-live.js: node.js script using playwright, runs in ci after deploy, tests at 1440px and 375px viewports, logs test results to stdout, exits 0 if all pass, exits 1 if any fail (ci job fails).git hook:
.githooks/pre-push: executable bash script, automatically invoked by git before push, calls scripts/pre-push-check.sh.ci workflow:
.github/workflows/deploy.yml: github actions yaml (or equivalent for gitlab ci/etc.), has build job (deploy to cloudflare pages) and validate job (run scripts/validate-live.js after 30s delay).deployment:
success criteria:
the user knows the skill worked when:
local validation passes: running bash scripts/pre-push-check.sh in the terminal exits with code 0 (no output means success, or "all checks passed").
theme toggle works in browser: open the site in a desktop browser, click the sun/moon icon in the nav 3 times (dark, light, dark), verify the page switches color and no flash of unstyled content appears on refresh (localStorage is persisting).
mobile responsive: open the site on a phone (375px viewport) or use browser dev tools to simulate mobile, verify all sections stack vertically, buttons are touchable (44x44px minimum), glass cards render without overflow.
language switcher works (if multi-language): click the locale switcher, select a different language, verify all page text updates (hero headline, button labels, footer links) and localStorage stores the new locale.
ci validation passes: push to main branch, watch the github actions (or ci) workflow, verify the validate job runs after the deploy job and shows green (no test failures). check ci logs for "all checks passed" or similar message.
deployed site is live: visit your cloudflare pages domain in a browser, verify the site loads, theme toggle works, all links work, no 404s or js errors in console.
lighthouse audit passes: run chrome dev tools lighthouse audit on the deployed domain, verify performance score >= 90, accessibility >= 90, best practices >= 90.
git hook blocks bad pushes: intentionally break a validation rule (e.g., add a hex color to css), attempt git push, verify that .githooks/pre-push blocks the push with an error message. fix the issue and push succeeds.
credits: original skill by jonathanlindsay (clawhub). enriched to implexa quality standards with explicit decision logic, edge case handling, and validation script integration.