For the engineers
How this site works under the hood.
Pagemage is a website starter that sells itself — so every claim on the sales page is running right here, in production, for you to poke at. This is the technical tour.
The payment-verified delivery loop
Digital delivery usually works one of two ways: a public download link (anyone with the URL gets it free), or a third-party delivery service (another account, another bill). Pagemage does it with two serverless functions and Stripe as the source of truth:
-
Checkout —
/api/create-checkout-sessiontakes a tier, maps it to a Stripe Price ID from environment variables, and creates a hosted Checkout Session. Success redirects to/success.html?session_id=…. -
Verification — the success page calls
/api/verify-session, which retrieves the session from Stripe and reports whether it's actually paid. No client-side trust, no "thank you" page that hands out files. -
Delivery — the download button points at
/api/download?session_id=…, which re-verifies the session server-side before streaming the archive. Validating the format first (cs_(test|live)_…) keeps random probing cheap to reject.
Because the download is keyed to the checkout session rather than a static link, "free updates forever" costs nothing to honor: the endpoint always serves the latest build, so past customers get every improvement by re-downloading.
The product archive ships inside the function
The zip lives at api/assets/, so Vercel bundles it with the serverless
function — api/ is never served as a static path. There is no public URL
for the product, only the verified endpoint. A tiny Node script
(scripts/make-zip.mjs) builds the archive with a hand-rolled ZIP writer:
STORE entries, a CRC32 table, UTF-8 name flags — about a hundred lines, zero
dependencies, and it runs anywhere Node runs.
Zero third-party requests
Open this page, open devtools, and count the requests that leave the origin: there
are none. Fonts are self-hosted (the woff2 files ship in the product too), the
Content-Security-Policy pins script-src, style-src, and
font-src to 'self', and the only external connection in the
entire codebase is the Stripe API — used server-side, by the functions, with a
restricted key. Your browser makes exactly one kind of third-party contact here: none.
Theming is data, not CSS rewrites
Every color on this page routes through design tokens at the top of
styles.css. The three palettes (Paper, Midnight, Plum) are just three
token blocks scoped under [data-theme] — switching themes is a single
attribute write, which is why the demo switcher on the
sales page can re-theme the whole site instantly and remember your
choice per visitor.
Constraints we chose on purpose
- No build step. The files you edit are the files you deploy — nothing to install, nothing to transpile, nothing to break.
- Functions only where money moves. Everything else is static and cached; the five API routes exist because keys and verification must live server-side.
- Progressive everything. Print styles, no-JS fallbacks, keyboard paths, and reduced-motion support are part of the starter, not an afterthought.
- Guarded by tests.
npm run checkvalidates every internal link, anchor, JSON file, and structured-data block;npm run smokeexercises each API's failure paths without needing real keys.
See it for yourself
The full setup guide shows every step from purchase to taking payments, and the sales page is the demo — the design, the checkout, and the delivery you're reading about are the product. Planning to sell something of your own? Start with the field guide to selling your first digital product.