Duas tabelas locais
Category e Task provam relacionamento, filtro e atualização de UI por evento.
Fatia de dadosCombine SDKs gerados com arquitetura SPA ou PWA, persistência IndexedDB e o mesmo vocabulário de contratos do backend.

bun install
bun run cli
bun run dev:expressDo zero ao primeiro MVP
Use este caminho quando o primeiro MVP precisa rodar no browser, manter estado local e depois sincronizar com contratos backend.
Comece com tabelas Category e Task, um filtro, uma ação de create e um evento que a UI consegue ouvir.
Saída MVP: modelo de dados browser com fluxo visível.
const schema = {
version: 1,
stores: [
{ name: 'categories', keyPath: 'id', indexes: [{ name: 'byName', keyPath: 'name', unique: true }] },
{
name: 'tasks',
keyPath: 'id',
indexes: [
{ name: 'byCategory', keyPath: 'categoryId' },
{ name: 'byCompleted', keyPath: 'completed' }
]
}
]
} as const;Escopo MVP
Category e Task provam relacionamento, filtro e atualização de UI por evento.
Fatia de dadosUse Context, Redux ou Pinia como primeira superfície de integração.
Fatia de UIDocumente se o MVP é local-only, sync-later ou apoiado por API.
Fatia de produto| Área de prova | Pergunta a responder | Mecanismo Jumentix | Evidência MVP |
|---|---|---|---|
| Dados locais | O app cria e lê registros sem servidor? | Playground Cana/browser in-memory e checks de persistência local. | O primeiro fluxo funciona offline. |
| Atualizações de estado | Componentes atualizam a partir dos eventos do Cana? | Exemplos React/Vue de state management e assertions de listener. | UI permanece consistente com dados locais. |
| Backend futuro | O mesmo vocabulário mapeia para contratos de API depois? | Nomes de SDK gerado e paridade de contrato Category/Task. | O MVP frontend não inventa outro domínio. |
Implementação prática
Estes exemplos mantêm Category e Task como vocabulário de produto e mostram controller, contrato, client, worker ou camada de estado necessários para chegar a um MVP executável.
type Category = { id: string; name: string };
type Task = { id: string; title: string; categoryId: string; completed: boolean };
const categories = new Map<string, Category>([
['work', { id: 'work', name: 'Work' }]
]);
const tasks = new Map<string, Task>();
const listeners = new Set<() => void>();
export function subscribe(listener: () => void) {
listeners.add(listener);
return () => listeners.delete(listener);
}
export function createTask(input: { title: string; categoryId: string }) {
if (!categories.has(input.categoryId)) throw new Error('category not found');
const task = { id: crypto.randomUUID(), completed: false, ...input };
tasks.set(task.id, task);
listeners.forEach((listener) => listener());
return task;
}
export function listTaskCards() {
return [...tasks.values()].map((task) => ({
...task,
category: categories.get(task.categoryId)
}));
}Continue explorando
Entregue serviços OpenAPI 3.1 com adaptadores HTTP nativos intercambiáveis.
Explore o blueprintExecute Socket.IO ou gRPC ao lado de fallback REST e documentação AsyncAPI.
Explore o blueprintLance um deploy com limites de domínio prontos para virar serviços.
Explore o blueprintMantenha a comunicação entre serviços baseada em contratos com o Message Mediator.
Explore o blueprintCrie produtos frontend que compartilham SDKs gerados e funcionam offline.
Explore o blueprintExplore o código, execute a fábrica localmente e transforme seu próximo serviço Node.js em uma capacidade repetível de plataforma.