# Secret (/academy/secret)



A public string says who something is. A **secret** proves you are allowed.

[API](/academy/api) keys. Session tokens. Private keys. Database passwords. Hold one and you can spend, delete, or impersonate. That is the whole difference. `NEXT_PUBLIC_SITE_URL` can be in the repo. `STRIPE_SECRET_KEY` cannot.

**Where it lives**

In an [env file](/academy/env) on your laptop. In the host's vault after [deploy](/academy/deploy). Never in the route. Never in a screenshot for Discord. Never in the chat log you paste into a [GitHub](/academy/github) issue. Bots scan public repos for exactly these strings. They are faster than you.

The [builder](/builder) will create `.env.example` with names. Fill the real file locally. Tell your [agent](/academy/agent) the name of the variable, not the value. If it echoes a key, rotate it. Treat the leak as done, not theoretical.

**If it got out**

Rotate. Cancel the old key. Issue a new one. Update `.env` and the host. Do not "watch for a bit." A leaked Stripe key at a hackathon is a real bill.

Give each key the least power it needs. A publishable key in the browser is not the secret key. Do not copy the wrong one into `NEXT_PUBLIC_` and ship it to every judge's tab.

[Encryption](/academy/encryption) hides a secret on the wire. It does not forgive a commit. The [CLI](/academy/cli) can scaffold the files. It cannot unsay a push.

**What this unlocks**

You can open-source the app and still own the account.

Show the public strings. Hide the keys. Rotate when you slip.
