KasyKasy

Notificações Push

FCM nos três backends. Setup automático, APNs no iOS, deep links e imagem na notificação.

Push usa Firebase Cloud Messaging (FCM) nos três backends. O FCM entrega no device; seu backend decide quando e pra quem enviar.

BackendComo dispara
FirebaseCloud Function ao inserir em users/{uid}/notifications/{id}
SupabaseEdge Function via webhook na tabela notifications
API RESTSeu servidor chama FCM via HTTP

Implementação

Push usa FCM nos três backends. No modo Rápido:

  • Firebase backend: push já vem no preset
  • Supabase / API: no Rápido a CLI pergunta se quer push. Se sim, cria/liga companion Firebase (FCM). Se não, fica sem companion; dá pra ligar depois com Advanced, --push no MCP, ou kasy add notifications

O kasy new interativo configura o que for possível na hora. Credenciais adiadas no Rápido: Android funciona sem passo extra no emulador. iOS precisa de uma APNs Key (todos os backends). Supabase + API REST precisam da service account do Firebase quando o módulo push estiver ligado.

Pelo MCP: depois do setup, peça "checa a configuração de push do meu projeto" (check_project) ou "checa e corrige o push" (check_project com fix). Veja MCP do Kasy.

iOS: APNs Key (todos os backends)

A APNs Key só existe no Apple Developer Portal e precisa de upload no Firebase Console. Uma chave serve para todos os apps do mesmo Team ID.

1. Criar a chave no Apple Developer Portal

  1. Acesse developer.apple.com → Keys → "+"
  2. Dê um nome (ex.: Firebase APNs Key)
  3. Ative Apple Push Notifications service (APNs)
  4. Clique em Continue → Register
  5. Baixe o .p8: só pode baixar uma vez; guarde em lugar seguro
  6. Anote o Key ID e o Team ID (canto superior direito do portal)

Dica: ative também Sign In with Apple na mesma chave. Assim você tem um único .p8 para push e login Apple.

2. Upload no Firebase Console

  1. Firebase Console → Cloud Messaging → seção Apps Apple
  2. Selecione o app iOS → clique em Fazer upload
  3. Selecione o .p8, preencha Key ID e Team ID
  4. Repita para Desenvolvimento e Produção (mesmo arquivo)
APNs Authentication Key configurada no Firebase Cloud Messaging
Firebase Console: Cloud Messaging → Apple app configuration com as chaves de Desenvolvimento e Produção

3. Verificar

Console Admin → Ferramentas → Enviar notificação de teste. No iOS, o app precisa estar com permissão de push concedida.

kasy check          # diagnóstico: secrets, edge functions, IAM
kasy check --fix    # corrige automaticamente
kasy deploy         # re-deploy das functions

Pelo MCP: "verifica o projeto" (check_project, com fix opcional), "faz o deploy do backend" (deploy_backend).

Supabase e API REST: chave do Firebase Service Account

No Firebase backend, push funciona "sem chave" porque o servidor usa as credenciais padrão do projeto Google Cloud (ADC). No Supabase e na API REST, o servidor é externo ao Firebase: você precisa gerar e cadastrar uma chave JSON.

1. Gerar a chave no Firebase Console

  1. Abra o Firebase Console → seu projeto
  2. Configurações do projeto → Service accounts
  3. Gerar nova chave privada → JSON → Criar
  4. Guarde o arquivo (é um JSON de ~1 KB com type, project_id, private_key etc.)
Diálogo de geração de nova chave privada no Firebase Admin SDK
Firebase Console: Project settings → Service accounts → Generate new private key

2. Cadastrar no backend

BackendComo cadastrar
SupabaseO kasy deploy cria a service account e grava FIREBASE_SERVICE_ACCOUNT_JSON e FIREBASE_PROJECT_ID. Manual depois: supabase secrets set FIREBASE_SERVICE_ACCOUNT_JSON='<conteúdo do JSON>' e supabase secrets set FIREBASE_PROJECT_ID=seu-id
API RESTVocê carrega o JSON no seu servidor e usa a SDK do Firebase Admin (Node, Python, Go etc.) para chamar firebase-admin.messaging().send()

Nunca coloque a chave JSON no app Flutter ou no .env do cliente. Ela vai SÓ no servidor.

