Cloudflare Pages, Stripe and Supabase skills for coding agents

Built on real apps, not just the docs.

Your agent says the site is live, billing works, passkey sign-in is done and the CRM sent the right email, because nothing threw an error. The App Stack Pack makes it prove each one on Cloudflare Pages, Stripe, Supabase, SureContact and OttoKit before a customer finds what it missed. Its rules come from four web apps we run in production, on WordPress and off it, including the store that sells this pack, and each one says whether it was measured there or read in the vendor’s docs.

$39. Every pack, now and later: $149.

Works with

  • Claude Code
  • Codex
  • Gemini CLI
  • Cursor
  • Windsurf
  • Aider

Fit check

Is this for you?

It’s for you if

  • You’re building a web app with sign-in or payments on Supabase, Stripe or Cloudflare Pages.
  • Your agent said billing or sign-in works because nothing threw an error.
  • You run SureContact or OttoKit behind any site, WordPress included.

You’ll need

  • An AI coding agent: Claude Code, Codex, Cursor or Gemini CLI.
  • Node.js 18 or newer. Nothing else to install: no packages, no browser.
  • Your own accounts on the services you use: Cloudflare, Supabase, Stripe, SureContact or OttoKit.

Skip it if

  • Your stack uses none of Cloudflare Pages, Supabase, Stripe, SureContact or OttoKit.
  • Your billing runs outside Supabase, or sign-in on another provider. Two of the five skills won’t apply.

Behind the curtain

Why this site isn’t WordPress, and the store is.

The page you’re reading is a React app on Cloudflare Pages. Nothing sits between the design and the browser: no theme, no block editor, no page builder. Any component library, animation or layout goes in as plain code, and an agent can build it with whatever tools and MCP servers suit the job, not only what a plugin vendor has already made for WordPress.

The store runs on WordPress, because SureCart does. We chose it for selling digital products: order bumps that can offer the bundle when one pack is in the cart, upsells, a customer dashboard for downloads and license keys, and WordPress’s own accounts for customer logins. Checkout, customers and deliveries live in one place.

Each side does what it’s best at, and agents build both. Skills in this pack came from that work. For the store side, see the WordPress Pack.

Sound familiar?

Has this ever happened to you?

Tap every one you’ve lived through.

Nothing yet? Lucky you.

Why it keeps happening

This stack fails quietly.

Cloudflare leaves the pages.dev address indexable, a test-mode price ID doesn’t exist in live mode, Supabase counts a passkey as one factor, and SureContact reads a branch it doesn’t understand as true for everyone. None of it fails a build or raises an error, so the agent reports success and means it.

So you hear about it from someone else: a search console report, a customer who can’t check out on launch day, a two-factor user stuck on a code screen, a subscriber who got another tier’s email. By then it’s in production, and you’re the one tracing it back to a default.

What every page declared

A correct canonical tag, naming its own address as the one to index.

What search console reported

Five pages: “Duplicate, Google chose different canonical than user.” The production pages.dev address sent no noindex header.

One site, 2026-09-24. A canonical tag is a hint, not an order: only a host rule in _headers can tell the two addresses apart.

The fix

Make it prove the quiet parts.

The App Stack Pack is five skills your agent loads: Cloudflare Pages, Stripe billing on Supabase, passkeys on Supabase Auth, SureContact and OttoKit. Each names the silent failures in its part and ships scripts that refuse the mistake before a customer finds it.

  1. Checkers, not promises

    The scripts read your Pages headers, Edge Functions and SQL, passkey code, built emails and automation files, and name each defect and where it is.

  2. Checks that can fail

    Every checker’s selftest plants the defects it hunts and must catch them, from 9 cases to 66, with no live service touched.

  3. Every silence named

    Each skill opens on the ways its part fails without a message, and says what that silence looks like and what to measure instead.

Proof

Real output, unedited.

Three checkers, run on the fixtures the pack’s own tests use: a headers file written for the wrong subdomain, a billing repo with 12 planted defects, and the passkey code the skill teaches. Every line below is one it printed.

