# vercel env push

```sh
scribase vercel env push <org> <project> <env> [--dir <path>] [--dry-run] [--json]
scribase vercel status [--dir <path>]
```

Writes the environment's project URL and keys into the Vercel project this
folder deploys to, for **development, preview and production**, in one
request. The next deploy uses them. Run it again after a key rotation: it
updates the values in place.

```sh
vercel link                                   # once, if the folder is not linked yet
scribase vercel env push acme shop production
# Vercel: 9 environment variables set on prj_… for development, preview and production (via VERCEL_TOKEN); the next deploy uses them
```

## Automatic in `npx scribase init`

You usually do not need this command. `npx scribase init` pushes the same
variables right after it provisions the backend and writes your `.env` file,
whenever the folder is linked to Vercel. It prints one line:

| Line | Meaning |
|---|---|
| `Vercel env updated for development, preview, production` | Done; redeploy to pick them up |
| `Not linked to Vercel — skipped` | No `.vercel/project.json` and no `VERCEL_PROJECT_ID` |
| `No Vercel credentials — skipped` | Linked, but no `VERCEL_TOKEN` and no signed-in `vercel` CLI |
| `Vercel env not updated: …` | Vercel refused; the reason follows. Retry with `scribase vercel env push` |

With `--json`, the result includes the outcome:

```json
{ "ok": true, "...": "...", "vercel": { "status": "updated", "targets": ["development", "preview", "production"], "project_id": "prj_…" } }
```

`status` is `updated`, `not_linked`, `no_credentials`, `failed` (with an
`error` string) or `disabled` (`--no-vercel`). Vercel never fails `init`: the
backend and your `.env` are ready either way.

Pass `--no-vercel` to leave the Vercel project alone.

## How the project is found

In order:

1. `VERCEL_PROJECT_ID` (and `VERCEL_ORG_ID`), the variables Vercel's own CLI
   reads in CI.
2. `.vercel/project.json` in the folder (`--dir`, default the current one),
   written by `vercel link` or `vercel deploy`.

No link means nothing to do. `scribase vercel status` shows what was found and
which credentials would be used.

## How it authenticates

- **`VERCEL_TOKEN`** set: Scribase calls the Vercel REST API directly. The
  token is only sent in the `Authorization` header (the Rust CLI streams it to
  curl on stdin); it is never put on a command line or printed.
- **Otherwise, a signed-in `vercel` CLI** (`npx vercel login` once): Scribase
  runs `vercel api` without a shell and passes the request body on stdin, so
  the CLI's own session is used and Scribase never reads a Vercel token.

Neither available: nothing is pushed, and the message says how to fix it.

## What gets set

The same names as the console's Vercel integration, so either path gives the
same result:

| Variable | Type | Targets |
|---|---|---|
| `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SCRIBASE_URL` | plain | development, preview, production |
| `NEXT_PUBLIC_SUPABASE_ANON_KEY`, `NEXT_PUBLIC_SCRIBASE_ANON_KEY` | plain | development, preview, production |
| `SCRIBASE_ORG`, `SCRIBASE_PROJECT`, `SCRIBASE_ENV` | plain | development, preview, production |
| `SUPABASE_SERVICE_ROLE_KEY`, `SCRIBASE_SERVICE_ROLE_KEY` | sensitive | preview, production |

The anon key is public by design (row level security applies). The
service-role key bypasses row level security, so it is **server-only**: it never
gets a `NEXT_PUBLIC_` prefix, and it is stored as a sensitive variable that
cannot be read back from the Vercel dashboard. Vercel does not allow sensitive
variables on the development target; for local development it lives in your
`.env` file, which `init` writes.

The request is `POST /v10/projects/{id}/env?upsert=true` (plus `teamId` for a
team project) with every variable in one JSON array.

## Flags

| Flag | Meaning |
|---|---|
| `--dir <path>` | Folder to read `.vercel/project.json` from (default: current) |
| `--dry-run` | Print the variable names, types and targets that would be set; send nothing |
| `--json` | Print the outcome as JSON: `{"vercel":"pushed", "project_id", "count", "via", "keys"}`, or `not_linked`, `no_credentials`, `failed` |

`vercel env push` exits non-zero when nothing was pushed (unlike `init`,
where it is only a report).

## Environment

| Variable | Meaning |
|---|---|
| `VERCEL_TOKEN` | Vercel access token; optional when the `vercel` CLI is signed in |
| `VERCEL_PROJECT_ID`, `VERCEL_ORG_ID` | Use this project instead of `.vercel/project.json` |
| `SCRIBASE_VERCEL_BINARY` | Path to the `vercel` CLI (default: `vercel` on `PATH`) |
| `SCRIBASE_VERCEL_API_URL` | Vercel API origin (default: `https://api.vercel.com`) |
