Arklay — gestão de frotas

Gestão de frota com painel web e app do motorista para Android e iOS gerados da mesma base Next.js via Capacitor: demandas, veículos, estoque de peças, manutenção preventiva com alerta e checklist digital.

Next.js 15TypeScriptRadix UIshadcn/uiCapacitor 7PHPMySQLJWT

O contexto

Empresa de transporte com frota própria: motoristas, veículos, ordens de serviço, peças em estoque, manutenção. Antes do sistema, isso vivia em planilhas separadas e papel — uma planilha de motoristas, outra de veículos, checklist impresso preenchido a caneta e guardado numa gaveta.

O problema

Dois problemas distintos, que quase sempre aparecem juntos nesse tipo de operação.

O primeiro é visibilidade. Ninguém sabe, em um lugar só, quem está dirigindo o quê agora e qual veículo está perto da próxima revisão. Manutenção vira reativa: você descobre que o veículo precisava de atenção quando ele para na rua.

O segundo é registro. Checklist em papel depende de disciplina e não gera histórico consultável. Quando dá problema, não existe o que consultar para saber se o item foi verificado.

E tinha um problema meu, de execução: a operação precisava de duas superfícies — painel para o escritório, app para o motorista no celular. Duas superfícies normalmente viram duas bases de código evoluindo em paralelo até divergirem.

Decisões técnicas

Capacitor sobre uma base Next.js, em vez de React Native ou nativo. Essa é a decisão central do projeto e ela vem de olhar o que o app do motorista realmente faz: abrir checklist, tirar foto, receber notificação, consultar demanda. Câmera e push, nada além. React Native traria performance melhor em animação e listas longas — que esse app não tem — em troca de uma segunda base de componentes, um segundo conjunto de chamadas de API e um segundo lugar para o bug morar. Nativo puro traria isso multiplicado por dois. Com Capacitor, a lógica de negócio, os componentes e a integração com a API são os mesmos do painel web. O limite dessa escolha é claro: se um dia entrar rastreamento de GPS em background ou uso pesado offline, Capacitor deixa de ser a resposta óbvia e essa decisão precisa ser revista.

Radix UI + shadcn/ui em vez de biblioteca de UI fechada. Painel de frota é denso: tabelas, filtros, formulários longos, modais empilhados. Uma biblioteca fechada (Material, Ant) entrega tudo isso pronto e cobra depois, quando a identidade visual do cliente não cabe no tema e você passa a sobrescrever CSS de componente que não foi feito para ser sobrescrito. Radix dá o comportamento acessível — foco, teclado, ARIA em modal e select, que é a parte cara de acertar — sem opinião visual, e o shadcn/ui põe o design por cima como código no meu repositório, editável.

JWT em vez de sessão stateful. O mesmo backend PHP atende o painel web e o app. Sessão em servidor funcionaria bem para o painel e mal para o app, que fica com conectividade instável e precisa guardar credencial entre aberturas. Token permite que as duas superfícies usem o mesmo mecanismo, sem estado no servidor. O preço é o de sempre: revogação de token não é imediata como matar uma sessão, então expiração curta e renovação são obrigatórias.

Backend único servindo as duas superfícies. Motorista e administrador leem o mesmo estado. Sem isso, checklist enviado pelo app e ordem de serviço aberta no painel divergem, e alguém precisa reconciliar na mão.

Manutenção preventiva por regra no backend, não lembrete manual. O alerta é disparado por critério — quilometragem ou tempo desde a última manutenção — em vez de depender de alguém marcar no calendário.

O que ficou pronto

Sistema em operação com módulos de demandas, motoristas, veículos, empresas clientes, estoque de peças, ordens de serviço e manutenção preventiva com alertas. App do motorista publicado para Android e iOS a partir da mesma base do painel, com checklist digital e notificações.

O que eu faria diferente hoje

Colocaria uma fila de sincronização offline no app desde o começo. Motorista preenche checklist em garagem e em estrada, onde o sinal cai. Hoje o fluxo assume conectividade; um buffer local com envio posterior seria mais honesto com a realidade do uso.

Voltar para projetos