Informações

Enviar notificações

Para um usuário: Firebase (Firestore)

// users/{userId}/notifications/{id}
{
  title: "Título",
  body: "Corpo da mensagem",
  type: "OTHER",
  notify_user: true,
}

Para um usuário: Supabase (SQL)

INSERT INTO public.notifications (user_id, title, body, type)
VALUES ('uuid-do-usuario', 'Título', 'Corpo', 'OTHER');

Para todos os usuários: Supabase

INSERT INTO public.notifications (user_id, title, body, type)
SELECT DISTINCT ON (d.user_id) d.user_id,
  'Título', 'Corpo', 'OTHER'
FROM public.devices d
ORDER BY d.user_id, d.creation_date DESC;

Pelo app (Console Admin)

Settings → Admin → Ferramentas → Enviar notificação. Permite enviar para e-mail específico ou para todos, com imagem e tela de destino.

O campo data controla para onde o app navega:

dataComportamento ao tocar
vazioAbre a lista de Notificações
{"route": "/premium"}Navega para a tela interna
{"url": "https://..."} + type: LINKAbre no browser externo

O campo route aceita qualquer caminho do GoRouter. Funciona em qualquer estado do app (foreground, background, fechado).

Exemplos:

-- Leva para a tela de assinatura
INSERT INTO public.notifications (user_id, title, body, type, data)
VALUES ('uuid', 'Oferta!', 'Toque para ver.', 'OTHER', '{"route": "/premium"}');

-- Abre link externo
INSERT INTO public.notifications (user_id, title, body, type, data)
VALUES ('uuid', 'Novidade', 'Veja no site.', 'LINK', '{"url": "https://seusite.com/novidade"}');

Deep link dinâmico (ex.: abrir um post específico)

Mesma ideia, mas com parâmetro na rota:

  1. Crie a rota em router.dart: /post/:id
  2. Envie {"route": "/post/123"} no campo data

Cada notificação aponta para um conteúdo diferente, igual ao comportamento de Twitter e Instagram. A engrenagem (navegação, back stack, todos os estados do app) já vem pronta.

Imagem na notificação

Inclua image_url com uma URL pública JPEG/PNG:

// Firebase
{
  title: "Oferta!",
  body: "Toque para ver.",
  image_url: "https://exemplo.com/imagem.jpg",
  type: "OTHER",
  notify_user: true,
}
-- Supabase
INSERT INTO public.notifications (user_id, title, body, type, image_url)
VALUES ('uuid', 'Oferta!', 'Toque para ver.', 'OTHER', 'https://exemplo.com/imagem.jpg');

Aparece como thumbnail no banner do sistema (iOS precisa de UNNotificationServiceExtension, que já vem no projeto em ios/NotificationService/).

Comportamento por estado do app

EstadoO que acontece
Foreground (app aberto)Banner local + notificação salva na lista in-app
Background (minimizado)Banner do sistema operacional
FechadoBanner do SO; ao tocar abre o app na tela certa

Por que o Kasy envia a notificação pronta (e não só dados)

O servidor manda a notificação já com título e texto (notification), e o sistema operacional a mostra, mesmo com o app fechado. É o que o mercado usa quando a prioridade é a notificação chegar.

Enviar só dados ("data-only") e deixar o app decidir parece mais flexível, mas no iOS esse tipo de mensagem é tratado como silenciosa: o sistema pode atrasar ou descartar, e não acorda um app fechado. Trocar a notificação pronta por data-only deixaria de entregar parte das notificações. Por isso o Kasy não faz isso por padrão.

O que o app não pode fazer sozinho (horário silencioso, tipos desligados pelo usuário) é filtrado no servidor, antes de enviar, e vale igual no iOS, no Android e na web. Isso está no roadmap do kit (preferências de notificação). Até lá, sua regra de "quem recebe o quê" fica no código que chama o envio.

Observações

  • Emulador Android precisa de conta Google configurada no emulador para gerar token FCM válido.
  • iOS com debugger conectado pode bloquear push em background. Pressione d no terminal para desconectar o debugger mantendo o app rodando.
  • A chave .p8 só pode ser baixada uma vez: guarde bem.

Atualizado em 03/11/2026