Blog
Feature
15 de novembro de 20258 min

Lembretes recorrentes: como gerir a complexidade oculta

"Adicione um lembrete toda terça-feira." Seis palavras. Fácil de dizer. Mas por trás dessa frase, esconde-se um dos problemas mais subestimados no desenvolvimento de aplicativos: as regras de recorrência. Passei dias inteiros gerenciando casos extremos que ninguém antecipa antes de encontrá-los.

Pontos-chave a reter:
- Lembretes recorrentes parecem simples, mas escondem uma complexidade enorme (gerenciamento de meses irregulares, fusos horários, exceções).
- O armazenamento híbrido (regra no pai, ocorrências geradas sob demanda) é o melhor compromisso entre desempenho e flexibilidade.
- A UX progressiva — simples por padrão, poderosa como opção — é a chave para não perder nenhum usuário.
- Um bom sistema de recorrência requer no mínimo 4 tipos de regras e um gerenciamento robusto de casos extremos.

Por que os lembretes recorrentes são tão complexos de implementar?

Quando você pensa em "lembrete recorrente", provavelmente imagina um simples setInterval ou um cron job. A realidade é muito mais complicada. TAMSIV suporta quatro tipos de recorrência: diária, semanal, mensal e personalizada. O caso diário leva 10 minutos para codificar. O caso "a última sexta-feira de cada mês"? Dias.

O problema fundamental é que o calendário não é regular. Os meses têm 28, 29, 30 ou 31 dias. As semanas se sobrepõem aos meses. Anos bissextos existem. E os fusos horários adicionam uma camada extra de caos.

Como desenvolvedor solo do TAMSIV, tive que tomar decisões arquitetônicas críticas desde o início para evitar refatorar tudo mais tarde.

Aplicativo móvel exibindo um calendário com lembretes recorrentes coloridos e notificações repetitivas
Um sistema de lembretes recorrentes bem projetado deve gerenciar dezenas de casos extremos invisíveis para o usuário.

Como lidar com o problema do "dia 31 de cada mês"?

Este é o caso clássico que todo desenvolvedor de calendário teme. O usuário cria um lembrete no dia 31 de janeiro com recorrência mensal. O que acontece em fevereiro? Em abril?

Existem três abordagens:

  1. Pular o mês: sem lembrete em fevereiro. Má UX — o usuário pensa que é um bug.
  2. Deslocamento para o último dia: o lembrete passa para o dia 28 (ou 29) de fevereiro, 30 de abril, etc. É intuitivo.
  3. Forçar o 1º dia do mês seguinte: lógico para alguns casos, mas confuso.

Escolhi a opção 2 — o deslocamento automático para o último dia do mês. Por quê? Porque é o que o usuário espera sem pensar. Quando alguém diz "todo mês", quer dizer "aproximadamente na mesma data todo mês". O pragmatismo vence o rigor matemático.

Essa escolha tem um impacto direto no código. Para cada ocorrência, primeiro calculo a data teórica e depois verifico se ela existe no mês alvo com Math.min(diaOriginal, ultimoDiaDoMes). Simples na aparência, mas precisa ser feito para cada ocorrência gerada.

Qual é o melhor modelo de armazenamento para eventos recorrentes?

Esta é a questão arquitetônica chave. Duas escolas se confrontam:

Opção A: armazenar todas as ocorrências. Você gera 365 linhas no banco de dados para um lembrete diário anual. Vantagem: consultas simples. Desvantagem: explosão do banco de dados e complexidade de modificação (mudar a hora do lembrete = modificar 365 linhas).

Opção B: armazenar apenas a regra. Você mantém "toda terça-feira às 9h" e calcula na hora. Vantagem: banco de dados leve. Desvantagem: consultas complexas para saber "quais lembretes caem esta semana?".

Optei por um modelo híbrido no TAMSIV: a regra de recorrência é armazenada no evento pai, e as ocorrências são geradas sob demanda. Quando um lembrete é convertido em evento de calendário — por exemplo, via o sistema de agenda com filtros — uma ocorrência concreta é criada no banco de dados.

Desenvolvedor trabalhando à noite em frente a uma tela exibindo um esquema de banco de dados com tabelas de calendário
O armazenamento híbrido combina o melhor das duas abordagens: leveza do banco de dados e simplicidade das consultas.

Concretamente, a estrutura do banco de dados se parece com isto:

  • Tabela pai: contém o título, a descrição e um campo JSON com a regra de recorrência (type, interval, daysOfWeek, endDate)
  • Tabela de ocorrências: criada sob demanda quando o usuário interage (completa, adia, modifica)
  • Cálculo dinâmico: para a exibição do calendário, as ocorrências futuras são calculadas no lado do cliente

Este modelo híbrido evita as consultas N+1, mantendo o banco de dados sob controle. Com o sistema de cache otimizado, o desempenho permanece excelente mesmo com centenas de lembretes.

Como criar um lembrete recorrente por voz?

Uma das vantagens únicas do TAMSIV é que você pode criar lembretes complexos falando naturalmente. O pipeline de voz IA analisa sua frase e extrai automaticamente a regra de recorrência.

Exemplos concretos:

  • "Lembre-me de regar as plantas a cada 3 dias" → recorrência personalizada, intervalo de 3 dias
  • "Reunião de equipe toda segunda e quarta-feira às 10h" → semanal, dias específicos
  • "Pagar o aluguel no primeiro dia de cada mês" → mensal, dia fixo com gerenciamento de casos extremos
  • "Aniversário de Maria em 15 de março todo ano" → anual

