Reorients the whole sales surface to accounting so it matches the rebuilt demos. Replaces the Shopify and RevOps persona pages with accounts-payable (1099) and accounts-receivable pages, refreshes the bookkeeper page, and rewires the hub + deploy tooling: - landing/bookkeeper/ — refreshed to the validated bank-rec demo (26 -> 20, six phantom duplicates), iframe ?p=bookkeeper. - landing/ap-1099/ — NEW (replaces shopify-pet/): 1099 vendor prep, "24 records -> 8 vendors, 7 missing EINs recovered", iframe ?p=ap-1099, amber accent. - landing/ar-aging/ — NEW (replaces revops/): AR open invoices, "26 -> 21, five double-entered invoices removed", iframe ?p=ar-aging, green accent. - landing/index.html — hub rewritten with the three accounting cards. - deploy.py / deploy.config.example.json / README.md / _shared/styles.css — persona list, sitemap defaults, 404 links, cross-links, docs updated. All demo iframes now point at the renamed app_demo personas; deploy.py builds the dist bundle cleanly (verified) and the Gumroad ?from= tags match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.9 KiB
Landing pages
Three persona-tagged landing pages per docs/PLAN.md §2.3 and
docs/DEMO-PLAN.md §3 / §7. Static HTML, zero build step, ship to
Cloudflare Pages.
Structure
landing/
├── _shared/styles.css shared CSS (system fonts, no externals)
├── bookkeeper/index.html bookkeeper — bank reconciliation
├── ap-1099/index.html accounts payable — 1099 vendor prep
├── ar-aging/index.html accounts receivable — open invoices
└── README.md this file
Each page:
- Inherits
landing/_shared/styles.css - Overrides the
--accentcolour variable in an inline<style>block so each persona has its own visual identity (Bookkeeper = steel blue, AP / 1099 = amber/gold, AR = receivables green) - Has a sticky buy bar with the Gumroad CTA tagged with
?from=<persona> - Embeds the live demo (Streamlit) via
<iframe>with a sandbox attribute - Carries persona-specific H1, sub-copy, use cases, FAQ, and a
ready-to-paste
terminalblock showing the CLI in action - Includes Open Graph + Schema.org
SoftwareApplicationJSON-LD for link-share previews and SEO
Pre-deploy URL substitutions — automated
The HTML carries placeholder URLs (the literal strings
https://demo.datatools.app, https://datatools.app,
https://gumroad.com/l/datatools, mailto:hello@datatools.app)
that must be replaced before deployment. A small Python script
does this for you — no global search-and-replace needed.
# 1) Copy the template and fill in your real URLs:
cp landing/deploy.config.example.json landing/deploy.config.json
edit landing/deploy.config.json
# 2) Build the deploy-ready bundle:
python3 landing/deploy.py
# → produces landing/dist/ with substitutions applied,
# plus robots.txt, sitemap.xml, 404.html, favicon.svg
landing/deploy.config.json is gitignored so your real URLs never
hit the repo. Re-run landing/deploy.py whenever you change a URL or
edit any HTML source.
Cloudflare Pages deployment
The simplest path — one Pages project pointed at landing/dist/:
# Option A: drag-and-drop the directory in the Cloudflare dashboard
# Pages → Create project → Direct Upload → drag landing/dist/
# Option B: Wrangler CLI (one command, scriptable)
wrangler pages deploy landing/dist
Configure the custom apex domain (datatools.app) in the Cloudflare
Pages project settings; sub-paths /bookkeeper/, /ap-1099/,
/ar-aging/ are served automatically because the directory layout
mirrors them. Cache rule defaults are fine (HTML 1 day, CSS 7 days).
If you want separate Pages projects per persona for independent
A/B testing, point three projects at the same landing/dist/ and
configure each with its own sub-domain (bookkeeper.datatools.app, etc.)
and a Pages rule that rewrites the root to that persona's
sub-directory.
Telemetry wiring (per DEMO-PLAN §8)
The plan calls for event-only counters, no PII, no Google Analytics.
For each page, on Cloudflare Pages, attach a Worker (or use Cloudflare Web Analytics — it's privacy-friendly out of the box and zero config). Track:
page_viewper persona (auto from CF Web Analytics)cta_clicked— add a small inline<script>that fires a fetch to/api/event?event=cta_clicked&persona=<persona>when the buy button is clicked, then continues the navigation to Gumroad.demo.run_completedanddemo.cta_clickedare owned by the demo app, not the landing page.
Conversion (per DEMO-PLAN §8):
demo_engagement = demo.run_completed / page_view (target ≥ 30%)
purchase_intent = demo.cta_clicked / demo.run_completed (target ≥ 5%)
purchase_rate = gumroad.purchase / demo.cta_clicked (target ≥ 30%)
The Gumroad webhook captures ?from=<persona> so we can attribute
purchases back to the landing page that produced them.
Maintenance triggers (per DEMO-PLAN §9)
Refresh the page when:
| Trigger | Action |
|---|---|
cta_clicked / run_completed < 5% for 4 weeks |
The demo is working but the buyer isn't trusting the CTA. Add a screenshot of the network tab showing zero outbound calls. Soften the price callout. |
page_view → run_completed < 30% for 4 weeks |
The demo iframe isn't loading or visitors aren't engaging. Check the iframe URL. Move the demo above the fold if it's currently below. |
| New tool ships (06–09) | Add it to the persona's saved pipeline only if it fits — don't bloat the demo with every tool. |
| Pricing change | Update <meta> schema, the buybar .price-tag, the pricing card, and the FAQ. Search-and-replace $49 across the file. |
| New persona added (4th, 5th) | Copy bookkeeper/index.html, replace persona-specific copy, add to the footer cross-link block on the existing pages. |
Why static HTML
Per DECISIONS.md §5 and BUSINESS.md §7, the landing-page channel
must be:
- Async-friendly — Cloudflare Pages serves these with no operator involvement
- Cheap — Cloudflare Pages free tier is sufficient until well past
the $5k/mo MRR re-lock trigger (
DECISIONS.md §8) - Privacy-respecting — no third-party tracker means no cookie banner, which means no friction added to the conversion funnel
- Zero ongoing maintenance — no framework, no build, no upgrades. The CSS uses system fonts; no Google Fonts; no CDN dependency that could break the page when their TLS certificate rolls.
Anti-temptations (per DEMO-PLAN §11 + plan §5)
These pages deliberately exclude:
- No live chat widget. Locked by no-touch.
- No "schedule a demo with us" CTA. Same.
- No email capture before the demo. Friction kills conversion.
- No Google Analytics / Meta Pixel. Privacy story is a moat, not a checkbox to ignore.
- No SaaS-style "free trial / no credit card." This is a one-time download, not a subscription.
- No A/B-testing framework yet. Pre-PMF traffic doesn't reach statistical significance — ship the single-arm copy, iterate monthly.