# Deploy on Vercel

> Clone deploy button env wiring, Blob store creation, required server env vars, and post-deploy dashboard steps from README.

- Repository: MaxLeiter/vcup
- GitHub: https://github.com/MaxLeiter/vcup
- Human docs: https://grok-wiki.com/public/docs/maxleiter-vcup-05c16ae77ebb
- Complete Markdown: https://grok-wiki.com/public/docs/maxleiter-vcup-05c16ae77ebb/llms-full.txt

## Source Files

- `README.md`
- `.env.example`
- `vercel.json`
- `package.json`
- `api/upload.ts`
- `api/f.ts`

---

---
title: "Deploy on Vercel"
description: "Clone deploy button env wiring, Blob store creation, required server env vars, and post-deploy dashboard steps from README."
---

vcup runs as a Vercel project with three serverless handlers under `api/` (`upload`, `delete`, `f`), a `vercel.json` rewrite that maps `/f/:slug*` to `api/f`, and Vercel Blob as the object store. The README **Deploy with Vercel** button clones the repo, provisions a Blob store, and prompts for the server environment variables the handlers and `@vercel/blob` expect.

## Runtime layout on Vercel

```mermaid
flowchart TB
  subgraph client["CLI (cli.ts)"]
    CLI["vcup / vcup rm"]
  end

  subgraph vercel["Vercel deployment"]
    RW["vercel.json rewrite /f/:slug* → /api/f"]
    UP["api/upload.ts POST"]
    DEL["api/delete.ts DELETE"]
    PROXY["api/f.ts GET"]
  end

  subgraph storage["Vercel Blob"]
    BLOB["public blobs + random suffix"]
  end

  CLI -->|"POST /api/upload Bearer + X-Filename"| UP
  CLI -->|"DELETE /api/delete Bearer + X-Blob-Url"| DEL
  CLI -->|"opens proxy URL"| RW
  RW --> PROXY
  UP -->|"put()"| BLOB
  DEL -->|"del()"| BLOB
  PROXY -->|"fetch BLOB_STORE_URL + slug"| BLOB
```

| Surface | Path / handler | Auth | Blob dependency |
| --- | --- | --- | --- |
| Upload | `POST /api/upload` → `api/upload.ts` | `VCUP_TOKEN` Bearer | `put()` via `@vercel/blob` |
| Delete | `DELETE /api/delete` → `api/delete.ts` | `VCUP_TOKEN` Bearer | `del()` via `@vercel/blob` |
| Inline proxy | `GET /f/:slug` → rewrite → `api/f.ts` | None (public) | `BLOB_STORE_URL` + slug fetch |

The dev entrypoint is `npm run dev` / `bun run dev`, which runs `vercel dev` from `package.json`.

## Deploy with Vercel button

The README ships a one-click deploy link. Decoded query parameters:

| Parameter | Value | Effect |
| --- | --- | --- |
| `repository-url` | `https://github.com/maxleiter/vcup` | Clones the vcup repo |
| `env` | `BLOB_READ_WRITE_TOKEN,BLOB_STORE_URL,VCUP_TOKEN` | Prompts for these three vars during setup |
| `envDescription` | `See .env.example for details` | Points operators at `.env.example` |
| `stores` | `[{"type":"blob"}]` | Provisions a Vercel Blob store on the new project |

Use the button from the README or open:

```
https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fmaxleiter%2Fvcup&env=BLOB_READ_WRITE_TOKEN,BLOB_STORE_URL,VCUP_TOKEN&envDescription=See%20.env.example%20for%20details&stores=%5B%7B%22type%22%3A%22blob%22%7D%5D
```

<Note>
The button pre-registers all three server variables. Values still need to be filled or corrected after the Blob store exists—especially `BLOB_STORE_URL` and a chosen `VCUP_TOKEN`.
</Note>

## Required server environment variables

`.env.example` documents the same three variables the deploy button requests:

```env
BLOB_READ_WRITE_TOKEN=
BLOB_STORE_URL=
VCUP_TOKEN=
```

| Variable | Required on server | Role in this repo |
| --- | --- | --- |
| `BLOB_READ_WRITE_TOKEN` | Yes | Used by `@vercel/blob` `put()` / `del()` on Vercel when the project is linked to Blob storage (not read directly in handler source) |
| `BLOB_STORE_URL` | Yes | Public store origin for `api/f.ts` proxy fetches (`${storeUrl}/${slug}`); returns **500** `BLOB_STORE_URL not configured` when missing |
| `VCUP_TOKEN` | Yes | Shared secret; upload and delete return **401** when unset or Bearer mismatch |
| `VCUP_BASE_URL` | No | Overrides the host used in upload JSON `url` (proxy link); defaults to `x-forwarded-proto` + `host` |

Example store URL shape from the README: `https://abc123.public.blob.vercel-storage.com`.

## Post-deploy dashboard steps

<Steps>
<Step title="Open Storage and copy Blob credentials">

