Guides
Architecture
How the extension, the server, and Whop divide responsibility.
The design rule is simple: the extension is a dumb client, and the server is the only thing that decides access.
The pieces
- The extension holds a Whop OAuth token. It renders the popup and calls the backend, but it never trusts its own copy of "do I have access."
- The Next.js server owns the secrets (the Whop API key) and re-checks access with Whop on every gated request.
- Whop answers "does this user have access to this product" from their real memberships.
The access flow
- The user signs in through Whop OAuth, run from the extension's background service worker.
- The extension sends the user's token to
POST /api/extension/entitlements. - The server resolves the token to a Whop user, then calls Whop's access endpoint for the configured resource.
- The server returns an entitlement snapshot, and the popup uses it to show the locked or unlocked UI.
- When the user runs the paid feature, the extension calls
POST /api/extension/gated-resource, which re-checks access and returns402if the user has not paid.
Why re-check every time
The cached snapshot in the extension is a convenience for the UI, never a security boundary. A membership can be cancelled or refunded at any moment, so the server asks Whop again on every gated call. A revoked user stays visually "unlocked" only until their next request.