Skip to content

Configuring Your Clone

A finished clone is a working backend, not a finished product. Everything the source owner held as a secret, and everything tied to their identity or billing, stopped at the boundary. This page is the list of what you now have to supply.

SchemaTables, columns, types, indexes
SecurityRow-level security policies, access mode
FunctionsFunction code, deployed to your app
Durable ObjectsClass definitions, redeployed on your namespace
RepoThe source’s latest pushed snapshot
ConfigStorage settings, CORS allowed origins, OAuth provider list and redirect URLs, AI model defaults
App env varsApp-level environment variables, values included
Seed dataRows in tables the publisher marked _seed: true
FrontendThe source’s most recent published frontend, with the source app id rewritten to yours so it calls your backend
Why
End-user accounts and sessionsThey belong to the source app’s users
OAuth client secretsThe source owner’s credentials
Function environment variable valuesSecrets — you got the key names, not the values
Durable Object env valuesApp-scoped secrets; never copied
BYOK AI provider keysThe source owner’s billing
Custom domainsTied to DNS you don’t control
Stripe Connect / plans / productsThe source owner’s Stripe account
Invocation history, audit logsNot yours
manage_app action: "get_clone_job", job_id: "<job_id>"

Do this first. Warnings tell you what the pipeline couldn’t reproduce — most importantly a broken auth hook binding (left NULL) and any minted webhook secret, which is shown exactly once.

2. Fill in the remaining function env vars

Section titled “2. Fill in the remaining function env vars”

Preflight told you which keys were user_required. Anything you didn’t pass at clone time is still empty, and the function will fail at runtime rather than at deploy time.

manage_function action: "update_env"
app_id: "<your_new_app_id>"
function_name: "send-invite"
env: { "RESEND_API_KEY": "re_..." }

You can also set them in App → Functions → function → Environment in the dashboard.

Check what’s still missing with unfilled_env_vars on the clone job, or with manage_function action: "get" on each function.

DO environment values are never carried across a clone. Every non-convention key must be re-set:

manage_durable_objects action: "set_env"
app_id: "<your_new_app_id>"
name: "<do_class_name>"
key: "OPENAI_API_KEY"
value: "sk-..."

One key per call — repeat for each. action: "list_env" shows which keys exist.

The provider list and redirect URLs copied; the client id/secret pairs did not. For each provider the template used, register an app with that provider and configure it:

manage_oauth action: "configure"
app_id: "<your_new_app_id>"
provider: "google"
client_id: "..."
client_secret: "..."
redirect_uris: ["https://api.butterbase.ai/auth/<your_new_app_id>/oauth/google/callback"]

Update the redirect URLs to point at your domains — the copied ones point at the source app’s. See Authentication.

5. Rebind the auth hook if the warning said so

Section titled “5. Rebind the auth hook if the warning said so”

If a warning reported the auth hook couldn’t be bound, set it once the function exists:

manage_auth_config action: "configure_auth_hook", app_id: "<app_id>", post_auth_function: "<fn>"

The clone inherits the source’s model defaults but not their BYOK keys. Either let it run on your Butterbase AI credits, or add your own keys:

manage_ai action: "update_config", app_id: "<app_id>", config: { byokKey: "sk-ant-..." }

See AI Integration.

The copied allowed_origins list points at the source’s domains. Replace it:

manage_app action: "update_cors"
app_id: "<app_id>"
allowed_origins: ["https://myapp.com", "http://localhost:5173"]

Clones usually come up with a live frontend already serving. Step 7 of the clone pipeline republishes the source’s most recent frontend artifact and rewrites the source app id inside it to yours, so it talks to your backend rather than the template’s. Your app overview shows the URL.

Two cases need your attention:

  • No frontend deployed. The source never published one, or the replay failed — replay is best-effort and logs a warning rather than failing the clone. Build and deploy your own; see Frontend Deployment.
  • A warning says the artifact had no occurrences of the source app id. The rewrite couldn’t find anything to change, so the cloned frontend may still be pointed at the source app. Redeploy from your own build before putting any data in.

Frontend build env vars (VITE_* / NEXT_PUBLIC_*) are separate from function env vars and are not inherited — set them on your app and redeploy if the frontend needs them.

Optional, and only on Launch or above. See Custom Domains.

Stripe Connect does not transfer. If the template ships a paywall, plans, or products, you need your own Connect account and your own plan/product rows. See Charging Your Users.

11. Review the security posture before you go live

Section titled “11. Review the security posture before you go live”

Never assume an inherited configuration is safe for your use case.

  • Check the app’s access mode: manage_app action: "get_config".
  • Read every RLS policy that came across — Row-Level Security has a debugging guide.
  • Confirm no seed row contains data you don’t want to ship.
  • If the template was built for a demo, it may be deliberately permissive.

If you cloned from the dashboard or MCP and want the files locally:

Terminal window
butterbase repo init <your_new_app_id>
butterbase repo pull

The CLI’s butterbase clone already did this for you.

  1. manage_schema action: "get" — the expected tables exist.
  2. select_rows on a seeded table — seed data landed.
  3. invoke_function on each function — a 500 here is almost always a missing env var.
  4. Sign up a test end user through your auth config.
  5. Deploy the frontend and click through the primary flow.