# Add login, teams and paid plans to a Bolt.new app, and keep Bolt Cloud or Supabase for your data

> Bolt runs Node in your browser tab, so the three sign-in routes answer inside the preview. Where the live copy of them runs is the one decision this guide is built around. Read on 27 October 2026.

- Source: https://www.buildbase.app/guides/add-login-teams-and-paid-plans-to-a-bolt-app
- Section: Guides
- Author: Dharmendra Jagodana
- Published: 2026-10-28

## In short

To add login, teams and paid plans to a Bolt.new app, ask Bolt for the @buildbase/sdk package and the three sign-in handlers from the Vite guide, keep the secret out of the browser and GitHub, and run the live handlers on a host that runs functions. Data stays in Bolt Cloud or Supabase; teams and plans are SDK calls.

You are adding real sign-in, a workspace per customer, paid plans and the
email that goes out when a card fails to an app Bolt built for you, without
moving your data out of Bolt Cloud or your Supabase project. When it works,
a stranger opens your live address in a private window, signs up with
Google or a magic link, lands in their own workspace, invites a colleague
who gets an email, picks a plan on a test card, and the feature they paid
for appears without a reload. The client secret never reaches the browser
and never reaches GitHub.

Bolt is different from the other builders in one way that matters here,
and it cuts both ways. Bolt runs Node in your browser tab (its supported
technologies page says "Node.js for the backend", JavaScript only, no PHP
or Python), so the three small sign-in routes this guide adds answer inside
the preview, where you can see them work before you publish. The other
edge of it: the preview's server is your tab, and the live site needs a
server of its own. Where that lives is the one decision this guide is built
around.

What we ran on 27 October 2026: the three handlers are the ones from
[BuildBase on Vite](/guides/buildbase-on-vite), which have been run end to
end in `vite dev` against a real organization on our local stack, and which
ran unchanged today as server routes inside the Cloudflare Workers runtime
for the [Lovable guide](/guides/add-login-teams-and-paid-plans-to-a-lovable-app).
What we have not run: anything inside Bolt itself. The Bolt-specific parts
of this guide (the preview, the token prices, Bolt Cloud's sign-in,
hosting, secrets and GitHub sync) are read from Bolt's help center today,
and the guide says so wherever a Bolt behaviour is the thing that decides
whether a step works.

> **Before you start:** A Bolt project, on any plan. A BuildBase organization, and an auth client
> created in the console under **User Management → Authentication**, with its
> client ID and secret. A GitHub account, for step 1's second route. A Stripe
> account, only when you reach plans.

> **Tip:** Bolt's own help center asks agents to treat it as the source of truth for how
> Bolt works. We did. Where this guide and a Bolt page disagree on a Bolt
> behaviour, the page is newer than this post, and wins.

## 1. Decide where the live sign-in server runs

Sign-in needs one thing a browser cannot hold: a secret. The hosted sign-in
page sends a person back to your app with a one-time code, and swapping
that code for a session uses the client secret, so the swap runs on a
server and the session comes back as an httpOnly cookie on your app's own
address. Three small routes do all of it: swap the code, report the
session, sign out.

During building, this is solved for you. Bolt's preview runs Node in the
tab, the Vite dev server runs there, and a small Vite plugin answers the
three routes, so the preview is a complete app. For the live site there
are two honest routes, and you should pick one before you prompt, because
the files differ.

**Route A: stay on Bolt hosting.** Bolt's Netlify page says "Bolt hosting
supports projects with a backend", and Bolt Cloud has server functions
that Bolt deploys for you. What no page in the help center says is the
address a server function answers on, or whether it shares your site's
address. The cookie only works if the route that sets it lives on the same
address as the app. So route A is a try, not a promise: ask Bolt to run the
three handlers as server functions, publish, and run the check in step 5.
If your live site answers the route with JSON, you are done and this is the
simplest setup there is. We have not published a project this way, so we
cannot tell you it works.

**Route B: keep building in Bolt, run the live site from GitHub.** Bolt's
GitHub integration is two-way: "every time you make a change that doesn't
break the project, Bolt creates a commit for you", and "it also checks
GitHub every 30 seconds for any updates made outside Bolt and pulls those
in". Connect the repository to Vercel, Netlify or Cloudflare, where each
handler is a one-line function file, and the live site is the same code
with a server that we know answers the routes. You keep working in Bolt;
the host rebuilds on every commit Bolt makes. The alternative Bolt offers
in one click, Netlify from the Publish menu, is not this: Bolt's own page
says Netlify there "can't host a database or a traditional backend", which
is the one-click static path, not a Netlify site built from your
repository.

