Stripe Apps
fossasia/eventyay
A skill your agent uses when building, modifying, or reviewing a Stripe App — or when the user describes something that implies one (e.g.
Clerk Billing for subscription management - render Clerk's PricingTable and in-app checkout drawer, configure subscription plans, seat-limit plans for B2B, feature entitlements with has(), and…
$ npx skills add geekskai/blog --skill clerk-billing -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install geekskai/blog clerk-billing --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/geekskai/blog.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/clerk-billing .claude/skills/clerk-billing && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "clerk-billing" agent skill from https://github.com/geekskai/blog/tree/main/.agents/skills/clerk-billing into .claude/skills/clerk-billing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clerk-billing", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/geekskai/blog/tree/main/.agents/skills/clerk-billingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add geekskai/blog --skill clerk-billing -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install geekskai/blog clerk-billing --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/geekskai/blog.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/clerk-billing .agents/skills/clerk-billing && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "clerk-billing" agent skill from https://github.com/geekskai/blog/tree/main/.agents/skills/clerk-billing into .agents/skills/clerk-billing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clerk-billing", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add geekskai/blog --skill clerk-billing -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install geekskai/blog clerk-billing --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/geekskai/blog.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/clerk-billing .cursor/skills/clerk-billing && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "clerk-billing" agent skill from https://github.com/geekskai/blog/tree/main/.agents/skills/clerk-billing into .cursor/skills/clerk-billing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clerk-billing", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/geekskai/blog.git --path .agents/skills/clerk-billing--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add geekskai/blog --skill clerk-billing -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install geekskai/blog clerk-billing --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/geekskai/blog.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/clerk-billing .gemini/skills/clerk-billing && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "clerk-billing" agent skill from https://github.com/geekskai/blog/tree/main/.agents/skills/clerk-billing into .gemini/skills/clerk-billing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clerk-billing", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install geekskai/blog clerk-billingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add geekskai/blog --skill clerk-billing -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/geekskai/blog.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/clerk-billing .github/skills/clerk-billing && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "clerk-billing" agent skill from https://github.com/geekskai/blog/tree/main/.agents/skills/clerk-billing into .github/skills/clerk-billing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clerk-billing", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add geekskai/blog --skill clerk-billing -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install geekskai/blog clerk-billing --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/geekskai/blog.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/clerk-billing .opencode/skills/clerk-billing && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "clerk-billing" agent skill from https://github.com/geekskai/blog/tree/main/.agents/skills/clerk-billing into .opencode/skills/clerk-billing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "clerk-billing", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
clerk-billingClerk Billing for subscription management - render Clerk's PricingTable and in-app checkout drawer, configure subscription plans, seat-limit plans for B2B, feature entitlements with has(), and…
Clerk Billing is an agent skill from geekskai/blog. Clerk Billing for subscription management - render Clerk's PricingTable and in-app checkout drawer, configure subscription plans, seat-limit plans for B2B, feature entitlements with has(), and billing webhooks. Use for SaaS monetization, plan gating, checkout flows, trials, invoicing, and subscription lifecycle management.
Its SKILL.md is about 5.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 7 other files, including reference files (for example `evals/evals.json`, `references/b2b-patterns.md` and `references/b2c-patterns.md`). Compatibility notes: Requires NEXTPUBLICCLERKPUBLISHABLEKEY, CLERKSECRETKEY, and CLERKWEBHOOKSIGNINGSECRET. Billing must be enabled in Clerk Dashboard → Billing. Development…
It sits in Backend & APIs, covering Webhooks. It works with Stripe. The repository describes itself as: 🚀 2026 Most Popular FREE Blog Template! Next.js 14, Zero Code - Just Write & Deploy | 2026最火免费博客模板!支持Markdown,一键部署,极致性能!⚡️ ✨ Write in Markdown, get your professional blog in…. The licence is MIT.
10 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit e5554c5. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
WebFetchFrom allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript and bash).
From the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
dashboard.clerk.comAlso links to:
clerk.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
CLERK_WEBHOOK_SIGNING_SECRETFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Requires NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, and CLERK_WEBHOOK_SIGNING_SECRET. Billing must be enabled in Clerk Dashboard → Billing. Development instances can use the shared Clerk development gateway; production instances require a Stripe account for payment processing.
From compatibility in the SKILL.md frontmatter.
Clerk Billing loads about 5.1k tokens when it runs, and up to ~11k if it reads all its reference files. Until then it costs about 85 tokens; SKILL.md has 1,706 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from geekskai/blog at commit e5554c5, republished under its MIT licence (© geekskai). 1,706 words, ~5,091 tokens.
.claude/skills/clerk-billing/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.STOP, prerequisite. Billing must be enabled before any
<PricingTable />,<CheckoutButton />,has({ plan }), orhas({ feature })usage works. Two paths: (1) Dashboard → Billing → Settings, or (2)clerk enable billing(see "Agent-first: Programmatic billing config" below). Enabling auto-creates defaultfree_user/free_orgplans. Dev instances can use the shared Clerk development gateway (no Stripe account needed); production requires a Stripe account for payment processing only.Note: Billing APIs are still experimental. Pin your
@clerk/nextjsandclerk-jspackage versions. Seeclerkskill for the supported version table.
Enable Billing, via Dashboard → Billing → Settings or clerk enable billing (see Agent-first section). Skipping this throws cannot_render_billing_disabled in dev and renders empty in prod.
Create plans in the matching tab, Dashboard → Billing → Plans. Two tabs, slugs scoped per tab, not movable after creation:
<PricingTable /> (default for="user")<PricingTable for="organization" />Wrong-tab is the #1 cause of an empty <PricingTable />. Plans live in Clerk; not synced to Stripe.
Add features inside a plan, open the plan in Dashboard → Billing → Plans, use its Features section. Features are scoped per plan, not global. The same slug can attach to multiple plans; has({ feature: 'export' }) matches if the active plan contains that slug.
Render <PricingTable /> (pass for="organization" for B2B).
Gate access with has({ plan }) or has({ feature }) from auth().
Handle billing webhooks for subscription lifecycle.
| Action | URL |
|---|---|
| Enable Billing | https://dashboard.clerk.com/last-active?path=billing/settings |
| Create / edit plans | https://dashboard.clerk.com/last-active?path=billing/plans |
| Membership mode (B2C + B2B coexistence) | https://dashboard.clerk.com/last-active?path=organizations-settings |
| Edit features | Plans → click a plan → Features section (no direct URL) |
The full billing config (enable toggles, plans, features, plan-feature attachments) is editable via PLAPI without touching the Dashboard. Useful for agents seeding plans, replicating config across instances, or version-controlling billing structure.
Pre-req: project linked to the Clerk app (clerk auth login + clerk link, see clerk-setup).
clerk enable billing # both targets (default, auto-creates free_user + free_org plans)
clerk enable billing --for org # org only
clerk enable billing --for user # user onlyclerk config pull --keys billing > billing.jsonThis writes the current billing config (toggles + plans + features) for the linked instance to billing.json.
Edit billing.json to add/remove plans or features, then preview the diff and apply:
clerk config patch --file billing.json --dry-run
clerk config patch --file billing.jsonPass --instance prod to target the production instance instead of dev.
For one-shot plan/feature updates without a config file:
clerk api --platform PATCH /v1/platform/applications/<app_id>/instances/<ins_id>/config \
-d '{"billing":{"plans":[{"slug":"pro","name":"Pro","amount":2000,"currency":"usd","payer_type":"user","is_recurring":true}],"features":[{"slug":"export","name":"Export"}]}}'<PricingTable /> + billing webhooks, see clerk-webhooks skill for the lifecycle events.features map manipulation and plan-feature attachments (sync) are fully supported via the PLAPI billing config handler.| Task | Reference |
|---|---|
<PricingTable /> props, <CheckoutButton />, <Show> billing patterns | references/billing-components.md |
B2C patterns (individual user subscriptions, Membership optional prerequisite) | references/b2c-patterns.md |
| B2B patterns (org subscriptions, seat-limit plans, admin-gated billing UI) | references/b2b-patterns.md |
| Webhook event catalog, payload shapes, handler templates | references/billing-webhooks.md |
| Reference | Description |
|---|---|
references/billing-components.md | <PricingTable /> and subscription UI |
references/b2c-patterns.md | B2C subscription billing patterns |
references/b2b-patterns.md | B2B billing with organization subscriptions and seat-limit plans |
references/billing-webhooks.md | Subscription lifecycle event handling |
Use has({ feature: 'slug' }) when gating a specific capability, export, analytics, API access, audit logs.
Use has({ plan: 'slug' }) when gating a tier, showing the pro dashboard, checking org subscription level, redirecting free users.
| Scenario | Correct check |
|---|---|
| Gate the "Export CSV" button | has({ feature: 'export' }) |
| Gate the "Analytics" section | has({ feature: 'analytics' }) |
| Gate all of /dashboard/pro | has({ plan: 'pro' }) |
| Check if org has team subscription | has({ plan: 'org:team' }) |
| Gate SSO configuration | has({ feature: 'sso' }) |
When a user says "gate the export feature" or "gate analytics", always use has({ feature }). Only use has({ plan }) when the gate is the plan tier itself, not a specific capability within it.
Show available plans to users with a single component:
import { PricingTable } from '@clerk/nextjs'
export default function PricingPage() {
return (
<main>
<h1>Choose a plan</h1>
<PricingTable />
</main>
)
}<PricingTable /> automatically renders all plans configured in the Clerk Dashboard. Selecting a plan opens Clerk's in-app checkout drawer. No props needed for basic usage. For B2B, pass for="organization" to render org-level plans instead of user plans.
Gate by individual features, this is the preferred approach for specific capabilities:
import { auth } from '@clerk/nextjs/server'
export default async function AnalyticsPage() {
const { has } = await auth()
const canViewAnalytics = has({ feature: 'analytics' })
const canExport = has({ feature: 'export' })
return (
<div>
{canViewAnalytics && <AnalyticsChart />}
{canExport && <ExportButton />}
</div>
)
}Features are configured in Clerk Dashboard → Billing → Features and assigned to plans. Use has({ feature }) instead of has({ plan }) when gating granular capabilities, check the feature, not the plan.
Use useAuth() for client-side feature gating. Combine with server-side checks for full coverage:
'use client'
import { useAuth } from '@clerk/nextjs'
export function FeatureGatedUI() {
const { has, isLoaded } = useAuth()
if (!isLoaded) return null
const canExport = has?.({ feature: 'export' })
const canAnalytics = has?.({ feature: 'analytics' })
return (
<div>
{canAnalytics && <AnalyticsSection />}
{canExport ? <ExportButton /> : <UpgradeToExport />}
</div>
)
}Server Components use auth(), Client Components use useAuth(). Both support has({ feature }) and has({ plan }).
Gate access by subscription plan (use this for tier-level gates, not individual features):
import { auth } from '@clerk/nextjs/server'
import { redirect } from 'next/navigation'
export default async function ProDashboard() {
const { has } = await auth()
if (!has({ plan: 'pro' })) {
redirect('/pricing')
}
return <ProFeatures />
}Use useAuth() hook for client components:
'use client'
import { useAuth } from '@clerk/nextjs'
export function UpgradePrompt() {
const { has } = useAuth()
if (has?.({ plan: 'pro' })) {
return null
}
return (
<div>
<p>Upgrade to Pro to access this feature</p>
<a href="/pricing">View plans</a>
</div>
)
}Org plans can carry a seat limit (membership cap) that Clerk enforces at invite time. Use the org: slug prefix on org-side plan checks (e.g. has({ plan: 'org:team' })) to keep gating unambiguous. Render the B2B pricing page with <PricingTable for="organization" />, and use <OrganizationProfile /> for the org account billing UI.
See references/b2b-patterns.md for tiered plan naming, seat-limit invariants, admin-only billing, and webhook handlers.
Check specific plans with has({ plan }), or use useSubscription() for full subscription details in client components. Do not read plan information from sessionClaims directly, that is not the supported path.
Server component, check for specific plans:
import { auth } from '@clerk/nextjs/server'
export default async function AccountPage() {
const { has } = await auth()
const currentPlan = has({ plan: 'pro' })
? 'pro'
: has({ plan: 'starter' })
? 'starter'
: 'free'
return (
<div>
<h2>Current Plan</h2>
<p>You are on the {currentPlan} plan</p>
{currentPlan === 'free' && <a href="/pricing">Upgrade</a>}
</div>
)
}Client component, full subscription details via useSubscription():
'use client'
import { useSubscription } from '@clerk/nextjs/experimental'
export function SubscriptionDetails() {
const { data: subscription, isLoading } = useSubscription()
if (isLoading) return null
if (!subscription) return <a href="/pricing">Choose a plan</a>
return (
<div>
<p>Status: {subscription.status}</p>
{subscription.nextPayment && (
<p>Next payment: {subscription.nextPayment.date.toLocaleDateString()}</p>
)}
</div>
)
}
useSubscription()is for display only. For authorization checks (gating content or routes), always usehas({ plan })orhas({ feature }).
Gate API routes using auth():
import { auth } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'
export async function GET() {
const { has } = await auth()
if (!has({ plan: 'pro' })) {
return NextResponse.json({ error: 'Pro plan required' }, { status: 403 })
}
return NextResponse.json({ data: 'premium data' })
}Clerk event names differ from Stripe event names. Clerk billing webhooks use dot-notation and camelCase, not Stripe's underscore format.
There is no
subscription.canceledevent. Cancellation fires at the item level assubscriptionItem.canceled.
Intent Stripe event name Clerk event name Subscription created customer.subscription.createdsubscription.createdSubscription updated customer.subscription.updatedsubscription.updatedSubscription active (none) subscription.activeSubscription past due (none) subscription.pastDueSubscription item canceled customer.subscription.deletedsubscriptionItem.canceledSubscription item past due invoice.payment_failedsubscriptionItem.pastDueSubscription item updated (none) subscriptionItem.updatedSubscription item active (none) subscriptionItem.activeSubscription item upcoming renewal (none) subscriptionItem.upcomingSubscription item ended (none) subscriptionItem.endedSubscription item abandoned (none) subscriptionItem.abandonedSubscription item expired (none) subscriptionItem.expiredSubscription item incomplete (none) subscriptionItem.incompleteFree trial ending soon (none) subscriptionItem.freeTrialEndingPayment attempt created (none) paymentAttempt.createdPayment attempt updated (none) paymentAttempt.updatedAlways use Clerk's event names, never Stripe's, in
evt.typechecks.
Payload shape. Clerk billing webhook payloads are nested. The subscribing entity lives under
evt.data.payer(fields:user_id?,organization_id?). The plan info is on each item underevt.data.items[i].plan.slug. The subscription id is simplyevt.data.id. Subscription items do not carry asubscription_idfield back-reference, so insubscriptionItem.*handlers you identify the record by the item id (evt.data.id) or look up by payer plus plan.
Minimal handler to anchor the pattern (import from @clerk/nextjs/webhooks, verify, branch on Clerk event name):
import { verifyWebhook } from '@clerk/nextjs/webhooks'
import { NextRequest } from 'next/server'
import { db } from '@/lib/db'
export async function POST(req: NextRequest) {
let evt
try {
evt = await verifyWebhook(req)
} catch {
return new Response('Verification failed', { status: 400 })
}
if (evt.type === 'subscription.created') {
const { id, payer, items, status } = evt.data
const entityId = payer.organization_id ?? payer.user_id
const plan = items[0]?.plan?.slug
await db.subscriptions.upsert({
where: { subscriptionId: id },
create: { subscriptionId: id, entityId, plan, status },
update: { entityId, plan, status },
})
}
// Add more branches per the event catalog above (subscription.updated,
// subscriptionItem.canceled, subscriptionItem.pastDue, etc.)
return new Response('OK', { status: 200 })
}For the full template covering all 15 events, the TS type declarations from @clerk/backend, the proxy.ts public-route setup, and the subscription status value table, see references/billing-webhooks.md.
Let users manage their subscription from inside the app:
import { PricingTable } from '@clerk/nextjs'
import { auth } from '@clerk/nextjs/server'
export default async function BillingPage() {
const { has } = await auth()
const isPro = has({ plan: 'pro' })
return (
<div>
<h1>Billing</h1>
{isPro ? (
<div>
<p>You are on the Pro plan</p>
<PricingTable />
</div>
) : (
<div>
<p>Upgrade to access premium features</p>
<PricingTable />
</div>
)}
</div>
)
}<PricingTable /> renders differently for subscribed users, it shows the current plan and allows upgrades or cancellations, all through Clerk's in-app checkout drawer.
Plan slugs and feature slugs are defined in Clerk Dashboard → Billing. Common conventions:
| Tier | Plan Slug | Example Features |
|---|---|---|
| Free | (no plan check needed) | basic features |
| Starter | starter | analytics, api_access |
| Pro | pro | analytics, export, team |
| Enterprise | enterprise | all features + sso, audit_logs |
Use lowercase slugs matching what you define in the dashboard.
| Scenario | Who subscribes | Plan check |
|---|---|---|
| B2C SaaS | Individual user | has({ plan: 'pro' }) on user session |
| B2B SaaS | Organization | has({ plan: 'org:team' }) on org session |
| Seat-limited B2B | Organization | Plan has a seat cap; pricing is per-plan, not per-member, tier your plans for bigger orgs |
For B2B, ensure the user has an active org session. The has() check evaluates the active entity (user or org).
Clerk renders its own checkout drawer automatically through <PricingTable /> and <CheckoutButton />. Plans and pricing live in Clerk. To trigger checkout from a server action, redirect to a page that renders <PricingTable />:
'use server'
import { redirect } from 'next/navigation'
export async function upgradeAction() {
redirect('/pricing')
}When you see any of these errors or symptoms, the fix is almost always a Dashboard toggle, not a code change. Do not start editing components.
| Error / symptom | Root cause | Fix |
|---|---|---|
Clerk: 🔒 The <PricingTable/> component cannot be rendered when billing is disabled. (code: cannot_render_billing_disabled, dev only) | Billing is not enabled for this instance | Enable Billing at dashboard.clerk.com → Billing → Settings, or run clerk enable billing. |
<PricingTable /> renders empty | No plans, OR plan in the wrong tab (User vs Organization), OR Billing not enabled | Create plan in matching tab; pass for="organization" for B2B; check Billing Settings |
| Users can't subscribe to a personal plan on a B2C + B2B app | Membership required mode (default since 2025-08-22) disables personal accounts, signed-in users are forced into choose-organization and never land on a personal-subscription state | If you need personal + org subscriptions coexisting: Dashboard → Organizations settings → Membership optional |
| Can't find a Features page | Features are per-plan, not global | Dashboard → Billing → Plans → click plan → Features |
has({ plan: 'pro' }) always returns false after a successful checkout | Session token hasn't been refreshed to include the new plan | await clerk.session?.reload() or navigate to force a new session |
has({ plan: 'pro' }) returns false before any subscribe attempt | Plan slug mismatch (case-sensitive), OR Billing not enabled, OR payment gateway not connected in production | Verify slug in Dashboard → Billing → Plans; confirm Billing → Settings shows enabled + connected gateway |
has({ permission: 'org:x:y' }) returns false for a user who has the role | The Feature tied to that permission is not included in the organization's active Plan | Add the Feature to the Plan in Dashboard → Billing → Plans → Features |
| Webhook 401 / signature verification failed | CLERK_WEBHOOK_SIGNING_SECRET mismatch or route protected by middleware | Copy the Signing Secret from Dashboard → Webhooks; add the webhook route to createRouteMatcher(['/api/webhooks(.*)']) |
When Billing is enabled, has({ permission: 'org:posts:edit' }) returns false if the Feature associated with that permission is not included in the organization's active Plan, even if the user has the permission assigned via their role. This is by design: billing gates permissions at the feature level. Always ensure the required Feature is attached to the Plan in Dashboard → Billing → Plans → Features.
clerk-setup - Initial Clerk installclerk-orgs - B2B organizations (required for B2B billing and seat-limit plans)clerk-webhooks - Webhook signature verification and routing© geekskai, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (references) in .agents/skills/clerk-billing of geekskai/blog.
Open the folder on GitHubat commit e5554c5
Clerk Billing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Clerk Billing this skillgeekskai/blog | 103 | — | ~5.1k | Automated safety check: Pass | MIT | |
| Stripe Appsfossasia/eventyay | 1.7k | 1 repos | ~3.6k | Automated safety check: Pass | Apache-2.0 | |
| Stripe Best Practiceskanchengw/cnllm | 175 | 2 repos | ~925 | Automated safety check: Pass | Apache-2.0 | |
| Cashier Stripe Developmentluadotsh/lua | 343 | 1 repos | ~1.2k | Automated safety check: Pass | MIT | |
| Stripe Best Practicesfossasia/eventyay | 1.7k | 1 repos | ~1.7k | Automated safety check: Pass | Apache-2.0 | |
| Stripe Integrationwshobson/agents | 40k | 10 repos | ~1k | Automated safety check: Pass | MIT |
fossasia/eventyay
A skill your agent uses when building, modifying, or reviewing a Stripe App — or when the user describes something that implies one (e.g.
kanchengw/cnllm
Guides Stripe integration decisions — API selection (Checkout Sessions vs PaymentIntents), Connect platform setup (Accounts v2, controller properties), billing/subscriptions, Treasury financial…
luadotsh/lua
Handles Laravel Cashier Stripe integration including subscriptions, webhooks, Stripe Checkout, invoices, charges, refunds, trials, coupons, metered billing, and payment failure handling.
fossasia/eventyay
Guides Stripe integration decisions across development and test environment planning (separate sandboxes vs the shared test mode sandbox), API selection (Checkout Sessions vs PaymentIntents)…
wshobson/agents
Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks.
waynesutton/builder-skills
Adds HTTP endpoints in convex/http.ts: webhook receivers with signature checks, REST style routes, CORS, auth headers, streaming responses, and file uploads over HTTP.
geekskai/blog
React SPA auth patterns with @clerk/react for Vite/CRA - ClerkProvider setup, useAuth/useUser/useClerk hooks, React Router protected routes, custom sign-in flows.
geekskai/blog
React Router v7/v8 patterns with Clerk — rootAuthLoader, getAuth in loaders, clerkMiddleware, protected routes, SSR user data, org switching.
geekskai/blog
TanStack React Start auth patterns with @clerk/tanstack-react-start - createServerFn, beforeLoad guards, loaders, Vinxi server.
geekskai/blog
Implement Clerk authentication for native Android apps using Kotlin and Jetpack Compose with clerk-android source-guided patterns.
geekskai/blog
Astro patterns with Clerk — middleware, SSR pages, island components, API routes, static vs SSR rendering.
geekskai/blog
Chrome Extension auth with @clerk/chrome-extension -- popup/sidepanel setup, syncHost for OAuth/SAML via web app, createClerkClient for service workers and headless extensions, stable CRX ID.
Works with
Categories
Clerk Billing for subscription management - render Clerk's PricingTable and in-app checkout drawer, configure subscription plans, seat-limit plans for B2B, feature entitlements with has(), and…. Clerk Billing is an agent skill from geekskai/blog. Clerk Billing for subscription management - render Clerk's PricingTable and in-app checkout drawer, configure subscription plans, seat-limit plans for B2B, feature entitlements with has(), and billing webhooks.
Clerk Billing fits situations like: saaS monetization; subscription lifecycle management.
Run `npx skills add geekskai/blog --skill clerk-billing -a claude-code`. Or copy the skill folder (.agents/skills/clerk-billing in geekskai/blog) into .claude/skills/clerk-billing in your project. Claude Code loads it when a task matches its description.
Run `npx skills add geekskai/blog --skill clerk-billing -a codex`. Or copy the skill folder (.agents/skills/clerk-billing in geekskai/blog) into .agents/skills/clerk-billing in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add geekskai/blog --skill clerk-billing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/clerk-billing, .gemini/skills/clerk-billing, .github/skills/clerk-billing and .opencode/skills/clerk-billing in your project.
Going by SKILL.md and its folder, Clerk Billing needs credentials named CLERK_WEBHOOK_SIGNING_SECRET. Our summary lists: A credential in NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY; A credential in CLERK_SECRET_KEY. Its frontmatter pre-approves these tools: WebFetch. Compatibility (from SKILL.md): Requires NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, and CLERK_WEBHOOK_SIGNING_SECRET. Billing must be enabled in Clerk Dashboard → Billing. Development instances can use the shared Clerk development gateway; production instances require a Stripe account for payment processing..
SKILL.md names 2 domains. In commands or code: dashboard.clerk.com; the agent is likely to contact it when it follows the instructions. As links in the text: clerk.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Clerk Billing is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.1k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 5.5k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Clerk Billing: Stripe Apps (fossasia/eventyay, 1.7k stars), Stripe Best Practices (kanchengw/cnllm, 175 stars), Cashier Stripe Development (luadotsh/lua, 343 stars) and Stripe Best Practices (fossasia/eventyay, 1.7k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
geekskai (a GitHub user) maintains it in geekskai/blog, which has 103 GitHub stars. The repository holds 20 skills in this directory. The repository was last updated on October 7, 2026.
Source: geekskai/blog on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.