O LLM (via OpenRouter) decompõe a frase em intenções estruturadas. A função create_calendar_event então recebe um objeto com os parâmetros de recorrência já extraídos. O usuário só precisa validar — ou modificar — antes de salvar no banco de dados.

Esta é a força do gravador de voz integrado: tornar a complexidade técnica invisível para o usuário final.

Quais são as armadilhas dos fusos horários com os lembretes?

Se você acha que os meses irregulares são problemáticos, espere para ver os fusos horários. Um lembrete diário às 9h dispara às 9h hora local. Mas o que é "9h hora local" quando o usuário viaja? Quando ocorre a mudança de horário de verão/inverno?

Duas estratégias possíveis:

  • Armazenar em UTC e converter na renderização: limpo, mas problemático para "9h todos os dias" (que pode se tornar 8h ou 10h dependendo da estação)
  • Armazenar em hora local com fuso horário: mais fiel à intenção, mas mais complexo de gerenciar no banco de dados

No TAMSIV, optei pelo armazenamento em UTC com o fuso horário de referência do usuário. Quando o cálculo da ocorrência cai em um dia de mudança de horário, o sistema ajusta para manter a hora local estável. Este é o comportamento que os usuários do Google Calendar ou Apple Calendar esperam.

Como projetar a UX dos lembretes sem sobrecarregar o usuário?

O desafio da UX é tão importante quanto o desafio técnico. Como apresentar regras de recorrência potencialmente complexas sem perder o usuário ocasional?

A resposta: o design progressivo (progressive disclosure).

Interface móvel minimalista mostrando um padrão UX de divulgação progressiva com opções simples e um painel avançado
O design progressivo mostra primeiro as opções simples e depois revela o poder sob demanda.

Veja como implementei isso no TAMSIV:

  1. Nível 1 — 4 botões simples: Todos os dias, Todas as semanas, Todos os meses, Sem recorrência. Cobre 80% das necessidades.
  2. Nível 2 — Painel avançado: acessível via "Personalizar". Dias da semana selecionáveis, intervalo personalizado (a cada N dias/semanas/meses), data de término opcional.
  3. Nível 3 — Casos complexos: "A última sexta-feira do mês", "A 2ª terça-feira de cada mês". Interface especializada para essas regras raras.

O princípio orientador: simples por padrão, poderoso como opção. O usuário ocasional nunca deve se sentir perdido. O usuário avançado nunca deve se sentir limitado. Este princípio também guia o sistema de onboarding do aplicativo.

Também implementei a navegação por swipe nas telas de lembretes para tornar a experiência mais fluida.

Qual a diferença para os lembretes do Google Calendar ou Todoist?

Soluções existentes como Todoist ou Google Calendar gerenciam bem as recorrências. Mas todas têm o mesmo defeito: a entrada manual.

Com o TAMSIV, a criação por voz muda fundamentalmente a equação. Dizer "lembre-me de enviar o relatório toda sexta-feira às 17h" é incomparavelmente mais rápido do que navegar por 3 menus para configurar a mesma coisa manualmente.

Além disso, o sistema de gamificação recompensa a conclusão de lembretes recorrentes, o que cria um ciclo virtuoso de produtividade. Cada tarefa recorrente concluída alimenta sua sequência e o aproxima do próximo nível.

Quais lições tirar da implementação das recorrências?

Depois de codificar este sistema, estas são as lições que tiro:

  • Não subestime os casos extremos: o "dia 31 do mês", os anos bissextos, as mudanças de horário — cada caso parece raro individualmente, mas coletivamente eles afetam milhares de usuários.
  • Teste com dados reais: os testes unitários não são suficientes. É preciso simular um ano inteiro de ocorrências e verificar visualmente.
  • O modelo híbrido é o bom compromisso: nem tudo no banco de dados, nem tudo calculado. A mistura oferece o melhor dos dois mundos.
  • A UX progressiva salva vidas: esconder a complexidade por trás de níveis de detalhe é a única abordagem viável para um aplicativo de consumo.

Se você está desenvolvendo um aplicativo de produtividade ou um sistema de calendário, nunca subestime os lembretes recorrentes. O que parece ser um recurso de 2 dias pode facilmente levar 10.

FAQ

Quantos tipos de recorrência o TAMSIV suporta?

O TAMSIV suporta quatro tipos principais: diário, semanal, mensal e personalizado. O modo personalizado permite definir qualquer intervalo (a cada N dias, certos dias da semana, etc.) e cobre casos avançados como "a última sexta-feira do mês".

É possível criar um lembrete recorrente por voz?

Sim, este é um dos pontos fortes do TAMSIV. Você pode dizer "lembre-me de enviar o relatório toda segunda-feira às 9h" e a IA entende automaticamente o tipo de recorrência, o dia e a hora. Basta validar para que o lembrete seja criado.

O que acontece se um lembrete mensal cair em um dia que não existe?

O TAMSIV desloca automaticamente o lembrete para o último dia do mês. Por exemplo, um lembrete no dia 31 será antecipado para o dia 28 ou 29 em fevereiro, e para o dia 30 em abril, junho, setembro e novembro. Este é o comportamento mais intuitivo para o usuário.

Os lembretes recorrentes funcionam com a gamificação?

Absolutamente. Cada conclusão de um lembrete recorrente rende pontos de experiência e alimenta sua sequência diária. É uma excelente maneira de manter uma rotina produtiva e permanecer motivado a longo prazo.

Como modificar ou excluir uma única ocorrência de um lembrete recorrente?

Você pode modificar ou excluir uma ocorrência específica sem afetar as outras. O sistema então cria uma "exceção" para essa data. O restante da série continua normalmente de acordo com a regra definida.