One rule for route B that is easy to miss: Bolt's page says that when the
two sides conflict, "Bolt keeps your changes and overwrites the GitHub
version", and that merging branches is not supported in Bolt. So make
every change in Bolt, never in GitHub directly, and treat the repository
as the thing the host reads, not a second place to edit.

If your Bolt project is Next.js rather than Vite, the server is already in
the app. Bolt's terminal (not available in Safari, where previews are
hosted instead) should run `npx buildbase init --org-id <your org id>`,
which writes the route handlers for you, though we have not tried it
there; the [v0 guide](/guides/add-sign-in-teams-and-paid-plans-to-a-v0-app)
is the Next.js version of this page, and route B applies to hosting it.

What you should see: a decision, written down, and for route B a GitHub
repository connected from Bolt's project menu (it starts private, on
`main`) and imported into your host.

## 2. Register where people come back to

The hosted sign-in page sends people back to one exact address per
environment, so register them before you prompt: your live address with
`/sign-in` on the end, your custom domain with `/sign-in` if you have one,
and the address of the preview if you want to test sign-in there. An
address it was not told about is refused.

The preview is the awkward one. Bolt's preview opens in its own tab at an
address Bolt assigns, and that address can change when the project
restarts. Most people register the live address and the custom domain,
test sign-in there, and use the preview for everything else, which is what
we suggest. If you do want sign-in in the preview, open it in a new tab,
copy the address, register it with `/sign-in` on the end, and expect to do
it again after a restart.

This is also where Bolt's own sign-in keeps its version of the same
problem. Bolt Cloud's authentication page describes a Site URL, set to
`localhost:3000` by default, which "does not work for live applications",
and a comma-separated allow list of redirect patterns with wildcards, which
Bolt "usually updates" when you publish. Those settings govern Bolt Cloud's
sign-in, not this one, and the addresses you register on the BuildBase
client are the only ones that matter here. [Login that works after you
publish](/guides/login-that-works-after-you-publish) is the troubleshooting
page for either.

What you should see: the auth client in the console lists each address,
and the client secret has been shown once. Do not paste it into the Bolt
chat.

## 3. Ask Bolt for the package and the three handlers

Paste this prompt. It names the outcome, the rules, the files, and the one
thing that must never happen to the secret. Bolt installs the package in
the preview, and you can watch `npm install` run in its terminal.

```text
Use the @buildbase/sdk npm package to add BuildBase sign-in, a workspace per customer, paid plans and lifecycle email to this app.
Keep Bolt Cloud (or my Supabase project) as the database; BuildBase is not the primary database. Do not add Clerk, Auth0, Resend or n8n, and do not enable Bolt Cloud's own sign-in. Stripe is bring-your-own; do not store card data.
Read https://www.buildbase.app/llms.txt first and do not invent endpoints. Take the files from https://www.buildbase.app/guides/buildbase-on-vite unchanged:
- server/auth.ts with the guide's verify, session and signout handlers, byte for byte
- the buildbaseAuth Vite plugin in vite.config.ts, so the preview answers POST /api/auth/verify, GET /api/auth/session and POST /api/auth/signout
- api/auth/verify.ts, api/auth/session.ts and api/auth/signout.ts as one-line Vercel function files that export the matching handler
- src/context/buildbase-provider.tsx from the guide, with import '@buildbase/sdk/css', wrapping the app in main.tsx
Put VITE_BUILDBASE_ORG_ID, VITE_BUILDBASE_CLIENT_ID and VITE_BUILDBASE_REDIRECT_URL in .env, add .env to .gitignore, and leave BUILDBASE_CLIENT_SECRET empty for me to fill in; never read it in the browser and never give it a VITE_ prefix.
If sign-in already exists in this app, stop and ask me before changing it.
```

For route A, replace the third line of the file list with: "run the three
handlers as Bolt server functions at /api/auth/verify, /api/auth/session
and /api/auth/signout on the published site, reading
BUILDBASE_CLIENT_SECRET from Bolt Secrets". For a Netlify or Cloudflare
host on route B, name that host's function folder instead of `api/`; the
handlers are plain `Request` to `Response` functions, and the Vite guide
says each host needs a one-line wrapper of its own.