[ Range card ] // What we aimed for, what came back
  1. [ Shot 01 ]

    pages-noindex-check.mjs --headers _headers

    Aimed: host rules for the project name, not its subdomain; must go red

    FAIL line 4: https://acme.pages.dev/* is for a different pages.dev subdomain than acme-3xk.pages.dev, so it matches nothing this project serves

    FAIL no rule for https://acme-3xk.pages.dev/* setting X-Robots-Tag: noindex. The production alias gets no header from Cloudflare, so it is an indexable copy of the site

    4 finding(s). Static only: deploy, then run live mode to see what the edge sends.

    Landed where it was aimed // exit 1

  2. [ Shot 02 ]

    billing-check.mjs --root …/planted

    Aimed: a billing repo with 12 planted defects; must name every one

    FAIL price-id supabase/migrations/20260801000000_billing.sql:2 a Stripe price id (price_FAKE123) is written into the database by this SQL. A price id exists in one mode only, so when the functions switch to a live key, anything that uses this one fails. Store a lookup key and resolve the price when the session is created (prices.list with lookup_keys)

    12 findings; 17 rule(s) checked, 2 not checked. Static only: it reads the repository, not your Stripe account, your Supabase project or what is deployed.

    Landed where it was aimed // exit 1

  3. [ Shot 03 ]

    passkey-check.mjs --root …/doc

    Aimed: the code the skill teaches; must pass, its one exception printed

    -- allowed [aal2-sql] supabase/migrations/20260916000200_refunds.sql:3 "refunds move money, so a PIN-less key must not reach them"

    ok uv-flag 2 verifyAuthentication() call(s)

    ok aal2-sql 2 SQL statement(s) reading aal

    0 finding(s), 1 allowed; 15 rule(s) had something to check, 1 had nothing. Static only: SKILL.md §6 lists what this cannot see.

    Landed where it was aimed // exit 0

Run from a fresh unzip of the 1.2.1 download. Indents and column padding trimmed; nothing else changed.

Who it’s for

Built for web apps on this stack.

For
Developers, freelancers and small studios who build web apps with an AI coding agent (Claude Code, Codex, Cursor, Gemini CLI) on Cloudflare Pages, Stripe or Supabase, or run SureContact and OttoKit behind any site.
Best fit
An app on Cloudflare Pages that sells plans through Stripe Checkout, with Supabase Edge Functions, a subscriptions table, passkey sign-in on Supabase Auth, and SureContact and OttoKit for its email and automations.
Works with
Node 18 or newer, with no packages. Each skill works on its own, so billing and passkeys can sit on another host, Pages on another backend, and SureContact and OttoKit on any stack, WordPress included.
Not for
Stripe billing outside Supabase Edge Functions, passkeys on an auth provider other than Supabase, a host other than Cloudflare Pages, or another CRM or automation tool. The scripts are written for these five.

Five skills, each with its own checks.

One skill per part of the stack. Each teaches your agent the rules and ships scripts that check them on your project.

