> ## Documentation Index
> Fetch the complete documentation index at: https://supastack.dev/llms.txt
> Use this file to discover all available pages before exploring further.
> For the full documentation corpus in one file, fetch: https://supastack.dev/llms-full.txt

# Collect the remaining provider keys

Short walkthroughs for the services left: AI providers, Trigger.dev, S3 storage, Sentry or PostHog, Turnstile, and your domain.

## How to use this page

Each section below is one complete setup walkthrough: make the account, find the key, set the env names, verify. Take only the sections for services your product ships — a site with no AI features never needs the first one, and the kit keeps running with every section here skipped.

Same secret rules as everywhere: API keys and webhook secrets stay server-only, only values prefixed `NEXT_PUBLIC_`/`EXPO_PUBLIC_` may reach the client, production secrets live in the host's secret store, and the dev server rereads env only at restart.

[Back to the accounts checklist](https://supastack.dev/docs/tanstack/external-accounts.md)


## AI provider keys

The kit's `AI_PROVIDER` accepts `openai`, `anthropic`, `openai-compatible`, and `openrouter` — plus `fake`, the default local stand-in. Pick one; the provider key is the only account needed, because model ids and prices come from the kit's database catalog, not env vars.

OpenAI: [platform.openai.com](https://platform.openai.com) → API keys → Create new secret key → copy `sk-…` → `OPENAI_API_KEY`. Anthropic: [console.anthropic.com](https://console.anthropic.com) → API Keys → Create Key → `sk-ant-…` → `ANTHROPIC_API_KEY`. Both bill per token — a few dollars of credit covers development.

OpenRouter routes every catalog model through one key: [openrouter.ai](https://openrouter.ai) → Keys → Create Key → `sk-or-…` → `AI_PROVIDER=openrouter` plus `OPENROUTER_API_KEY`; optional `OPENROUTER_APP_NAME`/`OPENROUTER_SITE_URL` send attribution headers. `openai-compatible` covers any OpenAI-shaped endpoint: `OPENAI_COMPATIBLE_API_KEY` plus `OPENAI_COMPATIBLE_BASE_URL`.

Verify: restart, run one AI task, and expect a real model answer instead of the deterministic fake. A startup error naming the key means the provider flag is on without its key. A real reply also needs `JOB_PROVIDER=trigger` from the Trigger.dev section below plus one enabled model in the kit's catalog — [Set up AI](https://supastack.dev/docs/tanstack/setup-ai.md) covers that setup.

```
# apps/web-tanstack/.env.local — pick ONE provider
AI_PROVIDER=openai
OPENAI_API_KEY=sk-…

# or AI_PROVIDER=anthropic
# ANTHROPIC_API_KEY=sk-ant-…

# or AI_PROVIDER=openrouter
# OPENROUTER_API_KEY=sk-or-…

# or AI_PROVIDER=openai-compatible
# OPENAI_COMPATIBLE_API_KEY=…
# OPENAI_COMPATIBLE_BASE_URL=https://your-endpoint/v1
```


## Trigger.dev

Skip unless the product needs real background-job runs — `JOB_PROVIDER=local` queues jobs in memory without executing them, which is right for development.

1. Open [app.trigger.dev](https://app.trigger.dev) → sign up → create a project.

2. Copy two values: the project ref `proj_…` from the project's settings or dashboard URL → `TRIGGER_PROJECT_REF`, and the secret key from the project's API keys page (`tr_dev_…` for the dev environment, `tr_prod_…` for production) → `TRIGGER_SECRET_KEY`. Both stay server-only.

3. The kit's tasks already live in `apps/web-tanstack/trigger` and `apps/web-tanstack/trigger.config.ts` reads `TRIGGER_PROJECT_REF`. From `apps/web-tanstack` run `corepack pnpm exec trigger.dev dev` — it registers the tasks with your project and runs them locally against the dev key.

Verify: the dev command logs the registered tasks; queue one in the app and watch it execute in the dashboard's Runs list. Deployed environments run `corepack pnpm --filter @supastack/web-tanstack trigger:deploy` to publish the task set.

```
# apps/web-tanstack/.env.local
JOB_PROVIDER=trigger
TRIGGER_PROJECT_REF=proj_…
TRIGGER_SECRET_KEY=tr_dev_…   # tr_prod_… in production

# run the worker alongside the app, from apps/web-tanstack:
cd apps/web-tanstack
corepack pnpm exec trigger.dev dev
```


## S3-compatible storage (Cloudflare R2)

Skip unless the product stores files — `STORAGE_PROVIDER=memory` keeps uploads in-process for development.

Any S3-compatible bucket works; Cloudflare R2 is the free-tier-friendly pick. 1. Open [dash.cloudflare.com](https://dash.cloudflare.com) → R2 Object Storage → Create bucket, name it, and keep the default location hint.

2. Back on the R2 overview open Manage R2 API Tokens → Create API token → permission Object Read & Write, scoped to that bucket → Create. Copy the Access Key ID, the Secret Access Key, and the S3 endpoint shown — `https://<account-id>.r2.cloudflarestorage.com`.

3. Set the env names below. `STORAGE_REGION=auto` is the R2 convention — the kit defaults `us-east-1`, which R2 also accepts. `STORAGE_FORCE_PATH_STYLE` already defaults on for custom endpoints, which R2 wants. Serving public files additionally needs `STORAGE_PUBLIC_BASE_URL` or CDN wiring; private files need nothing more.

Verify: restart and upload through the app — the object appears in the R2 bucket browser. A signature or 403 error means the token lacks object read/write on that bucket; create a fresh token scoped correctly.

```
# apps/web-tanstack/.env.local
STORAGE_PROVIDER=s3
STORAGE_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
STORAGE_REGION=auto
STORAGE_BUCKET=your-bucket
STORAGE_ACCESS_KEY_ID=…          # server-only
STORAGE_SECRET_ACCESS_KEY=…      # server-only
# STORAGE_PUBLIC_BASE_URL=       # optional public-URL base
```


## Sentry or PostHog (optional)

Entirely optional: every observability value is unset by default and the kit runs fine with none — add this when you want error reports and analytics in production.

Sentry for errors: [sentry.io](https://sentry.io) → create a project → pick the TanStack Start platform → the setup screen shows the DSN `https://…@….ingest.sentry.io/…` → `SENTRY_DSN`. Exceptions then reach Sentry tagged with correlation ids; the free tier is enough to start.

PostHog for product analytics instead: [posthog.com](https://posthog.com) → create a project → copy the project API key `phc_…` → `NEXT_PUBLIC_POSTHOG_KEY` plus `NEXT_PUBLIC_POSTHOG_HOST` (`https://us.i.posthog.com`, or your EU host). Those two are public browser values by design; `SENTRY_DSN` stays server-side. `ALERT_WEBHOOK_URL` optionally posts failure alerts to a Slack-compatible endpoint.

Verify: restart, raise a test exception (or replay Sentry's sample event), and confirm it lands in the project's Issues list.

```
# apps/web-tanstack/.env.local — all optional
SENTRY_DSN=https://…@….ingest.sentry.io/…

NEXT_PUBLIC_POSTHOG_KEY=phc_…
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com

# ALERT_WEBHOOK_URL=https://hooks.slack.com/services/…
```


## Cloudflare Turnstile

Bot protection for the public forms and credential endpoints — `CAPTCHA_PROVIDER=off` by default, so add it before opening sign-up to strangers. Free.

1. Open [dash.cloudflare.com](https://dash.cloudflare.com) → Turnstile → Add widget → name it and list the hostnames: `localhost` for development plus your real domain → Create.

2. Copy both values: the Site Key — public by design, it renders inside the widget → `NEXT_PUBLIC_TURNSTILE_SITE_KEY` — and the Secret Key, which the server uses to verify → `TURNSTILE_SECRET_KEY`.

3. `CAPTCHA_PROVIDER=turnstile` switches it on; startup fails naming whichever key is missing. The captcha guide lists exactly which surfaces the widget protects.

Verify: open `/auth` or the contact form — the widget renders; submissions without a solved challenge are rejected. If the widget never loads, the hostname you are browsing is not on the widget's list.

[See which forms Turnstile protects](https://supastack.dev/docs/tanstack/captcha.md)

```
# apps/web-tanstack/.env.local
CAPTCHA_PROVIDER=turnstile
NEXT_PUBLIC_TURNSTILE_SITE_KEY=0x…   # public by design
TURNSTILE_SECRET_KEY=0x…             # server-only
```


## A domain of your own

One purchase at any registrar — Cloudflare Registrar, Porkbun, Namecheap all work. Nothing here copies into env; the domain shows up in the Services ID, Resend DNS, Turnstile hostnames, and OAuth return URLs you configured along the way.

Two ways to point it at the app: for Cloud Run use the domain mapping in the deploy guide — a few console clicks plus the DNS records Google lists. Or move DNS to Cloudflare nameservers (the registrar swaps two records) — optional, but it is also the tidy way to manage R2 public buckets and Turnstile hostnames in one place.

[Map the domain on Cloud Run](https://supastack.dev/docs/tanstack/deploy-google-cloud.md)

[Set up the database next](https://supastack.dev/docs/tanstack/setup-database.md)


If you want to continue setup, read [Set up database](https://supastack.dev/docs/tanstack/setup-database.md).


## Next

[Set up database](https://supastack.dev/docs/tanstack/setup-database.md)