What you should see: `@buildbase/sdk` in `package.json`, and five new or
changed files. The one that matters is the handler that swaps the one-time
code for a session, and it is the Vite guide's file. The provider is the
guide's too, and the part worth reading is the three callbacks, because
each one is a fetch to one of the routes:

```tsx
// src/context/buildbase-provider.tsx (trimmed; the Vite guide has the full file)
import '@buildbase/sdk/css';

import { ApiVersion } from '@buildbase/sdk';
import { SaaSOSProvider } from '@buildbase/sdk/react';

let cached: string | null | undefined;
export async function getSession() {
  if (cached === undefined) {
    cached = (await (await fetch('/api/auth/session')).json()).sessionId;
  }
  return cached ?? null;
}

export function BuildBaseProvider({ children }: { children: React.ReactNode }) {
  return (
    <SaaSOSProvider
      serverUrl={
        import.meta.env.VITE_BUILDBASE_SERVER_URL ||
        'https://api.console.buildbase.app'
      }
      version={ApiVersion.V1}
      orgId={import.meta.env.VITE_BUILDBASE_ORG_ID}
      auth={{
        clientId: import.meta.env.VITE_BUILDBASE_CLIENT_ID,
        redirectUrl: import.meta.env.VITE_BUILDBASE_REDIRECT_URL,
        callbacks: {
          getSession,
          handleAuthentication: async (code: string) => {
            const res = await fetch('/api/auth/verify', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ code }),
            });
            cached = (await res.json()).sessionId;
            return { sessionId: cached! };
          },
          onSignOut: async () => {
            await fetch('/api/auth/signout', { method: 'POST' });
            cached = null;
          },
        },
      }}
    >
      {children}
    </SaaSOSProvider>
  );
}
```

Then the first check, and it is the reason Bolt is a good place to do
this. Open the preview's address with `/api/auth/session` on the end. You
should see `{"sessionId":null}`: the server half is alive, inside the
preview, before any button exists. The Vite plugin answered it, running in
your tab.

**Correcting potential issues.** Read the change before you accept it. The
ways Bolt tends to drift, and the line to paste back:

- It switched on Bolt Cloud's sign-in as well, or wrote a `users` table for
  its own login. Paste: "BuildBase is the only sign-in in this app. Remove
  the other sign-in pages and the users table for them, and keep every
  other table."
- It put the secret in `.env` as `VITE_BUILDBASE_CLIENT_SECRET`, or read it
  in the provider. Paste: "BUILDBASE*CLIENT_SECRET is read only inside
  server/auth.ts. Remove every other reference and the VITE* prefix."
- It wrote the three routes as Bolt server functions when you asked for
  route B, or as Vercel files when you asked for route A. Paste the route
  you chose, by name, with the file list from the prompt.
- `/api/auth/session` returns the app's HTML in the preview. The Vite
  plugin is missing from `vite.config.ts`. Paste: "Add the buildbaseAuth
  plugin from the Vite guide to vite.config.ts, before react()."

## 4. The secret, and where it must never go

During building, the secret lives in `.env` as `BUILDBASE_CLIENT_SECRET`,
with no prefix, next to the three public `VITE_` values. The Node process
that reads it is the Vite dev server in your tab, which is yours, so this
is safe in the same way a `.env` on your laptop is safe. Two things keep it
that way.

**`.env` in `.gitignore` before GitHub.** Bolt commits every non-breaking
change to the repository on its own, and Bolt's secrets page says "never
store secrets in plain text in your code". A `.env` that is not ignored is
code as far as a commit is concerned. Check the file before you connect
the repository, not after.

**A separate auth client for building.** Create a second client in the
console, call it "Bolt preview", and use its secret in `.env`. If a preview
secret ever leaks, you regenerate that client's secret in the console and
nothing about the live site changes. The console shows a secret in full
once, when the client is created, so copy it then.

For the live site, the secret goes where the functions run. On route B
that is the host's environment variables: Vercel's project settings,
Netlify's site settings, Cloudflare's secrets. On route A it is Bolt's
Secrets page, reached from the database icon at the top of the project,
which Bolt's docs say is readable by server functions and, on an
individual account, by the project owner only. Prefixes stay the same
everywhere: three `VITE_` values the browser may see, one bare value it
never does.

