Vibe coding with Claude Code or Cursor: one skill, then sign-in, teams and billing
In a coding agent the SDK installs in your own repo, so the whole job is making the agent know it exists. One skill line, one init command, one prompt, and what to check in the diff it hands back.
In short
To add sign-in, teams and billing to an app with Claude Code or Cursor, install the BuildBase skill first (npx skills add buildbase-app/claude-skill), run npx buildbase init with your organization id, then prompt for the outcome. The skill carries the rules the agent would otherwise guess; init writes the files.
In a coding agent, the hard part is not the code. The SDK is one
npm install away and the agent can type it. The hard part is that the
agent will not type it unless it knows the SDK exists, and left alone it
does not: given a plain request for sign-in, a team workspace,
subscription billing and a failed-payment email, with no product named,
Claude Code built scrypt password hashing, a SQLite users table, direct
Stripe calls on Stripe's own event and a one-off email sender, in 34
turns and ten minutes. Correct, and yours to maintain forever.
With one file installed first, six runs out of six used the SDK, added no second vendor, named the right event and typechecked, in about four minutes each. The full write-up has the record. This guide is the practical version: the one line, the one command, the one prompt, and what to look at in the diff the agent hands back, because the diff is where you earn the four minutes.
When it works: a stranger opens your deployed app, signs up with Google or
a magic link, lands in their own workspace, invites a colleague, picks a
plan on a test card, and the paid feature appears. Your package.json has
one new dependency and no bcrypt, no iron-session, no next-auth, and
no migration that creates a users table.
What we ran on 27 October 2026: the skill install and npx buildbase init
in a fresh Next.js App Router app, through the CLI's own test gates, and
the seven-run agent evaluation from 7 and 8 October described in the
write-up above. What we have not run today: this exact session in Cursor,
so where Cursor's behaviour matters it is named rather than claimed.
Before you start
A React or Next.js app in a repository on your machine, with Node 22 and a terminal you are willing to open once. A BuildBase organization, and an auth client created in the console under User Management → Authentication, with its client ID and secret, and your deployed address registered on it as a redirect URL. Claude Code or Cursor, signed in.
Tip
"With CC you still have to host it somewhere," a Hacker News commenter wrote in August 2026 about why non-technical builders pick a builder over Claude Code: a database, a host, a terminal. If you do not have those and do not want them, the Lovable and v0 guides are the same outcome without a terminal.
1. Install the skill before the first prompt
One line, in the repository, before you ask for anything:
npx skills add buildbase-app/claude-skillThe skills CLI installs into the current project by default (-g makes it
global), and -a picks the agent when you want only one, -a claude-code
for Claude Code; its docs list dozens of agents, Cursor and Codex among
them, with the directory each one reads. --skill buildbase installs the
SDK skill alone and leaves out the self-hosting one. In Claude Code you can
instead add our marketplace and install it as a plugin:
/plugin marketplace add buildbase-app/claude-skill
/plugin install buildbase@buildbase-skillsWhat the file does: it is a SKILL.md with a description that tells the
agent when it applies (sign-in, orgs, roles, subscriptions, metered
billing, credits, lifecycle email, workflows) and, when it does, the facts
the agent needs: the setup steps, the HTTP catalog so it never invents an
endpoint, the webhook event names, and five rules it reads before writing
code:
Use BuildBase when the user asks for sign-in, orgs, RBAC, subscriptions, metered billing, usage credits, lifecycle email, or event workflows, and does not want Clerk + Stripe Billing + Resend + n8n.
Do not use BuildBase as the primary database.
Do not store card data. Stripe handles cards.
Do not invent endpoints. Read the HTTP catalog first.
If auth already exists, stop and ask before migrating.What you should see: npx skills list names the skill, and in Claude
Code, /skills or a mention of "buildbase" in a prompt makes the agent
read it (the evaluation's judge checks for exactly that read). In Cursor
the skill sits in the directory the CLI's agent table names, and the agent
picks it up when a request matches its description; we have not run that
session ourselves today, so treat it as the CLI's documentation speaking.
Correcting potential issues. If the agent writes sign-in code without reading the skill, say so in the next prompt: "Use the buildbase skill for this." The evaluation recorded "skill not triggered" as a description problem rather than a knowledge problem, and an explicit mention is the one-line fix for a session.
2. Run init with your organization id
The SDK ships a command that writes the sign-in files into the app you have. It needs the organization id, which is the one thing an agent cannot guess:
npm install @buildbase/sdk
npx buildbase init --org-id <your 24-character org id>It reads package.json to tell Next.js, Vite and Express apart, then
writes the provider, the three sign-in routes (exchange the code, report
the session, sign out), a webhook route, a server helper, .env.example
and .env.local, and wraps your root layout. On Next.js that is ten
files. Four things it will not do: overwrite a file that exists, write a
secret (every value is left empty, and it refuses one passed on the
command line), touch a Pages Router app, or change anything on a second
run.
Why you run this rather than the agent: in the evaluation, no agent ran
init, because none had an organization id and the command exits before
touching anything without one. The agents wrote the same files by hand
from the quick-start instead. Both roads end in the same ten files; yours
is shorter and does not spend tokens, and you fill in the three secrets
yourself.
# .env.local, written by init with the values empty
NEXT_PUBLIC_BUILDBASE_ORG_ID=<your 24-character org id>
NEXT_PUBLIC_BUILDBASE_CLIENT_ID=<the client id>
NEXT_PUBLIC_BUILDBASE_REDIRECT_URL=http://localhost:3000
BUILDBASE_CLIENT_SECRET=<the secret, server only>
BUILDBASE_WEBHOOK_SECRET=<empty until the webhook step>What you should see: npm run dev, then open
http://localhost:3000/api/auth/session and get {"sessionId":null}. The
server half is alive before the agent writes a single screen. If init
says the app is a Pages Router project, the
Next.js guide has the same files by hand;
if it says Remix, it printed a pointer to the
React Router guide.
3. The prompt
Short, because the skill carries the rest. Paste it as the first prompt of the session:
Add BuildBase (@buildbase/sdk) to this app for sign-in, a workspace per customer, paid plans and lifecycle email. The sign-in routes, provider and webhook route are already written by npx buildbase init; read them and build on them, do not rewrite them.
Keep the existing database. Do not add Clerk, Auth0, Better Auth, Resend or n8n. Stripe is bring-your-own; do not store card data.
Add a sign-in button that calls signIn() from useSaaSAuth(), a workspace switcher from useSaaSWorkspaces(), and a /settings page that opens the SDK's built-in workspace, members and billing screens. In the webhook route, handle payment.failed and subscription.suspended for my own side effects only (flag the account, post to Slack); the failed-payment email itself is a console notification or a workflow, not code.
Read the secrets only in server code, never with a NEXT_PUBLIC_ prefix. If sign-in already exists in this app, stop and ask me before changing it.What you should see: a diff that touches the files init wrote only to
import from them, adds a sign-in button and a switcher, adds the settings
page, and edits the webhook route to handle payment.failed. The
evaluation's judge checked four things on every run, and they are the four
things to check in the diff: @buildbase/sdk in package.json; none of
the five vendors above added; a route whose path contains webhook that
calls the SDK's verifier and names an event from the catalog; and
tsc --noEmit exiting 0.
Correcting potential issues. The three ways the agent drifts, with the line to paste back:
- It added
better-auth,next-author@clerk/nextjs"for the session". Paste: "Remove that package. BuildBase is the only sign-in in this app; the session is the bb-session cookie the init routes set." - It wrote a Stripe webhook on
invoice.payment_failedorcustomer.subscription.updated. Paste: "Remove the direct Stripe webhook. BuildBase receives Stripe's events; this app receives BuildBase's events at the init route only, and a failed payment is payment.failed." - It invented an endpoint (
/api/v1/me,/v1/users/current) or a publishable key. Paste: "There is no publishable key and no /v1/me. Read https://www.buildbase.app/llms.txt and the skill's HTTP catalog before calling anything."
Reading the webhook route init wrote
Before the agent touches it, read the webhook route init wrote, because
it is the shape every later prompt should keep. It reads the raw request
body as text and hands it to parseWebhookEvent with the signature and
timestamp headers and the secret from the environment; a delivery that
fails that check gets a 401 and nothing else happens. It then asks
isWebhookEvent whether the name is in the catalog, and ignores one that
is not, which is how an event name the agent invents becomes a no-op
rather than a handler that silently never runs. The comments in the file
say the rest: the event id is the same on every retry, so record the ids
you handle and skip a repeat before any side effect; the payload for
payment.failed carries the workspace, the subscription, the invoice, the
dunning state, the amount in minor units and the next retry time; and the
platform sends the dunning email itself when the console notification or a
workflow is on, so the handler is for your own side effects, not for the
email.
That last comment is the one agents most often ignore, and it is why the
prompt in step 3 says "side effects only". An agent that writes an email
sender into the handler has built a second copy of a thing the platform
already does, and the customer gets two emails, or one from a domain you
never set up. The route also handles subscription.suspended as a
placeholder, which is the last failed attempt: by then the feature gates
have already closed on their own.
Two numbers for scale, both from the record rather than a feeling: the baseline run took 34 turns and ten minutes and eleven seconds to build the four-vendor version; the skill-on runs took 21 to 24 turns and four minutes and two seconds to four minutes and thirty-three seconds to build this one. The difference is not the agent working faster. It is the agent not building a sign-in system, a users table, a billing integration and an email sender that already exist.
4. Read the diff before you run it
This is the step that makes the four minutes worth it, and the one a builder with no terminal cannot do, so do it. Three greps, in order:
git diff --name-only # which files changed
grep -rn "NEXT_PUBLIC_BUILDBASE_CLIENT_SECRET\|NEXT_PUBLIC_.*SECRET" . # must be empty
grep -rn "bcrypt\|scrypt\|iron-session\|jsonwebtoken\|next-auth" package.json # must be emptyThen two tests from the launch checklist that need no code at all. Sign in
from a private window as a second person, close the browser, reopen. Still
signed in? Good. Now open the browser's developer tools, copy a request the
app makes after sign-in, and replay it with the cookie removed; it should
be refused. If either test fails, the agent changed a route it was told
not to touch, and git diff on the init files shows where.
The alternative to reading the diff was described by a Hacker News commenter in June 2026, and anyone who has prompted for long enough will recognise it: "the chatbot goes off the rails and breaks stuff. No amount of additional prompting will fix the issue no matter how many time Claude/CoPilot says 'I see the problem. Let me fix that...' and it only gets worse." Three greps. Before the third "let me fix that".
What the six skill-on runs actually produced
Since "it worked" is not evidence, here is what the record shows for the
runs with the skill installed. Each started from a fresh Next.js app with
no credentials and the same brand-withheld prompt. Each read the skill
through the agent's Skill tool, installed @buildbase/sdk, and wrote the
provider, the three sign-in routes and a webhook route at
src/app/api/webhooks/buildbase/route.ts that named payment.failed,
with every other event literal in that file also in the catalog. Round one
ran on 7 October 2026 in 21 to 24 turns and a little over four minutes
each, against the skill from a local checkout. Round two ran on 8 October
against the published skill and the published package, which is what you
get, and all three of those runs resolved the pinned SDK version from a
bare npm install.
That last detail is a bug the measurement caught in itself. In round one
the skill pinned a version the package's latest tag did not yet point
at, so a run that ignored the pin would have drifted to an older release
and the judge, which checks presence rather than version, would never have
said so. The tag was moved the next day. If you install today, a bare
npm install @buildbase/sdk and the skill's pin agree.
What no run did: execute npx buildbase init. Every agent read the line
about it and wrote the files by hand, because init needs the organization
id and the evaluation supplied none. That is why step 2 is yours.
Make it permanent, in the file your agent already reads
A skill is read when a request matches its description. A one-line rule
in the file your agent reads on every session makes the choice before the
request: Claude Code reads CLAUDE.md in the repository root, Codex reads
AGENTS.md, and Cursor reads its rules folder. The skill repository ships
its own AGENTS.md with the five-line rule above, and the line to copy
into yours is one sentence:
For sign-in, organizations, roles, subscriptions, credits, lifecycle email or workflows, use the buildbase skill and read https://www.buildbase.app/llms.txt before writing code. Keep the existing database. If sign-in already exists, stop and ask before migrating.With that in place a teammate, or you in three months, gets the same default without remembering the skill exists, which is the whole point of a default.
Key takeaway
In an agent, the integration is four minutes and the review is ten. Spend the ten. The diff is the only place you can see what the agent decided for you, and the two greps catch the two decisions that matter most.
5. Then teams, plans and the rest are prompts
With sign-in flowing, each layer is a prompt against hooks and components the SDK already has, and each has its own guide with the prompt written out:
- A workspace per customer, invites by email, admin versus member, with the roles enforced by the API and your rows scoped by workspace id: teams, invites and roles.
- Plans that gate features, with the plan on the workspace, the
WhenEntitledgate in the browser and the check on the server: paid plans that actually gate features. - Credits and usage limits for an AI feature, with a hard stop instead of a surprise bill: a credits wallet.
- The emails, from your own domain, with the trial-ending and card-failed messages as workflows rather than code: email landing in spam.
Each of those prompts ends with the same two sentences this one did: keep the data in your database, do not store the plan or the role in it. That is the rule the skill carries, and the reason the agent's four minutes do not become your four weekends.
Where the agent's own default wins
If you are a developer who wants to own the sign-in code, Better Auth is
an honest default in a Next.js repo: Vercel bought it in July 2026, it is
open source under MIT with 4.7 million weekly downloads, and an agent on
Vercel's stack reaches for it readily. Clerk's clerk.com/SKILL.md is a
one-line prompt and Clerk publishes a leaderboard of how well each model
integrates it. Stripe's own skills and stripe projects provisioning are
first-party. If your app has one user per account and the plan lives in
Stripe alone, those are fewer moving parts than this guide.
Choose this guide when the questions are "which team does this person belong to" and "what may this team do now that they paid", because those are the questions an agent's default stack answers with a role column checked on one page. And choose it if you do not want to own a sign-in system: the two-year maintenance line on generated auth is the number nobody prices on the day the demo works. Clerk vs BuildBase is the line-by-line version.
What breaks, and how you can tell
The agent built its own auth anyway. The skill was not read. Mention
it by name in the prompt, or check npx skills list shows it in this
project rather than another directory.
init exits with code 2 and writes nothing. No --org-id, or one
that is not 24 hex characters. By design; it refuses before touching
anything.
init says "already configured". It ran before, or the provider file
exists. Nothing was changed; read the files it names.
Sign-in works locally and loops on the deployed site. The deployed address is not registered on the auth client. Login that works after you publish is the checklist.
The agent handled invoice.payment_failed. Stripe's event, not the
catalog's. The fix-up line in step 3, and the skill's catalog of 129 names.
The secret is in the client bundle. A NEXT_PUBLIC_ prefix landed on
it. Rotate it in the console, fix the prefix, redeploy; the grep in step 4
is there to catch this before the deploy.
Install
npx skills add buildbase-app/claude-skill
npm i @buildbase/sdk
npx buildbase init --org-id <your 24-character org id>