Task manager construído com um mini framework reativo vanilla JS
Sem React. Sem Vue. Sem dependências. Só JavaScript puro.
Flux é um task manager desenvolvido do zero com o objetivo de entender como frameworks modernos funcionam por baixo dos panos.
Em vez de usar React ou Vue, o projeto implementa seu próprio core reativo em JavaScript puro — com os mesmos conceitos que grandes frameworks usam internamente: reatividade via Proxy, reconciliação de DOM via Diff e gerenciamento de eventos via Dispatch.
O resultado é um app funcional, reativo e modular — provando que os fundamentos da web são suficientes para construir interfaces complexas.
- Criar, editar e excluir tarefas
- Checklist de subitens por tarefa
- Filtros — Todas, Ativas e Concluídas
- Painel lateral com progresso e estatísticas
- Visão rápida de tarefas pendentes
- Interface totalmente reativa — sem recarregar a página
O coração do projeto é um mini framework construído do zero com 4 pilares:
Intercepta mudanças no estado automaticamente. Qualquer alteração dispara o render sem precisar chamar nada manualmente.
const stateReactive = new Proxy(state, {
set(target, prop, value) {
if (target[prop] === value) return true;
target[prop] = value;
listeners.forEach(listener => listener(target)); // render automático
return true;
}
});Compara o DOM atual com o novo gerado pelo template e aplica apenas as mudanças mínimas necessárias — sem destruir e recriar tudo.
function diff(parent, oldNode, newNode) {
if (!oldNode) return parent.appendChild(newNode);
if (!newNode) return parent.removeChild(oldNode);
if (oldNode.nodeName !== newNode.nodeName) return parent.replaceChild(newNode, oldNode);
if (oldNode.nodeType === Node.TEXT_NODE) {
if (oldNode.textContent !== newNode.textContent)
oldNode.textContent = newNode.textContent;
return;
}
patchAttributes(oldNode, newNode);
// recursão nos filhos...
}Registra handlers com IDs únicos via bind(). O HTML chama window.__dispatch() que localiza e executa o handler correto com acesso ao estado reativo.
// fora do template — criado uma única vez
const onAddTask = bind((event, state) => {
state.tasks = [...state.tasks, newTask];
});
// no template
const Template = ({ state }) => `
<button onclick="${onAddTask}">Adicionar</button>
`;Inspirado no Angular — o estado atualiza a view e a view atualiza o estado. Foco e posição do cursor são preservados durante re-renders.
<input
data-bind="taskName"
value="${state.taskName}"
oninput="${onTaskNameInput}"
/>flux/
├── public/
│ ├── index.html
│ ├── app/
│ │ ├── js/
│ │ │ └── core.js # core reativo
│ │ ├── pages/
│ │ │ └── Template.js # template principal
│ │ └── components/
│ │ ├── dashboard/ # painel lateral
│ │ ├── workspace/ # área de tarefas
│ │ ├── tasks/ # item de tarefa
│ │ ├── overlays/ # painéis e modais
│ │ ├── ui/ # Button, Input, Icon
│ │ └── shared/ # componentes compartilhados
├── server/
│ └── index.js # servidor local (dev)
├── vercel.json
└── package.json
Pré-requisitos: Node.js 18+
# Clone o repositório
git clone https://github.com/seu-user/flux.git
cd flux
# Instale as dependências de desenvolvimento
npm install
# Inicie o servidor local
npm run devAcesse http://localhost:3000
O projeto não tem build — é JavaScript puro servido como arquivo estático.
Ou manualmente:
- Importe o repositório na Vercel
- Deixe Build Command e Install Command vazios
- Configure Output Directory como
public - Deploy
Este projeto foi construído para responder uma pergunta: é possível construir uma interface reativa complexa sem nenhum framework?
A resposta é sim — e o processo de construir o core (motor) do zero trouxe clareza sobre o que React, Vue e Angular fazem internamente:
- Por que o estado não pode ser mutado diretamente
- Como o Virtual DOM decide o que atualizar
- Por que handlers precisam ser estáveis entre re-renders
- Como o two-way binding preserva a experiência do usuário
- JavaScript ES2022+
- ES Modules nativos
- HTML5 e CSS3
- Node.js (apenas desenvolvimento local)
- Vercel (deploy)