```bash
# .env (building) and the host's environment variables (live)
VITE_BUILDBASE_ORG_ID=<your 24-character org id>
VITE_BUILDBASE_CLIENT_ID=<the client id>
VITE_BUILDBASE_REDIRECT_URL=https://your-app.example.com/sign-in
BUILDBASE_CLIENT_SECRET=<the secret, server only>
# VITE_BUILDBASE_SERVER_URL defaults to https://api.console.buildbase.app
```

The redirect value is the one that differs between building and live: the
preview's `.env` carries the preview address, and the host's variables
carry the live one. Vite inlines `VITE_` values at build time, so the host
builds with its own.

What you should see: `.env` listed in `.gitignore`, the repository on
GitHub without it, and the host's variables set. Then one more
`/api/auth/session` on the preview, still `{"sessionId":null}`, to confirm
nothing broke while you moved things around.

## 5. Publish, then run the thirty-second check

Publish (route A), or let the host build the latest commit (route B). Then
open your live address with `/api/auth/session` on the end, before you
click anything.

JSON back, `{"sessionId":null}`, means the server half lives on your live
address, and the rest of this guide follows. The app's HTML back means the
route is not there: on route A, Bolt hosting did not put the server
functions under your site's address, and route B is the answer; on route
B, the function files are not in the host's function folder, or the host
built an older commit. Nothing further works until this check passes, and
nothing further is worth debugging until it does.

Then sign in. Open the live address in a private window, click the button
that calls `signIn()` from `useSaaSAuth()`, and you are sent to the hosted
sign-in page, which offers whichever methods you switched on in the
console. Sign up with a second email. You come back to `/sign-in` on your
app, signed in.

Then the two checks a demo skips. Close the browser, reopen the site: still
signed in, because the cookie is good for 30 days, which is the
[default session length](/guides/token-expired-mid-request). Sign out, then
reload: asked to sign in again, because sign-out ended the session on the
server rather than clearing a value in the browser.

The methods are switches, not code: email and password, a magic link, an
email code, a phone sign-in code sent through your own Twilio account,
passkeys, Google, LinkedIn, GitHub, Microsoft, Apple, your own OIDC
provider, and Ethereum or Solana wallets. Turning on Google means creating
the client in Google's console and pasting two values; nothing in the Bolt
project changes.

**Correcting potential issues.** "The redirect address is not allowed" on
the hosted page: the address in `VITE_BUILDBASE_REDIRECT_URL` and the one
registered on the client differ, usually by a trailing slash, `www`, or the
`/sign-in` path. "Sign-in failed" after a correct code: the secret did not
reach the function; check the host's variables, and on route A, Bolt's
Secrets page. Sign-in works in the preview and not on the live site: the
live address is not registered, or the host built with the preview's
`.env` values because `.env` was committed after all.

## 6. A workspace per customer, and the colleague they invite

Every new user lands in their own workspace on first sign-in, with no setup
step. That is on by default for new organizations, and in your app it is
one component for the switcher and the hooks the SDK already has. Prompt
Bolt for the screens; the data model is already there.

```text
Add a workspace switcher to the app header using useSaaSWorkspaces() from @buildbase/sdk/react, and a /settings page that opens the SDK's built-in workspace, members and billing screens.
Members with the admin role may invite teammates by email; everyone else sees the member list read-only.
Do not create workspace, membership or role tables in Bolt Cloud or Supabase; BuildBase holds them.
```

What you should see: a switcher listing the workspaces the signed-in person
belongs to, with **Add team** creating another if you allow it. On the
members screen, inviting an address that has no account yet sends an email
with a link; the person signs up and lands in the workspace with the role
you chose. That flow has been in the SDK since version 0.0.71, and the
reasons an invite can be refused (a seat limit, an outsider policy) come
back as named errors rather than silence.

Why not let Bolt write the tables? Bolt's own security audit is better
than most at catching what goes wrong here: its help page says it checks
"that protected parts of your app require an account", that "users can't
do things you don't intend, like changing a price", and that keys are not
"sent to visitors' browsers". What no audit can check is which workspace a
row belongs to, because a generated `teams` table has no rule for that
until someone writes one, and the role column it adds is checked on one
page and nowhere else. The SDK's roles are enforced by the API, so a member
who types the address of an admin page is refused by the server, not just
by a missing menu item. Bolt Cloud's sign-in page, read today, mentions no
roles, teams or permissions for the people using your app, so whatever a
prompt builds here is built from scratch.

**Correcting potential issues.** If a member can see another workspace's
rows by changing an id in the address bar, Bolt wrote a page that reads
your database without scoping it. That is your data and your query, and
the next section is about it.

