Use a Stripe test-mode account and Stripe's test payment details for all local development. Never use live keys or real payment details.
Run:
pnpm dev:stripeThis follows the production webhook path. It publishes only Ghost's Stripe
webhook route through Tailscale Funnel.
Once Stripe is connected in Admin, Ghost registers a temporary webhook endpoint
using its pinned Stripe API version and removes it on shutdown. The site and
Admin remain on localhost.
Use this mode when webhook payload shape matters, such as when reading fields from a checkout session. Ghost logs an error if an event arrives at a different API version from the one it pins.
Funnel requires Tailscale 1.52 or newer, with MagicDNS, HTTPS certificates, and Funnel enabled for the tailnet and node. The command reports when Tailscale is missing, disconnected, or has no MagicDNS name. Other setup failures include Tailscale's own error.
The webhook route is publicly reachable while the command runs, but every request must have a valid Stripe signature. The tunnel closes when the command stops. A forced kill can leave it running until Tailscale or the machine restarts. Turn it off manually if this happens:
tailscale funnel --https=443 offWhen Tailscale is unavailable and exact webhook payload shape does not matter, run:
pnpm dev:stripe --listenThis uses stripe listen in Docker and requires STRIPE_SECRET_KEY in the
environment or a local .env file. The key must be a test-mode key for the same
Stripe account connected to Ghost. The command does not require a local Stripe
CLI installation or stripe login. Never commit .env or Stripe credentials.
Stripe CLI renders events at the account's default API version rather than the version Ghost pins. The command warns about this difference, and Ghost logs an error when it receives a mismatched event.
- Start
pnpm dev:stripe. - Connect a Stripe test-mode account in Ghost Admin under Settings → Tiers. Ghost registers the temporary webhook endpoint when the connection settings are saved. Follow the development log's instruction to restart if registration could not happen during the first connection.
- Sign up for a paid membership through the local site's Portal using a
Stripe test card, such as
4242 4242 4242 4242with any future expiry date and any three-digit CVC. - Confirm that the member becomes paid in Admin. This verifies that Ghost received and processed the webhook.
Automated browser tests must use the E2E suite's fake Stripe service rather than a real account:
test.use({stripeEnabled: true});This gives the test an isolated Ghost environment, fake Checkout page, Stripe test service, and signed webhook delivery. See the E2E Stripe fixture guide and the subscription lifecycle test for the current helpers and an example.
For the implementation behind Stripe Connect, tier creation, and subscription checkout, see Stripe flows.