Documentação de engenharia
Os detalhes técnicos por trás do ContractFlow: a arquitetura client-side (zero-knowledge), o context engine multi-nicho, a geração de PDF no navegador e o PWA offline-first.
1. Arquitetura privacy-first
Ao contrário de SaaS tradicionais, o ContractFlow adota uma abordagem zero-knowledge no servidor. Toda a lógica de negócio, a persistência de dados e a geração de arquivos acontece no dispositivo do cliente.
Server side
Apenas hospedagem estática (HTML/JS/assets). Nenhum banco de dados.
Client side
Engine de templates, render de PDF, localStorage e service workers.
2. Context engine multi-nicho
O sistema usa um dicionário de dados estruturado para adaptar a interface conforme a profissão selecionada. Isso permite escalar para novos nichos sem tocar na lógica principal.
const INDUSTRY_DATA = { dev: { templates: [ { label: 'Site Institucional', icon: 'fa-laptop-code', items: [...] }, { label: 'App Mobile', icon: 'fa-mobile-screen', items: [...] } ] }, marketing: { templates: [ { label: 'Gestão de Tráfego', icon: 'fa-chart-line', items: [...] } ] } // Fácil extensão para novos nichos };
3. Geração de PDF no client
Usamos a biblioteca jsPDF para desenhar o documento vetorizado, pixel-perfect, direto no canvas do navegador.
O sistema injeta imagens (logos) convertendo-as para Base64 em tempo de execução.
async function generatePDF() { const doc = new window.jsPDF({ format: 'a4' }); // 1. Cabeçalho da marca (cor por template) doc.setFillColor(30, 58, 138); doc.rect(0, 0, pageWidth, 40, 'F'); // 2. Processamento do logo (white label) if (logoInput.files[0]) { const imgData = await readFileAsDataURL(logoInput.files[0]); doc.addImage(imgData, 'PNG', ...coords); } doc.save('Contrato_Final.pdf'); }
4. PWA & offline-first
Service Workers cacheiam os assets críticos (CSS, fontes, libs JS), o que permite instalar o app (adicionar à tela inicial) e usá-lo sem conexão com a internet.
// sw.js — estratégia do Service Worker self.addEventListener('fetch', (e) => { e.respondWith( caches.match(e.request).then((response) => { // retorna do cache ou busca na rede return response || fetch(e.request); }) ); });