Neon Object Storage
O caminho da demo pro armazenamento de anexos — sem cartão, e sem nenhuma conta que você já não tenha.
O storage compatível com S3 do Neon. Escolha este pra uma demo: ele não pede cartão, e se você já usa Neon pro Banco de dados ele não acrescenta conta nenhuma.
Não serve pra comunidade de verdade
O egress conta na cota de 5 GB/mês de rede do projeto, compartilhada com o banco. Quando ela acaba, o Neon suspende o compute até o próximo ciclo — levando seu app junto. Pra produção use o Cloudflare R2.
Instale a CLI do Neon:
npm install -g neonctlAutentique com a mesma API key do Banco de dados. Se você não tem uma, gere no Console do Neon em Account settings → API keys.
export NEON_API_KEY="COLE_SUA_CHAVE_AQUI"Crie o bucket com leitura pública habilitada:
neonctl buckets create opencall-uploads --access-level public_readO nome vira o R2_BUCKET. O public_read é obrigatório: o app monta a URL da
imagem direto, sem assinatura, então a leitura anônima precisa funcionar.
No Console do Neon, abra sua branch → Credentials → Create credential,
com os escopos storage:read e storage:write.
Os dois valores aparecem uma única vez:
token_id→R2_ACCESS_KEY_IDs3_secret_access_key→R2_SECRET_ACCESS_KEY
Pegue o endpoint de storage da branch, no formato
https://br-<branch-id>.storage.c-1.<regiao>.aws.neon.tech → R2_ENDPOINT.
Defina R2_REGION como a região do projeto — us-east-2 ou eu-central-1.
A URL pública é o endpoint mais o nome do bucket:
https://br-<branch-id>.storage.c-1.<regiao>.aws.neon.tech/opencall-uploadsEla, sem barra no fim, vira o NEXT_PUBLIC_R2_PUBLIC_BASE_URL.
O bucket vive na branch
O storage do Neon acompanha as branches do projeto: apagar ou resetar a branch leva as imagens junto. Aponte as variáveis pra branch que realmente serve o app.
Variáveis desta etapa
| Variável | Valor |
|---|---|
R2_BUCKET | Nome do bucket (opencall-uploads) |
R2_ACCESS_KEY_ID | token_id da credential |
R2_SECRET_ACCESS_KEY | s3_secret_access_key |
R2_ENDPOINT | Endpoint de storage da branch |
R2_REGION | us-east-2 ou eu-central-1 |
NEXT_PUBLIC_R2_PUBLIC_BASE_URL | <endpoint>/opencall-uploads |
O R2_ACCOUNT_ID fica vazio neste caminho — ele só vale pra Cloudflare.
Como funciona o armazenamento
Opcional — um bucket compatível com S3 pra que as pessoas possam anexar imagens no chat. Sem ele, todo o resto continua funcionando.
Cloudflare R2
O caminho de produção pro armazenamento de anexos — egress livre, que é do que servir imagem de chat pra uma comunidade de verdade precisa.