In the Vercel project **Storage** tab, note `BLOB_READ_WRITE_TOKEN` and the store’s public URL after the Blob store is created (the deploy flow’s `stores` parameter provisions one).

</Step>
<Step title="Set VCUP_TOKEN">

In **Settings → Environment Variables**, set `VCUP_TOKEN` to any random secret string. The same value must be configured on every CLI that uploads or deletes.

</Step>
<Step title="Set BLOB_STORE_URL">

Set `BLOB_STORE_URL` to the store’s public URL (for example `https://abc123.public.blob.vercel-storage.com`). Without it, `GET /f/...` proxy requests fail with **500**, and the CLI cannot resolve proxy URLs for `vcup rm` unless you pass the raw blob URL.

</Step>
<Step title="Confirm BLOB_READ_WRITE_TOKEN">

Ensure `BLOB_READ_WRITE_TOKEN` is present for the linked Blob store (typically auto-populated when Storage is connected). Uploads and deletes depend on `@vercel/blob` with this token on the deployment.

</Step>
<Step title="Redeploy if needed">

After changing environment variables, trigger a redeploy so serverless functions pick up the new values.

</Step>
</Steps>

## Proxy rewrite

`vercel.json` defines a single rewrite:

```json
{
  "rewrites": [
    { "source": "/f/:slug*", "destination": "/api/f" }
  ]
}
```

Upload responses return a proxy URL shaped as `{baseUrl}/f/{slug}`, where `slug` is the pathname segment from the blob URL after `put(..., { addRandomSuffix: true })`. The proxy handler streams bytes from `BLOB_STORE_URL` with inline `Content-Disposition`.

## Point the CLI at the deployment

After the deployment URL is live (default `*.vercel.app` or a custom domain), configure clients to call that origin—not the Blob store URL.

<Tabs>
<Tab title="~/.vcuprc">

```json
{
  "url": "https://your-vcup-deployment.vercel.app",
  "token": "your-vcup-token"
}
```

`token` must match server `VCUP_TOKEN`. `url` is the deployment base used for `/api/upload` and `/api/delete`.

</Tab>
<Tab title="Environment variables">

```bash
export VCUP_API_URL="https://your-vcup-deployment.vercel.app"
export VCUP_TOKEN="your-vcup-token"
```

`VCUP_API_URL` and `VCUP_TOKEN` take precedence over `~/.vcuprc` when both are set.

</Tab>
</Tabs>

<Warning>
Client `VCUP_TOKEN` is the same secret as server `VCUP_TOKEN`. Client `VCUP_API_URL` is the deployment origin; do not point it at `BLOB_STORE_URL`.
</Warning>

## Optional: custom domain and VCUP_BASE_URL

For a custom host (README: `vercel domains add`, CNAME to `cname.vercel-dns.com`), set `~/.vcuprc` `url` (or `VCUP_API_URL`) to that host. If upload responses should emit proxy links on the custom host while requests still hit Vercel, set server `VCUP_BASE_URL` to that public origin; otherwise upload uses the incoming request host headers.

## Verify the deployment

<Steps>
<Step title="Upload a test file">

```bash
vcup /path/to/small-file.txt
```

Expect a printed URL like `https://<deployment>/f/<slug>`.

</Step>
<Step title="Open the proxy URL">

Open the printed URL in a browser. A working proxy returns **200** with inline content; missing `BLOB_STORE_URL` yields **500** `BLOB_STORE_URL not configured`.

</Step>
<Step title="Check auth">

Wrong or missing Bearer on upload returns **401** `Unauthorized` from `api/upload.ts`.

</Step>
</Steps>

## Failure modes tied to deploy config

| Symptom | Likely cause |
| --- | --- |
| Upload **401** | `VCUP_TOKEN` mismatch or unset on server vs CLI |
| Proxy **500** `BLOB_STORE_URL not configured` | `BLOB_STORE_URL` not set on the deployment |
| Proxy **502** `Failed to fetch file` | Wrong store URL or slug; upstream fetch error |
| `vcup rm` on proxy URL fails locally | CLI needs client `BLOB_STORE_URL` to resolve `/f/` slugs, or pass the raw blob URL |
| Proxy links use wrong host | Set `VCUP_BASE_URL` to the public deployment or custom domain |

## Related pages

<CardGroup>
<Card title="Environment variables" href="/environment-variables">
Server and client variable reference for Blob, auth, and API URL.
</Card>
<Card title="Configure the CLI" href="/configure-cli">
`~/.vcuprc` schema and env precedence after deploy.
</Card>
<Card title="Custom domain" href="/custom-domain">
Domain DNS, `VCUP_BASE_URL`, and client `url` alignment.
</Card>
<Card title="Local development" href="/local-development">
`vercel dev` and `.env` from `.env.example` before production deploy.
</Card>
<Card title="Quickstart" href="/quickstart">
First upload and proxy URL check against a live deployment.
</Card>
</CardGroup>
