Habit Builder é uma Progressive Web App (PWA) moderna e completa para construção e acompanhamento de hábitos diários. O aplicativo permite que usuários criem pequenas tarefas diárias que, com o tempo, se transformam em hábitos sólidos através de tracking visual, gamificação e estatísticas detalhadas.
- ✅ Optimistic Updates - UI responde instantaneamente, sem delays perceptíveis
- 🔄 Estado na URL - Compartilhável via nuqs (search params type-safe)
- 📱 PWA Completo - Funciona offline, instalável, com Service Worker
- 🎨 Design Moderno - Dark mode, glassmorphism, animações suaves
- 📊 Estatísticas Avançadas - Gráficos, streaks, insights inteligentes
- 🎯 Múltiplos Tipos de Hábitos - Counter, Timer, Pomodoro
- 👥 Grupos de Hábitos - Organize hábitos em grupos temáticos
- 🎨 Personalização Completa - Ícones, cores, templates pré-definidos
| Tecnologia | Versão | Propósito |
|---|---|---|
| Next.js | 16.0.10 | Framework React com App Router |
| React | 19.2.0 | Biblioteca UI |
| TypeScript | 5.x | Type safety |
| Zustand | 5.0.9 | State management global |
| nuqs | 2.8.5 | Search params type-safe |
| Tailwind CSS | 4.1.9 | Estilização |
| shadcn/ui | Latest | Componentes UI |
| Sonner | 1.7.4 | Toast notifications |
| date-fns | 4.1.0 | Manipulação de datas |
| Recharts | 2.15.4 | Gráficos e visualizações |
┌─────────────────────────────────────────┐
│ UI Components (React) │
│ (Presentation Layer - Client Components)│
└──────────────┬──────────────────────────┘
│
↓
┌─────────────────────────────────────────┐
│ Search Params (nuqs) │
│ (Estado compartilhável via URL) │
└──────────────┬──────────────────────────┘
│
↓
┌─────────────────────────────────────────┐
│ Zustand Store │
│ (State Management + Business Logic) │
│ - Optimistic Updates │
│ - Rollback automático │
│ - Persistência localStorage │
└──────────────┬──────────────────────────┘
│
↓
┌─────────────────────────────────────────┐
│ API Layer (Simulada) │
│ (habits-api.ts) │
│ - Delay realista (200-500ms) │
│ - Taxa de erro configurável │
│ - Pronta para substituição por API real│
└─────────────────────────────────────────┘
habit/
├── app/ # Next.js App Router
│ ├── layout.tsx # Layout raiz com providers
│ ├── page.tsx # Página principal (Home)
│ ├── client-providers.tsx # Providers client-side
│ ├── habitos/
│ │ └── page.tsx # Página de hábitos
│ ├── estatisticas/
│ │ └── page.tsx # Página de estatísticas
│ └── configuracoes/
│ └── page.tsx # Página de configurações
│
├── components/ # Componentes React
│ ├── atoms/ # Componentes atômicos
│ │ ├── badge.tsx
│ │ └── icon.tsx
│ ├── molecules/ # Componentes moleculares
│ │ ├── habit-card.tsx
│ │ ├── counter-control.tsx
│ │ ├── timer-control.tsx
│ │ ├── pomodoro-control.tsx
│ │ ├── progress-chart.tsx
│ │ ├── category-stats.tsx
│ │ └── ...
│ ├── organisms/ # Componentes complexos
│ │ ├── habit-list.tsx
│ │ ├── habit-modal.tsx
│ │ ├── habit-creation-modal.tsx
│ │ ├── templates-modal.tsx
│ │ ├── group-creation-modal.tsx
│ │ ├── weekly-calendar.tsx
│ │ ├── bottom-navigation.tsx
│ │ ├── error-boundary.tsx
│ │ ├── offline-indicator.tsx
│ │ ├── pwa-install-banner.tsx
│ │ └── ...
│ └── ui/ # Componentes shadcn/ui
│ ├── button.tsx
│ ├── dialog.tsx
│ ├── card.tsx
│ └── ...
│
├── lib/ # Lógica de negócio
│ ├── api/
│ │ └── habits-api.ts # Camada de API (simulada)
│ ├── stores/
│ │ ├── habits-store.ts # Store principal Zustand
│ │ └── ui-store.ts # Store de UI
│ ├── hooks/
│ │ ├── use-search-params.ts # Hooks nuqs
│ │ ├── use-habit-data.ts # Hooks de dados
│ │ ├── use-habit-progress.ts
│ │ ├── use-calendar-completion.ts
│ │ └── ...
│ ├── types/
│ │ └── habit.ts # TypeScript types
│ ├── utils/
│ │ ├── habit-helpers.ts # Helpers de hábitos
│ │ ├── stats-helpers.ts # Cálculos estatísticos
│ │ ├── date-helpers.ts # Helpers de data
│ │ ├── group-templates.ts # Templates de grupos
│ │ └── ...
│ ├── contexts/
│ │ └── dialog-context.tsx # Context de diálogos
│ └── mock-data/
│ └── habits-mock.json # Dados mock para desenvolvimento
│
├── public/ # Arquivos estáticos
│ ├── manifest.json # PWA manifest
│ ├── sw.js # Service Worker
│ ├── icon-192.png
│ ├── icon-512.png
│ └── apple-icon-180.png
│
├── scripts/ # Scripts utilitários
│ ├── dev.js # Script de desenvolvimento
│ ├── generate-icons.js # Geração de ícones
│ └── sync-version.js # Sincronização de versão
│
└── ARQUITETURA.md # Documentação arquitetural detalhada
O sistema implementa Optimistic Updates em todas as operações CRUD, garantindo que a UI responda instantaneamente enquanto a API processa em background.
// 1️⃣ Usuário clica "Criar hábito"
await addHabit(habitData);
// 2️⃣ Store atualiza IMEDIATAMENTE (optimistic)
const tempId = `temp-${Date.now()}`;
set({
habits: [...habits, optimisticHabit],
pendingOperations: pendingOperations + 1,
});
// ✅ UI já mostra o novo hábito!
// 3️⃣ Chamada API em background
const serverHabit = await HabitsAPI.createHabit(habitData);
// 4️⃣ SUCESSO: Substitui temp com real
set({
habits: habits.map((h) => (h.id === tempId ? serverHabit : h)),
pendingOperations: pendingOperations - 1,
});
toast.success("Hábito criado!");
// OU 4️⃣ ERRO: Rollback automático
set({
habits: habits.filter((h) => h.id !== tempId),
pendingOperations: pendingOperations - 1,
});
toast.error("Erro ao criar hábito");
// ✅ UI volta ao estado anterior automaticamente- ✅
addHabit- Criar hábito - ✅
updateHabit- Atualizar hábito - ✅
deleteHabit- Deletar hábito - ✅
reorderHabits- Reordenar hábitos - ✅
markComplete- Marcar como completo - ✅
updateTimer- Atualizar timer - ✅
updatePomodoro- Atualizar pomodoro - ✅
addGroup- Criar grupo - ✅
updateGroup- Atualizar grupo - ✅
deleteGroup- Deletar grupo - ✅
assignHabitToGroup- Atribuir hábito a grupo
- 0ms de delay percebido - UI sempre responsiva
- Melhor UX - Feedback imediato
- Rollback automático - Em caso de erro, UI reverte
- Indicador de sincronização -
pendingOperationsmostra ops pendentes
O estado da aplicação é gerenciado através da URL usando nuqs, permitindo compartilhamento, bookmarks e navegação com botão voltar.
// Hook completo com todos os params
const {
day, // Data selecionada (Date)
category, // Categoria filtrada
habit, // Hábito selecionado (modal)
group, // Grupo(s) aberto(s)
view, // Modo de visualização (week/month/year)
search, // Busca/filtro
setDay,
setCategory,
setHabit,
clearFilters,
resetAll,
} = useAppSearchParams();
// Hook simplificado para data
const {
selectedDay,
setSelectedDay,
isToday,
goToPreviousDay,
goToNextDay,
goToToday,
} = useSelectedDay();
// Hook para categoria
const { selectedCategory, setSelectedCategory } = useSelectedCategory();
// Hook para hábito (modal)
const { selectedHabitId, openHabit, closeHabit, isOpen } = useSelectedHabit();
// Hook para visualização do calendário
const { calendarView, setCalendarView } = useCalendarView();/?day=12102025&category=saude&habit=abc123&view=week
day: Data no formato DDMMYYYY (ex:12102025= 12/10/2025)category:bons|saude|maus|tarefas|todoshabit: ID do hábito selecionadogroup: IDs dos grupos abertos (separados por vírgula)view:week|month|year
- ✅ Estado compartilhável via URL
- ✅ Bookmarks funcionam perfeitamente
- ✅ Botão voltar do navegador funciona
- ✅ Type-safe com TypeScript
- ✅ SSR-friendly
-
Counter (Contador)
- Incrementa/decrementa contador
- Meta: número de repetições (ex: 8 copos de água)
-
Timer (Cronômetro)
- Rastreia tempo gasto
- Meta: minutos (ex: 30 min de leitura)
-
Pomodoro (Técnica Pomodoro)
- Sessões de trabalho/descanso
- Meta: número de sessões (ex: 4 pomodoros)
- ✅ Criar hábito personalizado
- ✅ Escolher templates pré-definidos (30+ templates)
- ✅ Editar hábito (nome, ícone, cores, meta)
- ✅ Deletar hábito
- ✅ Reordenar hábitos (drag & drop)
- ✅ Personalização completa (ícones Lucide, cores)
- ✅ Marcar conclusão de hábitos
- ✅ Contador de repetições
- ✅ Streak (sequência de dias consecutivos)
- ✅ Calendário visual semanal/mensal/anual
- ✅ Histórico completo de progresso
- ✅ Undo/Redo de ações
- ✅ Criar grupos temáticos
- ✅ Templates de grupos pré-definidos (12 templates)
- ✅ Atribuir hábitos a grupos
- ✅ Visualização por grupo
- ✅ Expandir/colapsar grupos
- 📊 Taxa de conclusão hoje - Percentual de hábitos completados hoje
- 🔥 Streak total - Soma de todos os streaks
- 📈 Gráfico de progresso - Últimos 7 dias visualizados
- 📅 Estatísticas por categoria - Bons, Saúde, Maus, Tarefas
- 🎯 Hábito mais consistente - Maior streak atual
- 💯 Melhor performance - Maior taxa de conclusão
- 📊 Completions da semana - Total da semana atual
- 📊 Completions do mês - Total do mês atual
- "Seu melhor dia da semana é Segunda"
- "Beber água é seu hábito mais consistente"
- "Você melhorou 15% na última semana"
- Bons - Hábitos positivos gerais
- Saúde - Exercícios, alimentação, bem-estar
- Maus - Hábitos a evitar
- Tarefas - Tarefas diárias e produtividade
- 🛏️ Fazer a cama
- 💧 Beber água
- 📚 Ler livro
- 🏋️ Treino academia
- 🧘 Meditar
- 💊 Tomar vitaminas
- 🎸 Praticar violão
- 📝 Escrever diário
- E muitos mais...
- Saúde & Bem-estar
- Produtividade
- Estudos
- Fitness
- Alimentação
- Mindfulness
- Trabalho
- Criatividade
- Social
- Finanças
- Casa
- Sono
- ✅ Cache de assets estáticos
- ✅ Estratégia Network First com fallback para Cache
- ✅ Atualização automática de versão
- ✅ Limpeza de caches antigos
- ✅ Funcionamento offline completo
- ✅ Instalável em dispositivos móveis
- ✅ Ícones para todas as plataformas (192x192, 512x512, Apple 180x180)
- ✅ Splash screens
- ✅ Tema escuro padrão
- ✅ Modo standalone
- ✅ Offline Indicator - Mostra status de conexão
- ✅ PWA Install Banner - Convite para instalar
- ✅ PWA Update Banner - Notifica atualizações disponíveis
- ✅ App Updating Screen - Tela durante atualização
- ⚙️ Limpar todos os dados
- 💾 Importar/Exportar dados (JSON)
- 🔄 Sincronizar com servidor (quando implementado)
- 📊 Carregar dados mock para desenvolvimento
- Tema Principal: Dark mode com cores vibrantes
- Paleta de Cores:
- Primary: Roxo/Indigo (#6366F1)
- Success: Verde (#10B981)
- Warning: Amarelo/Laranja (#F59E0B)
- Danger: Vermelho (#EF4444)
- Purple: Rosa/Roxo (#D946EF)
- Base: shadcn/ui
- Estilização: Tailwind CSS v4
- Ícones: Lucide React (50+ ícones disponíveis)
- Animações: Framer Motion
- Tipografia: Sistema de fontes nativas
- Atoms: Badge, Icon, Button
- Molecules: HabitCard, CounterControl, TimerControl, ProgressChart
- Organisms: HabitList, HabitModal, WeeklyCalendar, BottomNavigation
- Templates: Layout principal, páginas
- Pages: Home, Estatísticas, Configurações
interface StoredData {
habits: Habit[];
progress: Progress[];
groups: HabitGroup[];
currentDate: Date;
skipAutoLoad: boolean;
}- ✅ Persistência automática via Zustand persist middleware
- ✅ Rehydrate automático ao carregar aplicação
- ✅ Conversão automática de strings para Date objects
- ✅ Tratamento de erros de parsing
// lib/api/habits-api.ts
export class HabitsAPI {
static async getHabits(): Promise<Habit[]>;
static async createHabit(data: CreateHabitDTO): Promise<Habit>;
static async updateHabit(id: string, data: UpdateHabitDTO): Promise<Habit>;
static async deleteHabit(id: string): Promise<void>;
static async markComplete(
habitId: string,
date: Date,
count: number
): Promise<Progress>;
// ... mais métodos
}Características:
- Delay realista (200-500ms)
- Taxa de erro configurável (desabilitada por padrão)
- Pronta para substituição por API real
# Clone o repositório
git clone <repo-url>
cd habit
# Instale as dependências
npm install
# ou
pnpm install
# Execute em desenvolvimento
npm run dev
# ou
pnpm devnpm run dev # Desenvolvimento (com hot reload)
npm run build # Build de produção
npm run start # Servidor de produção
npm run lint # Linter
npm run generate-icons # Gerar ícones PWA
npm run version:sync # Sincronizar versão- Carregar dados mock: Os dados mock são carregados automaticamente na primeira execução
- Criar hábito: Clique no botão "+" e escolha um template ou crie customizado
- Marcar como completo: Clique no card do hábito ou use os controles
- Ver estatísticas: Navegue para a aba "Estatísticas"
- Personalizar: Clique em um hábito → Editar → Personalize ícone e cores
import { useHabitsStore } from "@/lib/stores/habits-store";
const { addHabit } = useHabitsStore();
await addHabit({
title: "Beber água",
icon: "Droplet",
color: "#60a5fa",
category: "saude",
frequency: "daily",
habitType: "counter",
targetCount: 8,
description: "8 copos de água por dia",
});
// ✅ UI atualiza instantaneamente!import { useHabitsStore } from "@/lib/stores/habits-store";
import { useSelectedDay } from "@/lib/hooks/use-search-params";
const { markComplete } = useHabitsStore();
const { selectedDay } = useSelectedDay();
await markComplete(habitId, selectedDay, 1);
// ✅ Progresso atualizado imediatamente!import { useHabitStatistics } from "@/lib/hooks/use-habit-data";
const {
totalStreak,
completionRateToday,
statsByCategory,
mostConsistent,
bestCompletion,
insights,
} = useHabitStatistics();import {
useSelectedDay,
useSelectedCategory,
} from "@/lib/hooks/use-search-params";
const { selectedDay, goToNextDay } = useSelectedDay();
const { selectedCategory, setSelectedCategory } = useSelectedCategory();
// URL atualiza automaticamente: /?day=12102025&category=saudeO projeto inclui dados mock completos para desenvolvimento:
- 25 hábitos diversos
- 60 dias de histórico de progresso
- 1178 registros de progresso gerados
- Variação realista baseada em categoria e dia da semana
import { useHabitData } from "@/lib/hooks/use-habit-data";
// Carrega automaticamente se não houver dados
useHabitData();Ou manualmente:
import { useHabitsStore } from "@/lib/stores/habits-store";
const { loadMockData } = useHabitsStore();
loadMockData();Tudo é type-safe com TypeScript:
// ✅ Type-safe
const { selectedCategory } = useSelectedCategory();
// selectedCategory: "bons" | "saude" | "maus" | "tarefas" | "todos"
// ✅ Type-safe
await updateHabit(id, { title: "Novo nome" });
// Autocomplete funciona!
// ❌ Type error
await updateHabit(id, { invalid: "field" });
// Error: Object literal may only specify known properties-
Substituir API Simulada por Real
// De: await HabitsAPI.createHabit(data); // Para: await fetch("/api/habits", { method: "POST", body: JSON.stringify(data), });
-
Adicionar Autenticação
- NextAuth ou Better Auth
- Tokens nas chamadas API
- Proteção de rotas
-
WebSocket para Sync em Tempo Real
- Atualiza quando outro device faz mudanças
- Notificações push
-
Offline-First Avançado
- Queue de operações quando offline
- Sync quando reconectar
- Resolução de conflitos
- ✅ 0ms de delay percebido (optimistic updates)
- ✅ UI sempre responsiva mesmo com internet lenta
- ✅ Code splitting automático (Next.js)
- ✅ Lazy loading de modais e componentes pesados
- ✅ Memoização de cálculos estatísticos
- ✅ Bundle otimizado com tree-shaking
- ⚡ Server Components por padrão
- 🎨 CSS-in-JS evitado (Tailwind only)
- 📦 Code splitting automático
- 🖼️ Lazy loading de imagens
- 💨 Debounce em inputs
- 🔄 Optimistic updates
- 📱 Mobile-first responsive
- Unit tests: Vitest
- Integration tests: Testing Library
- E2E tests: Playwright
- Coverage mínimo: 80%
- ✅ Service Worker configurado
- ✅ Manifest.json completo
- ✅ Offline functionality
- ✅ Install prompt
- ✅ App icons (192x192, 512x512, Apple 180x180)
- ✅ Splash screens
- ✅ Update notifications
- ⏳ Push notifications (opcional)
- ✅ Input validation
- ✅ XSS prevention
- ✅ Data sanitization
- ✅ Secure cookie settings (quando implementado)
- ✅ Content Security Policy (via headers)
- ✅ Error boundaries para captura de erros
- ✅ Logging estruturado de erros
- ARQUITETURA.md - Documentação arquitetural detalhada
- CHANGELOG.md - Histórico de mudanças
- Estrutura básica do projeto
- CRUD de hábitos
- Tracking diário
- Calendário semanal/mensal/anual
- Templates pré-definidos
- PWA básico
- Estatísticas detalhadas
- Grupos de hábitos
- Personalização completa
- Notificações push
- Temas customizáveis
- Backup na nuvem
- Exportação de relatórios
- Comparação entre períodos
- Backend completo
- Autenticação
- Sync multi-device
- Social features
- Achievements/Badges
- Compartilhamento de hábitos
Este é um projeto em desenvolvimento ativo. Contribuições são bem-vindas!
- Fork o projeto
- Crie uma branch para sua feature (
git checkout -b feature/AmazingFeature) - Commit suas mudanças (
git commit -m 'Add some AmazingFeature') - Push para a branch (
git push origin feature/AmazingFeature) - Abra um Pull Request
MIT License
- Optimistic UI - Atualiza antes da confirmação
- Pessimistic Rollback - Desfaz se API falhar
- State in URL - nuqs para compartilhar estado
- Separation of Concerns - API / Store / UI separados
- Type Safety - TypeScript em todo lugar
- Error Boundaries - Try/catch + toasts + ErrorBoundary
- Persistence - localStorage para offline
- Middleware - Zustand persist
- Atomic Design - Estrutura de componentes
- PWA Best Practices - Service Worker, Manifest, Offline
Desenvolvido com ❤️ usando Next.js, TypeScript, Zustand e Tailwind CSS
Para dúvidas, sugestões ou problemas, abra uma issue no repositório.