## 7. Your data stays where it is: the one honest wrinkle

Your tables stay in Bolt Cloud or in your Supabase project. The rule we
give every agent is "do not use BuildBase as the primary database", and it
applies here. Supabase's own post of 30 September 2025 says Bolt Cloud
backends run on Supabase, so the wrinkle is the same on both: row-level
security policies keyed to the old sign-in (`auth.uid()` and friends) do
not know who a BuildBase user is, because a BuildBase session is an opaque
id, not a token Supabase can read.

There are two ways through, and most apps want the first.

**Read and write through server routes.** A function on the host (or a
server function on route A) checks the BuildBase session and queries your
database with a server-side credential, scoped by the BuildBase user or
workspace id. This is the pattern generated apps should use anyway, because
it puts the permission check where it cannot be forged. The server SDK
makes the check one call:

```ts
// server/buildbase.ts
import BuildBase from '@buildbase/sdk';

const readCookie = (request: Request) =>
  (request.headers.get('cookie') ?? '').match(/(?:^|;\s*)bb-session=([^;]+)/);

export function bbFor(request: Request) {
  const match = readCookie(request);
  return BuildBase({
    serverUrl:
      process.env.VITE_BUILDBASE_SERVER_URL ||
      'https://api.console.buildbase.app',
    orgId: process.env.VITE_BUILDBASE_ORG_ID!,
    getSessionId: async () => (match ? decodeURIComponent(match[1]) : null),
  });
}
```

A route that needs the user calls `bbFor(request).users.getProfile()`, and
a missing or expired session comes back as an error rather than a guess.

