> ## 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

# Recolher as chaves de provedor restantes

Percursos curtos para os serviços que faltam: provedores de IA, Trigger.dev, armazenamento S3, Sentry ou PostHog, Turnstile e o seu domínio.

## Como usar esta página

Cada secção abaixo é um percurso de configuração completo: criar a conta, encontrar a chave, definir os nomes env, verificar. Use apenas as secções dos serviços que o seu produto lança — um site sem funções de IA nunca precisa da primeira, e o kit continua a correr mesmo com todas as secções aqui saltadas.

As mesmas regras de segredos de sempre: chaves de API e segredos de webhook ficam apenas no servidor, só os valores com prefixo `NEXT_PUBLIC_`/`EXPO_PUBLIC_` podem chegar ao cliente, os segredos de produção vivem no secret store do hosting, e o servidor de desenvolvimento só relê o env ao reiniciar.

[Voltar à lista de contas](https://supastack.dev/pt/docs/web/external-accounts.md)


## Chaves de provedores de IA

O `AI_PROVIDER` do kit aceita `openai`, `anthropic`, `openai-compatible` e `openrouter` — mais `fake`, o substituto local predefinido. Escolha um; a chave do provedor é a única conta necessária, porque os ids de modelo e os preços vêm do catálogo na base de dados do kit, não de variáveis env.

OpenAI: [platform.openai.com](https://platform.openai.com) → API keys → Create new secret key → copie `sk-…` → `OPENAI_API_KEY`. Anthropic: [console.anthropic.com](https://console.anthropic.com) → API Keys → Create Key → `sk-ant-…` → `ANTHROPIC_API_KEY`. Ambos faturam por token — uns poucos dólares de crédito cobrem o desenvolvimento.

O OpenRouter encaminha cada modelo do catálogo através de uma única chave: [openrouter.ai](https://openrouter.ai) → Keys → Create Key → `sk-or-…` → `AI_PROVIDER=openrouter` mais `OPENROUTER_API_KEY`; os opcionais `OPENROUTER_APP_NAME`/`OPENROUTER_SITE_URL` enviam cabeçalhos de atribuição. `openai-compatible` cobre qualquer endpoint com formato OpenAI: `OPENAI_COMPATIBLE_API_KEY` mais `OPENAI_COMPATIBLE_BASE_URL`.

Verifique: reinicie, execute uma tarefa de IA e espere uma resposta de modelo real em vez do fake determinístico. Um erro de arranque que nomeia a chave significa que o flag do provedor está ligado sem a sua chave. Uma resposta real também precisa de `JOB_PROVIDER=trigger` da secção Trigger.dev abaixo mais um modelo ativado no catálogo do kit — [Configurar IA](https://supastack.dev/pt/docs/web/setup-ai.md) cobre essa montagem.

```
# apps/web/.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

Salte a menos que o produto precise de execuções reais de jobs em segundo plano — `JOB_PROVIDER=local` enfileira jobs em memória sem os executar, o que é o certo para desenvolvimento.

1. Abra [app.trigger.dev](https://app.trigger.dev) → Sign up → crie um projeto.

2. Copie dois valores: o project ref `proj_…` das definições do projeto ou do URL do painel → `TRIGGER_PROJECT_REF`, e a secret key da página de API keys do projeto (`tr_dev_…` para o ambiente dev, `tr_prod_…` para produção) → `TRIGGER_SECRET_KEY`. Ambos ficam apenas no servidor.

3. As tarefas do kit já vivem em `apps/web/trigger` e `apps/web/trigger.config.ts` lê `TRIGGER_PROJECT_REF`. A partir de `apps/web` corra `npx trigger.dev@latest dev` — regista as tarefas no seu projeto e executa-as localmente contra a chave dev.

Verifique: o comando dev regista as tarefas; enfileire uma na app e veja-a executar na lista Runs do painel. Os ambientes implementados correm `corepack pnpm --filter @supastack/web trigger:deploy` para publicar o conjunto de tarefas.

```
# apps/web/.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:
cd apps/web
npx trigger.dev@latest dev
```


## Armazenamento compatível com S3 (Cloudflare R2)

Salte a menos que o produto armazene ficheiros — `STORAGE_PROVIDER=memory` mantém os uploads dentro do processo para desenvolvimento.

Qualquer bucket compatível com S3 serve; o Cloudflare R2 é a escolha amiga do nível gratuito. 1. Abra [dash.cloudflare.com](https://dash.cloudflare.com) → R2 Object Storage → Create bucket, dê-lhe um nome e mantenha a indicação de localização predefinida.

2. De volta na vista geral do R2 abra Manage R2 API Tokens → Create API token → permissão Object Read & Write, limitada a esse bucket → Create. Copie o Access Key ID, a Secret Access Key e o endpoint S3 mostrado — `https://<account-id>.r2.cloudflarestorage.com`.

3. Defina os nomes env abaixo. `STORAGE_REGION=auto` é a convenção do R2 — o kit usa `us-east-1` por predefinição, que o R2 também aceita. `STORAGE_FORCE_PATH_STYLE` já vem ligado por predefinição para endpoints personalizados, que é o que o R2 quer. Servir ficheiros públicos precisa ainda de `STORAGE_PUBLIC_BASE_URL` ou de ligação a CDN; os ficheiros privados não precisam de mais nada.

Verifique: reinicie e carregue através da app — o objeto aparece no navegador do bucket R2. Um erro de assinatura ou 403 significa que ao token falta leitura/escrita de objetos nesse bucket; crie um token novo com o âmbito correto.

```
# apps/web/.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 ou PostHog (opcional)

Totalmente opcional: cada valor de observabilidade vem vazio por predefinição e o kit corre bem sem nenhum — adicione isto quando quiser relatórios de erros e analítica em produção.

Sentry para erros: [sentry.io](https://sentry.io) → crie um projeto → escolha a plataforma Next.js → o ecrã de configuração mostra o DSN `https://…@….ingest.sentry.io/…` → `SENTRY_DSN`. As exceções chegam depois ao Sentry marcadas com ids de correlação; o nível gratuito chega para começar.

PostHog para analítica de produto em alternativa: [posthog.com](https://posthog.com) → crie um projeto → copie a chave de API do projeto `phc_…` → `NEXT_PUBLIC_POSTHOG_KEY` mais `NEXT_PUBLIC_POSTHOG_HOST` (`https://us.i.posthog.com`, ou o seu anfitrião da UE). Esses dois são valores públicos de browser por desenho; `SENTRY_DSN` fica no servidor. `ALERT_WEBHOOK_URL` publica opcionalmente alertas de falhas para um endpoint compatível com Slack.

Verifique: reinicie, lance uma exceção de teste (ou repita o evento de exemplo do Sentry) e confirme que aterra na lista Issues do projeto.

```
# apps/web/.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

Proteção anti-bot para os formulários públicos e os endpoints de credenciais — `CAPTCHA_PROVIDER=off` por predefinição, por isso adicione-o antes de abrir o registo a desconhecidos. Gratuito.

1. Abra [dash.cloudflare.com](https://dash.cloudflare.com) → Turnstile → Add widget → dê-lhe um nome e liste os hostnames: `localhost` para desenvolvimento mais o seu domínio real → Create.

2. Copie os dois valores: a Site Key — pública por desenho, é renderizada dentro do widget → `NEXT_PUBLIC_TURNSTILE_SITE_KEY` — e a Secret Key, que o servidor usa para verificar → `TURNSTILE_SECRET_KEY`.

3. `CAPTCHA_PROVIDER=turnstile` liga-o; o arranque falha nomeando a chave em falta. O guia captcha lista exatamente que superfícies o widget protege.

Verifique: abra `/auth` ou o formulário de contacto — o widget é renderizado; envios sem um desafio resolvido são rejeitados. Se o widget nunca carrega, o hostname que está a visitar não está na lista do widget.

[Veja que formulários o Turnstile protege](https://supastack.dev/pt/docs/web/captcha.md)

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


## Um domínio só seu

Uma compra em qualquer registrador — Cloudflare Registrar, Porkbun, Namecheap, todos servem. Nada daqui se copia para o env; o domínio aparece na Services ID, no DNS da Resend, nos hostnames do Turnstile e nas return URL de OAuth que configurou pelo caminho.

Duas formas de o apontar para a app: para o Cloud Run use o mapeamento de domínio do guia de implementação — uns cliques de consola mais os registos DNS que a Google lista. Ou mova o DNS para os nameservers da Cloudflare (o registrador troca dois registos) — opcional, mas é também a forma arrumada de gerir buckets públicos R2 e hostnames do Turnstile num só sítio.

[Mapear o domínio no Cloud Run](https://supastack.dev/pt/docs/web/deploy-google-cloud.md)

[Configurar a seguir a base de dados](https://supastack.dev/pt/docs/web/setup-database.md)


Para continuar a configuração, leia [Configurar a base de dados](https://supastack.dev/pt/docs/web/setup-database.md).


## Seguinte

[Configurar a base de dados](https://supastack.dev/pt/docs/web/setup-database.md)