Explain it
  1. pages-noindex-check.mjs --selftest

    ok the production alias block missing

    ok a host-less /* noindex rule

    ok live: a custom domain answering noindex fails

    32 cases behaved as designed

    Pass

    Only your real domain gets indexed

    Every Pages site is also served at a pages.dev address that Cloudflare leaves open to search. Your agent adds the two rules that hide it, proves your domain stays indexable, and learns the redirect, cache and upload rules Pages breaks without a message.

    • cloudflare-pages
  2. billing-check.mjs --selftest

    ok price-id: a price id written into a seed

    ok webhook-jwt: no verify_jwt = false anywhere

    ok status-check-rejects: the CHECK has no paused and nothing maps it

    66 cases behaved as designed

    Pass

    Stripe goes live without a migration

    Your plans store Stripe lookup keys instead of price IDs, so the same rows work in test and live mode. The browser names a plan, never a price, and the webhook checks every signature and accepts every status Stripe sends.

    • stripe-on-supabase
  3. passkey-check.mjs --selftest

    ok the UV flag test removed [uv-flag]

    ok an RLS policy comparing aal inline [aal2-sql]

    ok insufficient_aal handling removed from adding a passkey [insufficient-aal]

    64 cases behaved as designed

    Pass

    Passkeys count as two factors

    Supabase treats every passkey sign-in as one factor, so two-factor users get a code screen after their fingerprint. The skill makes a verified passkey count as two, updates every check that demands a second factor, and keeps the code where it still belongs.

    • supabase-passkeys
  4. drip-to-workflow.mjs --selftest

    ok payload with one body edited by hand

    ok payload with a send cut out of the path

    9 cases behaved as designed

    Pass

    The approved email is what sends

    The email your subscribers get is the one you approved. Each email series is generated from your built HTML and checked byte for byte before it goes up, forms and webhooks land in the right workspace, and the CRM’s quiet failures are written down.

    • surecontact-integration
  5. ottokit-call.mjs --selftest

    ok end to end: another server is refused and nothing is saved

    ok end to end: no title matches, so it refuses, says the selection may have moved, and calls nothing

    36 cases behaved as designed

    Pass

    The automation that runs is yours

    The automation that runs is the one saved in your project. A call goes through only when the server’s id is the one you recorded and the workspace selected in OttoKit’s web app holds an automation title you named, and the run history you read keeps only that workspace’s automations. Definitions are checked before import and compared with the export after.

    • ottokit-integration

What’s in the pack

Every skill, with its job in one line. Each works on its own, and the SureContact and OttoKit skills point to each other where a webhook hands a contact over.

  • cloudflare-pages

    Cloudflare Pages

    Every pages.dev address kept out of search, your real domain kept in, checked in the build and live.

  • stripe-on-supabase

    Stripe billing on Supabase

    Lookup keys instead of price IDs, secrets kept server-side, and a webhook that verifies and maps every status.

  • supabase-passkeys

    Passkeys on Supabase Auth

    A passkey unlocked by fingerprint, face or PIN counts as two factors, without locking anyone out.

  • surecontact-integration

    SureContact, sent exactly

    Forms, drips and webhooks, with each drip checked byte for byte against your build before it sends.

  • ottokit-integration

    OttoKit, kept in your repo

    Automations kept as files, checked before import and diffed after, and called only when the server’s id and an automation title you name both match.

Where it lands, and what it proves.

One download: five skills for Claude Code, the same instructions to paste into any tool that reads AGENTS.md, the scripts they run, and the harnesses that prove each check can fail.

app-stack/

  • .claude-plugin/
    • plugin.json
  • ci/
    • cloudflare-skills.mjs
    • integration-skills.mjs
    • pack.json
    • passkeys-skills.mjs
    • skill-frontmatter.mjs
    • stripe-skills.mjs
    • surecontact-skills.mjs
    • verify.sh
  • CHANGELOG.md
  • install.sh
  • LICENSE
  • README.md
The files in app-stack/, as the download ships them.

Unzip it anywhere; nothing runs on its own

install.sh copies the five skills into ~/.claude/skills/, or a folder you name with --dir, and moves an existing copy aside with a timestamp instead of overwriting it. Or run claude --plugin-dir on the whole folder to load it as a plugin for one session.

ci/ is the pack’s own test suite: a harness per skill runs its selftests and breaks copies of its scripts to prove each selftest can fail. ci/verify.sh runs all of it, and everything else the pack must survive, in one command.

Every check can fail on purpose.

A check that has never failed is a green light with extra steps. Each checker here ships a selftest that plants the defects it hunts, and each harness breaks a copy of the checker to prove the selftest notices. Run them first, before you trust a clean result.

Our own probe caught a bug in two of these checkers.

  1. Walked the disk in silenceRefuses a folder that isn’t a project, in one line, before it reads anything.
Show the commands and what they must do

Run the controls

Shell
# with the App Stack Pack unzipped at /path/to/app-stack, and nothing here calls a live servicenode /path/to/app-stack/skills/cloudflare-pages/scripts/pages-noindex-check.mjs --selftest   # must report 32 cases behaving as designednode /path/to/app-stack/skills/stripe-on-supabase/scripts/billing-check.mjs --selftest   # must report 66 cases behaving as designednode /path/to/app-stack/skills/supabase-passkeys/scripts/passkey-check.mjs --selftest   # must report 64 cases behaving as designednode /path/to/app-stack/skills/surecontact-integration/scripts/drip-to-workflow.mjs --selftest   # must report 9 cases behaving as designednode /path/to/app-stack/skills/ottokit-integration/scripts/ottokit-definition.mjs --selftest   # must report 25 cases behaving as designedbash /path/to/app-stack/ci/verify.sh   # runs every harness in the pack and each broken copy must fail its selftest

We call these negative controls: a planted defect the check has to fail on. The selftests plant each checker’s defects, run any live check through a fake fetcher, and must report every case as designed. ci/verify.sh runs the pack’s harnesses, which break copies of the scripts on purpose; each broken copy must fail its own selftest.

The check that has never failed is the one to distrust.

Works with the agent you already use.

The skills are plain text files your agent reads. The scripts are single Node files with no dependencies, and they run on your computer.

  • Claude Code
  • Codex
  • Gemini CLI
  • Cursor
  • Windsurf
  • Aider
Shell
claude --plugin-dir /path/to/app-stack

The written skills need nothing at all. The scripts need Node 18 or newer and nothing else: no packages, no browser. billing-check.mjs also uses git when your project is a repository, and says what it assumed when it is not.

Everything the scripts touch

Your Pages hosts
Fetched once each, to read their headers: the ones you name, or the ones your own wrangler login lists. Read only.
Your project’s files
Read, never changed. Git is asked, read-only, whether an env file is tracked or ignored.
Your Supabase project
Two requests with your anon or publishable key, only with --project-url. No setting or user changes.
SureContact and OttoKit
One tool you name, when you run it, with a credential you supply. OttoKit only after the server answers with the id you recorded and the workspace the web app has selected holds the title you set.
Your email’s images
One request per image in your built email, to prove each one is live on your host.
The network
No telemetry, no license check, no phone-home. Nothing sends a credential anywhere but its own vendor.

Plain, commented JavaScript, nothing minified into a blob. A pack that says “don’t trust a report you can’t read” has to be readable itself.

One payment. Yours forever.

App Stack Pack

$39.

  • One company, team or solo operator
  • As many computers and projects as you like
  • Change and adapt it freely
  • Keep the version you bought, forever
  • No subscription
  • Every future version of the App Stack Pack included
  • 14-day refund, no questions

Please don't resell it or share it outside your company.

All-Access Bundle

Every pack, now and later.

Spotter Round, the Agent Setup Pack, the Email Pack, the WordPress Pack, the App Stack Pack and the Campaign Tracker Pack, plus every pack added after them, each with every future version.

$149.

The six separately: $234

Get every pack — $149

Questions before you buy.

Which pack do I need?

Spotter Round if an agent writes your web pages: it proves the work before and after it ships. The Agent Setup Pack if you use more than one agent or more than one tool, or hand agents API keys. The Email Pack if you send HTML email. The WordPress Pack if you build on WordPress with Bricks. The App Stack Pack if you build web apps on Cloudflare Pages, Supabase or Stripe, or use SureContact or OttoKit on any site, WordPress included. The Campaign Tracker Pack if you run ads and want short links, leads, purchases and cost per lead tracked from the server, on any site behind Cloudflare. The All-Access Bundle is every pack, now and later, for less than the six together.

Does this work with Codex, Cursor, Gemini CLI, Aider, Windsurf?

Yes. The skills are plain text files and the checks are plain Node scripts, so any agent can run them. Claude Code loads the skills from its skills folder. Codex, Cursor and the rest take a skill pasted into your repository's AGENTS.md, and Gemini CLI reads that file once its settings name it.

Do I need Cloudflare, Stripe and Supabase together?

No. Each skill works on its own: the Pages skill needs only Cloudflare Pages, the billing skill assumes Stripe with Supabase Edge Functions, and the passkey skill assumes Supabase Auth. The SureContact and OttoKit skills work with any stack, WordPress included. If you have Spotter Round, its checks verify the pages the app serves.

Why is this site React and the store WordPress?

Each does what it’s best at. The marketing pages need design freedom, so they’re a React app on Cloudflare Pages with no theme or page builder in the way. The store needs a proven engine for digital products, and SureCart, which runs inside WordPress, brings checkout, customer accounts, downloads and upsells into one place. Several skills in this pack came from building both.

Do the checkers need my Stripe or Supabase keys?

No. billing-check.mjs reads your repository, env files included, makes no request, and names a secret it finds only by kind and length. passkey-check.mjs reads files too; only its live mode sends a key, the anon or publishable one from a variable you name, to your own Supabase project, and it refuses a secret key. pages-noindex-check.mjs sends no credential of its own.

What can’t the checkers see?

The static checks say so at the end of every report. The billing check reads the repository, not your Stripe account, your Supabase project or what is deployed. The passkey check can’t see whether a device verified its user: the server never records it, so no tool can. Each SKILL.md lists the rest.

Does it send anything anywhere?

No telemetry, no license check, nothing phoning home. The Pages checker fetches your own hosts, named by you or listed by your own wrangler login; for that listing, npx fetches wrangler from the npm registry unless your project or your machine already has it. The passkey checker’s live mode makes two requests to your own Supabase project. surecontact-call.mjs calls the one tool you name, with a key you supply. ottokit-call.mjs does the same after reading the server’s id and its automation titles from that server, to check the server and the workspace. The image guard requests each image in your built email. Everything else reads files, and nothing sends a credential anywhere but its own vendor.

What do updates look like?

Numbered downloads with a list of what changed. Every future version of the App Stack Pack is included at no charge, so you never pay for a new version, and you are never forced to update.

Can I use it for client work?

Yes — that's what it's for. One company covers every project that company delivers.

Refunds?

Fourteen days, no questions. A product about checking things that argued with you over a refund would be a poor advertisement for itself.

Find it before a customer does.

Sold separately

Five more packs. One job or stack each.

Each pack is sold on its own and ships its own checks, the same way this one does.

Spotter Round$39
Agent Setup Pack$39
Email Pack$39
WordPress Pack$39
Campaign Tracker Pack$39
All-Access Bundle$149

Spotter Round

$39

The layout, the pixels, the speed and the live deploy: your agent’s work, proven before it says it’s done.

1 / 6