**Mint a Supabase-shaped token for browser queries.** If pages query
Supabase directly from the browser and you want the existing policies to
keep working, add one more function: it validates the session with the
server SDK, then signs a short-lived HS256 token with your Supabase
project's JWT secret, with `sub` set to the BuildBase user id and `role`
and `aud` set to `authenticated`, and the browser passes it to Supabase as
the bearer token. `auth.uid()` then matches `sub`, so store the BuildBase
user id in your owner columns. The step-by-step is in
[the skill repository](https://github.com/buildbase-app/claude-skill/blob/main/distribution/supabase-jwt.md).
You own that route and its refresh schedule. The platform change that would
make it unnecessary, BuildBase publishing signing keys so Supabase can
verify a user token directly, is recorded as not built.

Run Bolt's database review after a change this size. Its help page says it
"checks your database rules and permissions and flags anything that could
make your data insecure, like a permission rule that allows anyone to read
a table", and the full audit is a free button in the Publish menu
(prompting Bolt to audit costs tokens; the button does not).

## 8. Plans people can pay for, and the email when a card fails

Plans, prices and trials live in the BuildBase console and sync to your own
Stripe account at Stripe's rates, with a 0% platform fee, and no card data
touches your app. The part that generated apps get wrong is what happens
after the payment, so this step is mostly about the webhook route and the
feature flag.

In the console, create two plans, Launch and Pro, say, each with a 7-day
trial and a monthly and a yearly price. Then the webhook. It is a fourth
function, and this is the prompt for it:

```text
Add api/webhooks/buildbase.ts as a POST function. Verify the signature with parseWebhookEvent from @buildbase/sdk on the raw request body, using BUILDBASE_WEBHOOK_SECRET from the host's environment variables. Handle payment.failed with our own side effects only (flag the workspace, post to Slack); the platform sends the customer's email itself. Ignore other events.
Gate the export feature behind a BuildBase feature flag tied to the Pro plan, checked in a function. Do not store the plan in Bolt Cloud or Supabase.
```

Point an endpoint in the console at
`https://your-app.example.com/api/webhooks/buildbase`, add its signing
secret to the host as `BUILDBASE_WEBHOOK_SECRET`, and publish.

What you should see: subscribe on a test card and the Pro feature appears
without a reload, because the flag follows the workspace's plan. Let the
test card fail on renewal and the email goes out from your sending domain,
because `payment.failed` is one of the 129 events in the catalog and the
console's notification or a workflow sends it; the route in your app is
for whatever you want to happen besides. The console's delivery log shows
each attempt, and a delivery your server was down for is retried up to
five times over about two and a half minutes.

Compare that with Bolt's own Stripe integration, read today: one-time
payments and subscriptions, with "automatic webhook handling for payment
events", and the page says Bolt "automatically handles webhook endpoint
registration and signature verification", on a project that uses Bolt
Database or Supabase and has sign-in set up, and not with Firebase. That is a good integration for
selling one thing to one person. What the page does not describe is a plan
that belongs to a team, seats, limits, trials that end without a card, or
credits, so if a plan has to change what the app does for a whole
workspace, [entitlements rather than flags](/blog/entitlements-are-not-feature-flags)
is the ten-minute read before you prompt.

## Where Bolt's built-in wins

Keep Bolt Cloud's sign-in when your app has one user per account and you
need nothing after login. It is zero-config inside Bolt, it lives in the
same place as your database, its Site URL and redirect list are updated
for you when you publish, and nothing leaves Bolt hosting. Keep Bolt's
Stripe integration when you sell one subscription to one person and want
the webhooks registered and verified without touching them. And keep
Bolt's security audit in either case; it is free from the Publish menu,
and it checks things (a changed price, a key in the browser) that this
guide's setup does not make go away.

Choose BuildBase when the question is "what may this team do now that they
paid": a workspace per customer, invites and roles enforced by the API,
plans with versions, feature flags tied to the plan, credits with a hard
stop, and the lifecycle email, from one SDK, with your data staying in
Bolt Cloud. That is the layer Bolt's help center does not reach today, and
[the launch checklist](/guides/vibe-coded-app-launch-checklist) is the
twenty-item version of why it matters before strangers arrive.

> **Key takeaway:** On Bolt the preview is a real server, so the three routes work before you
> publish. The whole job is making sure the live site has a server too, and the
> thirty-second check in step 5 tells you whether it does.

## What this costs in tokens

Bolt prices building by tokens. On 27 October 2026 its pricing page lists
Free at $0 with 1M tokens a month and a 300K daily cap, Pro at $25 a month
with 10M tokens, rollover and no daily cap, Teams at $30 a member starting
at 10M tokens each, and Enterprise by consumption, with "save up to 28%"
on the annual toggle. Hosting is separate and per account: Free gets 10 GB
of bandwidth and 333,333 requests a month, after which the site stops
displaying until the month resets; Pro gets 30 GB and 1 million requests
with pay-as-you-go above that. Bolt changes these; check the page.

The prompt in step 3 is one request, with perhaps two fix-ups; steps 6 and
8 are one each. The expensive thing on Bolt is not a feature, it is a loop.
A one-star Trustpilot review from 29 August 2026 put it as "half the time
you spend your tokens trying to resolve issues that their own AI has
created itself", and another, from 4 October, reported "approximately 212K
Tokens out of my 300K daily allowance" gone "in a very short period of
time". Naming the exact files, the exact variable names and the exact
guide is how you avoid the loop, and it is why this page is long. The
other half is step 5: do not spend tokens debugging sign-in until the
thirty-second check passes, because until it does, the problem is not in
the code Bolt wrote.

BuildBase's side: a Free plan at $0, then Launch at $19 a month, with a 7-day
trial and no card on the paid plans.

## What breaks, and how you can tell

**`/api/auth/session` returns HTML on the live site and JSON in the
preview.** Step 5. The live site has no server for the routes: on route A
the functions are not under your site's address, on route B the function
files are not in the host's folder. Route B, or the folder.

**"Sign-in failed" on a correct code.** The secret did not reach the
function. Check the host's variables, or Bolt's Secrets page on route A.

**Sign-in works in the preview and loops on the live site.** The live
address is not registered with `/sign-in` on the end, or the host built
with the preview's redirect value because `.env` was committed. Step 2 and
step 4.

**The secret is in the repository.** `.env` was not ignored before Bolt
connected GitHub. Regenerate the secret in the console (the old one stops
working immediately), add `.env` to `.gitignore`, and treat the old value
as public.

**The preview address changed and sign-in there stopped.** The project
restarted. Register the new address, or test sign-in on the live site
only.

**Rows vanish, or "permission denied", after switching sign-in.** Row rules
keyed to the old sign-in no longer match. Section 7: route the reads
through the server, or mint the token.

**The package install fails in the preview.** Bolt runs Node inside the
browser, which cannot load compiled native addons, and the SDK's
dependencies are plain JavaScript, so read the install error before
assuming the package; it is usually another dependency the agent added in
the same change.

## Install

In Bolt, the install is a sentence in the chat: "Use the @buildbase/sdk
npm package", and `npm install` runs in the preview's terminal. On a
checkout of the repository, it is the usual line:

```bash
npm i @buildbase/sdk
```
