Files
portifolio-evandrodevbr/lib/site-content.ts
T

990 lines
56 KiB
TypeScript

import { offerLabels } from "./offer-labels";
import { portfolio } from "./portfolio-data";
import { isClientProject } from "./proof";
export const siteUrl = "https://evandro.dev.br";
export const siteName = "Evandro.dev.br";
/** Aparelho cuja captura abre a página do serviço: o site no computador (moldura de navegador) ou no celular (moldura de celular). */
export type HeroDevice = "desktop" | "mobile";
/** Esquema de fluxo que ocupa o topo do serviço sem case com captura gravada (app/servicos/_components/ServiceDiagram.tsx). */
export type ServiceDiagramKind = "desktop" | "iot" | "arquitetura";
/**
* Rótulos dos botões e links de ação, numa lista só: o contato diz sempre a mesma coisa, e o case também.
* O verde-limão fica só no contato; os demais são contorno ou link de texto.
*/
export const buttonLabels = {
contact: "Falar sobre meu projeto",
case: "Ver case",
site: "Abrir o site",
service: "Ver o serviço",
allCases: "Ver os cases",
allServices: "Ver todos os serviços",
} as const;
export interface ServicePageContent {
slug: string;
/** Nome curto do serviço: o mesmo na trilha, nos títulos, nos links e nos dados estruturados. Nas ofertas da home é o nome da oferta. */
navLabel: string;
/** Assunto da conversa de WhatsApp, em minúsculas e com artigo, para a frase "Quero conversar sobre {assunto}.". */
whatsappSubject: string;
eyebrow: string;
/** Título para busca, separado do h1: até 43 caracteres, e 60 com o sufixo " | Evandro.dev.br" (17) que o layout acrescenta. */
metaTitle: string;
/** Descrição para busca, com até 155 caracteres. */
metaDescription: string;
/** Título da página (h1). Nos serviços que são uma das ofertas da home, é o nome da oferta. */
headline: string;
intro: string;
answer: string;
audience: string[];
/** "O que podemos entregar". Nas páginas que explicam uma oferta da home a seção não aparece: vale o "O que você recebe" da oferta (`serviceOffers`), uma lista de entregáveis só. */
outcomes: string[];
process: string[];
examples: string[];
technicalDetails: string[];
stack: string[];
/** Ids dos cases relacionados; os de cliente aparecem primeiro na página. */
relatedCaseIds: string[];
/** Cases relacionados que saem de "Onde já apliquei isso" e vão para um bloco menor com este título, sem capa (ids de `relatedCaseIds`). */
alsoCases?: { title: string; caseIds: string[] };
/** Capa do topo: o case (um dos relacionados) e o aparelho da captura. Sem ela, o topo mostra o esquema `diagram`. */
heroCase?: { id: string; device: HeroDevice };
/** Esquema de fluxo do topo, para o serviço sem case com captura: nunca leva dado real nem logo de cliente. */
diagram?: ServiceDiagramKind;
/** Data (AAAA-MM-DD) da última mudança no conteúdo da página: vira o `lastmod` do mapa do site. Atualize ao mudar o texto. */
updatedAt: string;
/** Por que cada case relacionado interessa a este serviço, em uma frase (chave: id do case). */
caseRelevance: Record<string, string>;
/** Experiência profissional citada junto dos cases, só em texto, sem link nem detalhe interno. */
experienceNote?: string;
/** Oferta: preencha só com valores reais. O bloco "Investimento e prazo" só aparece quando algum campo existe. */
startingPrice?: string;
typicalTimeline?: string;
guarantee?: string;
faq?: { question: string; answer: string }[];
}
export interface CaseStudyContent {
id: string;
/** Nome do projeto ou do cliente. */
title: string;
/** Tipo do projeto, em poucas palavras. */
subtitle: string;
/** Título para busca, separado do h1: até 43 caracteres, e 60 com o sufixo " | Evandro.dev.br" (17) que o layout acrescenta. */
metaTitle: string;
/** Descrição para busca, com até 155 caracteres. */
metaDescription: string;
/** Título da página, em linguagem de negócio. */
headline: string;
/** Resumo de uma ou duas frases (cards e abertura da página). */
summary: string;
/** O que muda para quem usa, em uma frase. */
impact: string;
/** Quem é o cliente e em que situação o projeto nasceu. */
context: string;
/** O problema que o projeto resolve. */
problem: string;
/** Fatos verificáveis do projeto, como "No ar desde ...". Só aparece na página quando há algum; sem dado real, fica de fora. */
facts?: string[];
/** O que foi feito, escrito como benefício. */
deliveries: string[];
/** O que o cliente passou a poder fazer (2 ou 3 itens, sem número), só com o que as entregas já sustentam. Sem itens, a seção não aparece. */
capabilities?: string[];
/** Data (AAAA-MM-DD) da última mudança no conteúdo da página: vira o `lastmod` do mapa do site. Atualize ao mudar o texto. */
updatedAt: string;
/** Resultado com dado real e autorizado. Sem dado, o campo fica de fora e a seção não aparece. */
result?: string[];
/** Detalhes técnicos: tecnologias e decisões de projeto (ficam recolhidos, logo depois do que foi feito). */
stack: string[];
decisions: string[];
demoUrl?: string | null;
/** Papel do autor quando o projeto não é só dele. */
role?: string;
}
export const servicePages: ServicePageContent[] = [
{
slug: "criacao-de-sites",
navLabel: offerLabels.site.name,
whatsappSubject: offerLabels.site.whatsappSubject,
eyebrow: "Presença digital",
metaTitle: "Criação de sites em Joinville e SC",
metaDescription:
"Site profissional para apresentar sua empresa e levar o cliente ao WhatsApp. Atendimento em Garuva e Joinville (SC) e remoto em todo o Brasil.",
headline: offerLabels.site.name,
answer:
"Crio sites para apresentar sua empresa, mostrar o que você oferece e facilitar o contato. O projeto considera leitura no celular e no computador, conteúdo, páginas e funcionalidades combinadas antes do desenvolvimento.",
intro:
"Apresente seu negócio na internet com um site profissional: serviços, produtos, portfólio e caminhos claros para entrar em contato.",
audience: [
"Empresas e profissionais que ainda não têm site ou precisam substituir uma presença desatualizada.",
"Negócios que querem explicar seus serviços sem depender apenas das redes sociais.",
"Equipes que precisam organizar páginas, conteúdo e contato em um endereço próprio.",
],
outcomes: [
"Páginas com uma sequência clara: o que você faz, para quem e como entrar em contato.",
"Layout adaptado a celular e computador, com atenção à leitura e à navegação.",
"Publicação do site e orientação de uso. Domínio, hospedagem, produção de conteúdo e manutenção são combinados à parte, na proposta.",
],
examples: [
"Um site institucional para uma prestadora de serviços, com apresentação, áreas de atuação e contato.",
"Um catálogo para mostrar produtos e receber consultas, sem assumir uma loja com pagamento on-line.",
"Uma página de campanha para explicar uma oferta e orientar o próximo passo.",
],
process: [
"Conversamos sobre o negócio, o público e o que o visitante precisa conseguir fazer.",
"Combinamos páginas, conteúdo, referências visuais, responsabilidades e orçamento.",
"Você acompanha a construção e revisa conteúdo e navegação em etapas.",
"Publicamos após a revisão e definimos o que entra em suporte ou evolução posterior.",
],
technicalDetails: [
"Implementação com Next.js e TypeScript, escolhendo renderização e carregamento conforme o conteúdo e as integrações.",
"HTML semântico, navegação por teclado, imagens dimensionadas e avaliação de carregamento orientam acessibilidade e performance.",
"Metadados, URLs canônicas, sitemap e dados estruturados ajudam os buscadores a entender o site.",
],
stack: ["Next.js", "TypeScript", "Tailwind CSS", "SEO técnico", "Vercel"],
// a Lavação abre a página (capa), a SEV é o segundo trabalho e os dois sites institucionais ficam no bloco menor
relatedCaseIds: ["lavacao-047", "sev-modaintima", "sc-plus", "as-servicos"],
heroCase: { id: "lavacao-047", device: "desktop" },
alsoCases: {
title: "Também faço sites institucionais",
caseIds: ["sc-plus", "as-servicos"],
},
updatedAt: "2026-10-14",
caseRelevance: {
"lavacao-047":
"Um site local com preço por porte do veículo e pedido pelo WhatsApp, que o dono atualiza sozinho.",
"sev-modaintima":
"Um catálogo por tamanho com pedido pelo WhatsApp, e um painel para a loja cuidar de produtos e estoque.",
"sc-plus":
"Uma página institucional que reúne áreas, projetos, apoiadores e contato em um endereço próprio.",
"as-servicos":
"Um site institucional que conta duas frentes da empresa em uma só história, com cena 3D na rolagem.",
},
faq: [
{
question: "Quanto custa e o que preciso ter pronto?",
answer:
"O orçamento depende das páginas, conteúdo, funcionalidades e integrações. Podemos começar com uma conversa sobre seu negócio; nela definimos quem fornece textos, imagens e acessos, além dos custos de domínio e hospedagem.",
},
{
question: "O site também funciona no celular?",
answer:
"Sim. O site se adapta à tela e abre pelo navegador, no celular e no computador. Se você precisa de um aplicativo instalado no aparelho, conversamos sobre isso em um projeto à parte.",
},
{
question: "Posso contratar melhorias depois da publicação?",
answer:
"Sim. Ajustes de conteúdo, novas páginas, manutenção e novas funcionalidades podem ser combinados em continuidade. O que está incluído na entrega inicial e no suporte fica definido na proposta.",
},
],
},
{
slug: "engenharia-de-software",
navLabel: offerLabels.sistema.name,
whatsappSubject: offerLabels.sistema.whatsappSubject,
eyebrow: "Engenharia de software",
metaTitle: "Sistemas web e aplicativos sob medida",
metaDescription:
"Sistema web ou aplicativo sob medida para organizar pedidos, clientes e rotinas. Atendimento em Garuva e Joinville (SC) e remoto em todo o Brasil.",
headline: offerLabels.sistema.name,
answer:
"Quando a operação vive em planilhas, mensagens e retrabalho, desenvolvo um sistema web ou um aplicativo mobile feito para a sua equipe. Também conecto ferramentas e evoluo sistemas existentes. Definimos juntos os usuários, as funções e a primeira entrega útil.",
intro:
"Organize a operação com um sistema web ou aplicativo mobile sob medida. Conecte ferramentas, reduza tarefas repetidas ou melhore um sistema que já existe.",
audience: [
"Empresas que controlam processos em planilhas, mensagens e ferramentas que não conversam entre si.",
"Negócios que precisam de um sistema interno, área de clientes ou aplicativo para uso no celular.",
"Equipes com software em operação que precisam corrigir problemas e continuar evoluindo.",
],
outcomes: [
"Uma primeira versão com as funções prioritárias, em vez de tentar resolver toda a operação de uma vez.",
"Fluxos para consultar, registrar e compartilhar informações, com acessos definidos por perfil.",
"Web ou mobile, conforme o seu caso: dispositivos, sistemas operacionais, uso sem internet e distribuição são combinados na proposta.",
],
examples: [
"Um sistema web para acompanhar pedidos e atendimentos em uma única tela.",
"Um aplicativo mobile para uma equipe consultar tarefas e registrar visitas pelo celular.",
"Uma integração para transferir dados entre o sistema de vendas e outra ferramenta, sem digitação duplicada.",
],
process: [
"Entendemos a rotina atual, quem usa o sistema e onde estão as dificuldades.",
"Escolhemos o primeiro fluxo a entregar e combinamos plataformas, integrações e critérios de aceitação.",
"Construímos em etapas curtas, com demonstrações e revisão de quem vai usar.",
"Validamos no ambiente combinado e entregamos orientações para operação, manutenção e próximos passos.",
],
technicalDetails: [
"A arquitetura parte das regras do negócio, dos limites entre módulos e dos contratos de API. Migrações e integrações consideram os dados e o sistema já em uso.",
"Autorização por perfil, validação no servidor, tratamento de falhas e testes dos fluxos críticos entram conforme os riscos do projeto.",
"Em aplicativos mobile, a tecnologia é escolhida depois de avaliar os dispositivos e os recursos necessários, como câmera, notificações e uso sem internet.",
],
stack: ["Next.js", "TypeScript", "Node.js", "PostgreSQL", "APIs REST"],
relatedCaseIds: ["sev-modaintima", "lavacao-047"],
heroCase: { id: "sev-modaintima", device: "mobile" },
updatedAt: "2026-10-14",
caseRelevance: {
"sev-modaintima":
"Um sistema com painel para cadastrar produtos, controlar o estoque por tamanho e acompanhar pedidos.",
"lavacao-047":
"Um painel em que o dono altera preços, textos e fotos, e a mudança aparece no site sem nova publicação.",
},
experienceNote:
"Desde 2022 trabalho com isso na Apolo Energia: aplicações web e mobile para rotinas internas, APIs e painéis de operação. Por serem sistemas de uso interno, não há link nem detalhes públicos.",
faq: [
{
question: "Preciso saber qual tecnologia usar?",
answer:
"Não. Começamos pelo que as pessoas precisam fazer. Um sistema web pode resolver o uso pelo navegador; um aplicativo mobile pode fazer sentido quando a rotina exige recursos do celular. A escolha vem depois de entender o contexto.",
},
{
question: "Você também trabalha com sistemas que já existem?",
answer:
"Sim. Posso diagnosticar problemas, integrar ferramentas, corrigir fluxos e implementar novas funções. Primeiro avaliamos a base atual e os riscos para definir uma mudança que não dependa de reescrever tudo.",
},
{
question: "O aplicativo inclui publicação em lojas?",
answer:
"A forma de distribuição é definida no projeto. Plataformas, contas de desenvolvedor, requisitos das lojas e a publicação são combinados antes da contratação.",
},
],
},
{
slug: "consultoria-nextjs",
navLabel: "Consultoria em Next.js",
whatsappSubject: "uma consultoria em Next.js",
eyebrow: "Consultoria Next.js",
metaTitle: "Consultoria Next.js para site ou sistema",
metaDescription:
"Descubra por que seu site ou sistema Next.js está lento ou com falhas e receba um plano de correção. Garuva e Joinville (SC), remoto em todo o Brasil.",
headline: "Seu projeto Next.js pode funcionar melhor.",
answer:
"Analiso sites e sistemas feitos em Next.js para entender lentidão, falhas ou dificuldades de manutenção. Você recebe prioridades explicadas, um plano de correção e, quando contratado, a implementação das melhorias.",
intro:
"Seu site ou sistema Next.js está lento, apresenta falhas ou ficou difícil de manter? Identifique a causa e organize as melhorias antes de investir em mais mudanças.",
audience: [
"Empresas com um site ou sistema em Next.js que não está atendendo bem seus usuários.",
"Equipes que precisam de apoio para investigar falhas, carregamento ou indexação.",
"Responsáveis por um produto que precisam entender o que corrigir primeiro e por quê.",
],
outcomes: [
"Diagnóstico com problemas observados, impacto para o usuário e prioridades.",
"Plano de correção que distingue ajustes pontuais de mudanças maiores.",
"Implementação das correções ou acompanhamento do seu time, conforme a contratação. As metas de desempenho partem de medições do seu site.",
],
examples: [
"Investigar por que uma página demora a abrir no celular.",
"Corrigir navegação e informações de páginas que não são interpretadas corretamente pelos buscadores.",
"Ajudar uma equipe a incluir novas funções sem tornar o sistema mais difícil de manter.",
],
process: [
"Você apresenta os sintomas, o objetivo e os acessos necessários para a análise.",
"Investigo o projeto e explico as causas encontradas e suas consequências.",
"Combinamos prioridades e o formato: diagnóstico, correções ou apoio ao time.",
"Reavaliamos os fluxos alterados e registramos as orientações de continuidade.",
],
technicalDetails: [
"Revisão de App Router, fronteiras entre Server e Client Components, estratégias de renderização, cache e busca de dados.",
"Investigação de Core Web Vitals, tamanho do JavaScript, imagens e requisições; correções são comparadas com medições do cenário afetado.",
"Auditoria de metadados, canônicas, sitemap, dados estruturados e links internos, preservando URLs e requisitos de indexação nas mudanças.",
],
stack: ["Next.js", "React", "TypeScript", "Tailwind", "SEO técnico"],
relatedCaseIds: ["sc-plus", "lavacao-047"],
heroCase: { id: "sc-plus", device: "desktop" },
updatedAt: "2026-10-14",
caseRelevance: {
"sc-plus":
"Uma página em Next.js 15 com título, descrição, endereço canônico e dados estruturados para os buscadores.",
"lavacao-047":
"Um site que construí em Next.js 16, em que o conteúdo do painel alimenta a página, o sitemap e os dados para os buscadores.",
},
faq: [
{
question: "Não sei se meu site usa Next.js. Posso conversar?",
answer:
"Sim. Traga o endereço do site e o problema percebido. Identificamos o contexto e se essa consultoria é adequada antes de combinar uma análise mais profunda.",
},
{
question: "A consultoria inclui corrigir o código?",
answer:
"Pode incluir. Um diagnóstico pontual, a implementação das correções e o acompanhamento de um time são formatos diferentes. A proposta informa quais deles entram e como a entrega será avaliada.",
},
{
question: "Precisa substituir o site inteiro?",
answer:
"Não necessariamente. A análise busca a causa do problema e o menor conjunto de mudanças que atende ao objetivo. Uma migração só é recomendada quando os benefícios e os riscos justificam o trabalho.",
},
],
},
{
slug: "tauri-rust",
navLabel: "Aplicativos desktop",
whatsappSubject: "um aplicativo desktop",
eyebrow: "Aplicativos desktop",
metaTitle: "Aplicativos desktop para Windows e Linux",
metaDescription:
"Aplicativo desktop para Windows e Linux que automatiza tarefas no computador da empresa. Garuva e Joinville (SC), atendimento remoto em todo o Brasil.",
headline: "Aplicativos para Windows e Linux.",
answer:
"Desenvolvo aplicativos desktop para trabalhar no computador, lidar com arquivos e integrar recursos locais. Windows e Linux são as plataformas atendidas; as versões e distribuições compatíveis são combinadas em cada projeto.",
intro:
"Crie uma ferramenta para Windows ou Linux: organize arquivos, execute rotinas locais ou conecte o computador aos sistemas da empresa.",
audience: [
"Empresas que precisam de uma ferramenta instalada, em vez de depender apenas do navegador.",
"Equipes que trabalham com arquivos, processamento local ou recursos do computador.",
"Produtos que precisam avaliar uma aplicação desktop nova ou a evolução de uma ferramenta existente.",
],
outcomes: [
"Uma interface para executar as tarefas locais prioritárias e entender o resultado de cada operação.",
"Compatibilidade combinada para Windows e/ou Linux, incluindo versões, distribuições e dependências necessárias.",
"Instalação, atualizações, permissões e uso sem internet combinados no projeto. Cada plataforma é testada separadamente.",
],
examples: [
"Um aplicativo para conferir e organizar arquivos antes de enviá-los a outro sistema.",
"Uma ferramenta interna que executa uma rotina no computador e mostra seu andamento.",
"Uma interface local para acessar dados ou recursos que não estão disponíveis em um site comum.",
],
process: [
"Entendemos a tarefa e confirmamos se um aplicativo instalado faz mais sentido que um sistema web.",
"Definimos Windows e/ou Linux, ambientes de uso, acesso a arquivos e integrações necessárias.",
"Construímos e demonstramos os fluxos principais nos ambientes combinados.",
"Validamos instalação e operação e entregamos as instruções e a estratégia de atualização acordadas.",
],
technicalDetails: [
"Tauri conecta uma interface web a comandos nativos em Rust. Permissões e acesso a arquivos devem ser limitados ao necessário, com validação na fronteira entre interface e sistema.",
"Empacotamento e dependências variam por sistema, então cada integração nativa é testada no Windows e no Linux.",
],
stack: [
"Tauri",
"Rust",
"TypeScript",
"Aplicativos desktop",
"Integração com o sistema",
],
relatedCaseIds: ["gcc-installer"],
diagram: "desktop",
updatedAt: "2026-10-14",
caseRelevance: {
"gcc-installer":
"Um projeto próprio de aplicativo para Windows: lista as versões do compilador, instala e ajusta o PATH em uma única janela.",
},
faq: [
{
question: "O mesmo aplicativo pode funcionar em Windows e Linux?",
answer:
"Sim, desde que os dois entrem no projeto. Versões do Windows, distribuições Linux, recursos locais e dependências são definidos e testados separadamente.",
},
{
question: "O aplicativo funciona sem internet?",
answer:
"As funções locais podem funcionar sem internet. Login remoto, sincronização e serviços externos continuam precisando de conexão. Vemos cada caso na conversa inicial.",
},
{
question: "Como o aplicativo é instalado e atualizado?",
answer:
"A forma de instalação e de atualização é combinada no projeto, conforme o ambiente de uso: Windows, Linux ou os dois.",
},
],
},
{
slug: "integracao-hardware-software-iot",
navLabel: "Integração de equipamentos",
whatsappSubject: "uma integração de equipamentos",
eyebrow: "Hardware, software e IoT",
metaTitle: "Integração de equipamentos e sistemas (IoT)",
metaDescription:
"Leve os dados dos seus equipamentos para um painel e acompanhe a operação sem anotações manuais. Garuva e Joinville (SC), remoto em todo o Brasil.",
headline: "Dados dos equipamentos no seu sistema.",
answer:
"Conecto equipamentos e software para transformar leituras e eventos em informação útil para a operação. Primeiro vemos o que cada dispositivo permite acessar; a integração segue essas interfaces e os requisitos de segurança e funcionamento.",
intro:
"Leve informações de equipamentos para um sistema ou painel. Acompanhe leituras e eventos sem depender apenas de registros manuais.",
audience: [
"Operações que registram manualmente informações disponíveis em sensores ou equipamentos.",
"Empresas que precisam reunir dados físicos e informações de seus sistemas.",
"Equipes que querem avaliar a viabilidade de um produto conectado antes de ampliar o projeto.",
],
outcomes: [
"Um caminho definido entre a informação do equipamento e a tela de quem precisa usá-la.",
"Tratamento combinado para falta de conexão, leituras inválidas e outras falhas relevantes.",
"O trabalho parte dos protocolos, da documentação e do acesso ao equipamento. Compra de hardware, instalação física e certificações são tratadas à parte.",
],
examples: [
"Um painel para consultar leituras de sensores compatíveis.",
"Um registro de eventos de uma máquina para apoiar o acompanhamento da operação.",
"Uma prova de conceito para verificar se um equipamento consegue trocar dados com o sistema existente.",
],
process: [
"Mapeamos equipamentos, dados disponíveis e a decisão que essas informações precisam apoiar.",
"Verificamos documentação, formas de conexão e limites do ambiente.",
"Implementamos um fluxo delimitado e avaliamos as falhas relevantes com os acessos combinados.",
"Entregamos instruções de operação, limites conhecidos e próximos passos.",
],
technicalDetails: [
"A descoberta identifica APIs, arquivos, portas seriais ou protocolos expostos pelo equipamento; a escolha depende da interface realmente disponível.",
"Contratos de dados, validação, persistência, reconexão e rastreamento de falhas organizam o fluxo entre dispositivo, backend e painel. WebSockets entram apenas quando há necessidade de atualização contínua.",
"O Twins Lab, protótipo de laboratório, simula um reator e envia o estado dele a um painel a cada dois segundos, por eventos do servidor.",
],
stack: ["IoT", "WebSockets", "APIs", "Painéis", "Integração de sistemas"],
relatedCaseIds: ["twins-lab"],
diagram: "iot",
updatedAt: "2026-10-14",
caseRelevance: {
"twins-lab":
"Um reator simulado envia seu estado a um painel a cada dois segundos, com o histórico guardado.",
},
experienceNote:
"Desde 2022 trabalho com isso na Apolo Energia: sistemas internos, aplicativos, APIs e integração de dispositivos IoT para a troca de dados entre serviços e parceiros. Por serem sistemas de uso interno, não há link nem detalhes públicos.",
faq: [
{
question: "Qualquer equipamento pode ser conectado?",
answer:
"Depende do equipamento. Precisamos saber quais dados e interfaces ele disponibiliza, se há documentação e quais restrições existem no ambiente. Fazemos essa avaliação antes de fechar o projeto.",
},
{
question: "É necessário trocar os sistemas existentes?",
answer:
"Nem sempre. Podemos avaliar uma camada de integração que aproveita o que já funciona. O caminho depende das interfaces disponíveis, da confiabilidade exigida e dos riscos para a operação.",
},
{
question: "É possível começar pequeno?",
answer:
"Sim. Um equipamento, uma leitura ou um fluxo já permite validar a ideia antes de ampliar o projeto. Os critérios dessa primeira etapa são combinados antes de começar.",
},
],
},
{
slug: "arquitetura-de-software",
navLabel: "Diagnóstico de arquitetura",
whatsappSubject: "um diagnóstico de arquitetura",
eyebrow: "Diagnóstico e decisão",
metaTitle: "Diagnóstico e arquitetura de software",
metaDescription:
"Entenda por que seu sistema ficou difícil de mudar e decida o que corrigir, manter ou trocar. Garuva e Joinville (SC), remoto em todo o Brasil.",
headline: "Entenda o problema antes de mudar tudo.",
answer:
"Analiso como um sistema está organizado e por que ficou difícil de manter ou evoluir. Você recebe um diagnóstico explicado, prioridades e um plano de mudança para decidir o que corrigir, preservar ou substituir.",
intro:
"Quando cada mudança no sistema vira um problema, obtenha um diagnóstico e um plano para evoluir sem decidir no escuro ou reescrever tudo por impulso.",
audience: [
"Empresas que dependem de um sistema e não conseguem entender o custo ou o risco das mudanças.",
"Equipes que enfrentam falhas recorrentes, integrações frágeis ou dificuldade para entregar novas funções.",
"Responsáveis por um produto que precisam comparar caminhos antes de investir numa migração.",
],
outcomes: [
"Um mapa dos problemas encontrados e de como afetam o produto e a operação.",
"Alternativas com benefícios, limitações e riscos explicados para apoiar a decisão.",
"Plano de execução por prioridades; implementar as mudanças ou acompanhar o time depende do formato contratado.",
],
examples: [
"Investigar por que alterar uma função provoca falhas em outras partes do sistema.",
"Comparar manter, modernizar aos poucos ou substituir uma ferramenta antiga.",
"Organizar um plano para conectar novos sistemas sem aumentar a confusão da operação.",
],
process: [
"Conversamos com quem usa e mantém o sistema e reunimos os acessos e materiais necessários.",
"Analiso a base e os fluxos relevantes para o problema, sem ampliar a investigação sem motivo.",
"Apresento o diagnóstico e comparo as alternativas com o time e os responsáveis pelo negócio.",
"Entrego o plano priorizado e, se combinado, acompanho sua execução.",
],
technicalDetails: [
"Análise de dependências, fronteiras entre módulos, contratos de API, fluxos de dados e pontos de falha para localizar acoplamento e riscos.",
"A arquitetura proposta considera carga, consistência de dados, operação, segurança e capacidade real do time, evitando distribuir um sistema sem necessidade.",
"Migrações são divididas em etapas verificáveis, com estratégia de transição e reversão quando aplicável. As decisões ficam registradas com seus prós e contras, não apenas em um diagrama final.",
],
stack: [
"Arquitetura de software",
"APIs",
"Desempenho",
"Integrações",
"Sistemas críticos",
],
relatedCaseIds: [],
diagram: "arquitetura",
updatedAt: "2026-10-14",
caseRelevance: {},
experienceNote:
"Desde 2022 desenvolvo sistemas internos, aplicativos e APIs na Apolo Energia e participo do planejamento e da arquitetura de novas soluções. Por serem sistemas de uso interno, não há link nem detalhes públicos.",
faq: [
{
question: "Preciso ter uma equipe técnica para contratar?",
answer:
"Não, mas a análise precisa de acesso ao sistema e às pessoas ou materiais que expliquem seu funcionamento. O resultado é apresentado com consequências para o negócio e detalhes que uma equipe técnica possa usar.",
},
{
question: "O diagnóstico sempre recomenda reescrever o sistema?",
answer:
"Não. Preservar o que funciona e mudar pontos específicos pode ser o caminho mais adequado. As alternativas são comparadas com base nos problemas observados, nos riscos e na capacidade de executar a mudança.",
},
{
question: "O que é entregue ao final?",
answer:
"Um diagnóstico documentado com problemas, prioridades, alternativas e plano de mudança para o escopo analisado. Profundidade, reuniões e eventual acompanhamento da implementação são definidos na proposta.",
},
],
},
];
export const caseStudies: CaseStudyContent[] = [
{
id: "sev-modaintima",
title: "SEV Moda Íntima",
subtitle: "Catálogo digital e loja virtual",
metaTitle: "SEV Moda Íntima: loja virtual com WhatsApp",
metaDescription:
"Loja virtual de moda íntima: a cliente escolhe o tamanho e envia o pedido pelo WhatsApp, e a loja controla produtos e estoque em um painel.",
headline: "Loja virtual de moda íntima com pedido pelo WhatsApp",
summary:
"Catálogo digital e loja virtual de moda íntima. A cliente encontra o produto, escolhe o tamanho e envia o pedido pelo WhatsApp. A loja cuida de tudo em um painel próprio.",
impact:
"A cliente encontra o produto e envia o pedido pelo WhatsApp; a loja controla produtos, estoque e pedidos em um painel.",
context:
"A SEV Moda Íntima vende moda íntima pela internet. O site funciona como vitrine e loja virtual: apresenta os produtos, recebe os pedidos pelo WhatsApp e dá à loja um painel para cuidar do catálogo.",
problem:
"A loja vende moda íntima em várias peças e tamanhos. A cliente precisa achar o que procura entre as opções e escolher a medida certa, e o pedido segue pelo WhatsApp, com o frete calculado pela distância. A loja, por sua vez, precisa saber o que ainda tem de cada tamanho.",
deliveries: [
"Catálogo por tamanho, com filtros e busca: a cliente encontra a peça, escolhe a medida e vê primeiro os itens mais relevantes.",
"Pedido pelo WhatsApp: a cliente escolhe os produtos no site e envia o pedido para a loja.",
"Painel para a loja cadastrar as peças, acompanhar os pedidos e controlar o estoque.",
"Estoque controlado por tamanho, para cada medida ter a sua quantidade.",
"Frete calculado pela distância até o endereço da cliente.",
"Uma vitrine com animações que dão destaque aos produtos e deixam a navegação agradável.",
],
capabilities: [
"A cliente encontra a peça, escolhe o tamanho e envia o pedido pelo WhatsApp.",
"A loja cadastra as peças e acompanha os pedidos em um painel próprio.",
"A loja controla o estoque de cada tamanho e sabe o que ainda tem para vender.",
],
updatedAt: "2026-10-14",
stack: [
"Next.js 16",
"TypeScript",
"PostgreSQL",
"Prisma",
"Tailwind CSS 4",
"Framer Motion",
],
decisions: [
"A busca usa ranking de relevância e vários filtros combinados.",
"O cálculo de frete usa geocodificação híbrida para chegar à distância entre loja e cliente.",
"A vitrine tem modo escuro e animações com Framer Motion.",
"A área administrativa cobre produtos, estoque e pedidos.",
],
demoUrl: "https://sevmodaintima.com.br",
},
{
id: "lavacao-047",
title: "Lavação 047",
subtitle: "Site e painel para lavação automotiva",
metaTitle: "Lavação 047: site com preços e WhatsApp",
metaDescription:
"Site da Lavação 047, em Garuva-SC: preço pelo porte do veículo, pedido pelo WhatsApp e painel para o dono editar tudo sozinho.",
headline:
"Site com tabela de preços e pedido pelo WhatsApp para uma lavação em Garuva",
summary:
"Site da Lavação 047, em Garuva-SC. O cliente vê o preço pelo porte do veículo e pede o serviço pelo WhatsApp com a mensagem já pronta. O dono edita preços, textos e fotos sozinho.",
impact:
"O cliente descobre o preço e pede pelo WhatsApp; o dono atualiza o site sem depender de um desenvolvedor.",
context:
"A Lavação 047 é uma lavação automotiva em Garuva, Santa Catarina. O site apresenta os serviços, a tabela de preços e a localização, e leva o cliente ao WhatsApp.",
problem:
"O cliente chega com perguntas simples: quanto custa para o meu carro, onde fica e como pedir. O preço muda com o porte do veículo, e o contato é pelo WhatsApp. O dono, por sua vez, precisa mudar preços, textos e fotos quando quiser, sem esperar por um desenvolvedor.",
deliveries: [
"Tabela de preços por porte do veículo: o cliente vê quanto paga pelo seu carro.",
"Pedido pelo WhatsApp com mensagem pronta: um toque abre a conversa já com o serviço escolhido.",
"Painel do dono: ele altera preços, textos, fotos e o mapa sozinho, e a mudança aparece no site sem nova publicação.",
"Galeria de trabalhos por serviço, para o cliente ver o resultado antes de chamar.",
"Mapa de localização, para o cliente achar a lavação.",
"Informações organizadas para o Google e para assistentes de IA entenderem o que a lavação faz e onde fica.",
"Uma animação de rolagem que leva o carro do sujo ao brilho e perguntas frequentes montadas com os dados reais do negócio.",
],
capabilities: [
"O dono muda preços, textos, fotos e o mapa sem pedir a ninguém, e a mudança aparece no site sem nova publicação.",
"O cliente vê o preço pelo porte do veículo e pede o serviço pelo WhatsApp com a mensagem já pronta.",
"O cliente confere a galeria de trabalhos de cada serviço antes de chamar.",
],
updatedAt: "2026-10-14",
stack: [
"Next.js 16",
"React 19",
"TypeScript",
"Tailwind CSS 4",
"Motion",
"Upstash Redis",
"Vercel Blob",
],
decisions: [
"O conteúdo salvo no painel alimenta a página, os dados estruturados, o sitemap e o cartão de compartilhamento.",
"Conteúdo e imagens ficam guardados em Redis e em armazenamento privado, com arquivo local como alternativa.",
"A animação respeita a preferência do sistema por menos movimento.",
"O mapa de localização usa OpenStreetMap.",
],
demoUrl: "https://landing-page-lavacao047.vercel.app",
},
{
id: "nutriscan",
title: "NutriScan",
subtitle: "Consulta de produtos por nome e código de barras",
metaTitle: "NutriScan: consulta de alimentos",
metaDescription:
"Consulta de alimentos por nome ou código de barras, com cache próprio e a base pública Open Food Facts. Projeto próprio, no ar para teste.",
headline: "Consulta de alimentos por nome ou código de barras",
summary:
"Aplicação web para consultar produtos alimentícios por nome ou código de barras, combinando um cache próprio com a base pública Open Food Facts.",
impact:
"A consulta encontra o produto por nome ou código e só vai à base externa quando precisa.",
context:
"Projeto próprio, criado para estudar a integração com uma base pública de alimentos. Está no ar para quem quiser testar.",
problem:
"As informações dos produtos vêm de uma base pública externa. O desafio era não depender só dela a cada consulta e deixar claros dois caminhos: buscar pelo nome e consultar pelo código de barras.",
deliveries: [
"Busca por nome ou por código de barras.",
"As consultas passam primeiro pelo cache próprio e só vão à base externa quando faltam resultados, o que reduz a dependência dela.",
"O código de barras é validado (de 8 a 13 dígitos) antes da consulta, para evitar buscas inválidas.",
"Se a base externa demora mais de oito segundos, a consulta é cancelada e a pessoa não fica esperando.",
],
stack: ["Next.js", "TypeScript", "Cache JSON", "Open Food Facts"],
decisions: [
"A busca consulta o cache primeiro, tem um modo somente-cache e recorre ao Open Food Facts quando faltam resultados.",
"A consulta por código remove caracteres não numéricos, aceita de 8 a 13 dígitos, consulta o cache e usa a base externa se não achar.",
"A camada de acesso à base externa cancela requisições após oito segundos e separa a busca por nome da busca por código.",
],
demoUrl: "https://nutriscan.evandro.dev.br",
updatedAt: "2026-10-14",
},
{
id: "twins-lab",
title: "Twins Lab",
subtitle: "Painel ao vivo de um reator simulado",
metaTitle: "Twins Lab: painel de reator simulado",
metaDescription:
"Protótipo de painel ao vivo que mostra a simulação de um reator industrial, com acesso por login e histórico guardado. Projeto próprio.",
headline:
"Painel ao vivo para acompanhar a simulação de um reator industrial",
summary:
"Protótipo de gêmeo digital industrial: um simulador de reator envia seu estado a um painel com acesso por login, atualizado a cada dois segundos.",
impact:
"O estado do reator simulado chega ao painel sozinho, só para quem tem acesso, e o histórico fica guardado.",
context:
"Projeto próprio, um protótipo de laboratório para explorar como os dados de um processo físico chegam a uma tela. O reator é simulado.",
problem:
"Como levar o estado de um processo físico para uma tela, mostrar só a quem tem acesso e manter o histórico do que aconteceu?",
deliveries: [
"Acesso por login: só quem está autenticado abre o painel.",
"O estado do reator chega à tela sozinho, a cada dois segundos, sem recarregar a página.",
"Dados e estado do simulador ficam guardados no banco, o que mantém o histórico.",
"Quando a execução ou o cenário muda, todos os painéis abertos são avisados.",
],
stack: ["Next.js", "TypeScript", "NextAuth", "MongoDB", "SSE"],
decisions: [
"A rota exige sessão do NextAuth antes de abrir a transmissão de eventos.",
"A resposta usa text/event-stream (SSE), envia estados, dados e erros em intervalos de dois segundos e limita a conexão a dez minutos.",
"O simulador salva dados e estado no MongoDB e notifica os clientes quando a execução ou o cenário mudam.",
],
updatedAt: "2026-10-14",
},
{
id: "reddit-explorer",
title: "Reddit Posts Explorer",
subtitle: "Posts de um fórum de IA, filtrados por período",
metaTitle: "Reddit Posts Explorer: coleta e filtros",
metaDescription:
"Coleta os posts em alta do r/artificial sem duplicar e permite filtrar por período e ordenar por votos ou comentários. Projeto próprio.",
headline:
"Posts de um fórum de inteligência artificial, coletados e filtrados por período",
summary:
"Aplicação que coleta os posts em alta do r/artificial, guarda tudo no MongoDB sem duplicar e permite filtrar por período e ordenar por votos ou comentários.",
impact:
"Rodar a coleta de novo atualiza os posts que já existem, sem duplicar, e o histórico pode ser consultado por datas.",
context:
"Projeto próprio, feito para estudar a coleta de dados de uma API pública e a consulta por período.",
problem:
"Os posts em alta mudam o tempo todo. O desafio era coletar de novo sem duplicar o que já estava guardado e consultar o histórico por datas e por popularidade.",
deliveries: [
"Coleta dos posts em alta do r/artificial pela API pública do Reddit.",
"Cada post é guardado uma vez só: coletar de novo atualiza o que já existe em vez de duplicar.",
"Filtro por período e ordenação por votos ou comentários.",
"A consulta confere as datas e a ordenação e avisa quando os parâmetros estão errados.",
],
stack: ["Astro", "MongoDB", "Mongoose", "TypeScript", "API do Reddit"],
decisions: [
"O serviço consulta r/artificial/hot.json com identificação própria e limite de 15 segundos, e grava os posts em lote com atualização pelo id.",
"O endpoint de filtro valida as datas e o campo de ordenação (votos ou comentários) e responde com erro 400 quando faltam parâmetros ou eles são inválidos.",
"O Astro roda com saída de servidor e o adaptador Node em modo standalone.",
],
updatedAt: "2026-10-14",
},
{
id: "sc-plus",
title: "SC Plus Aquicultura",
subtitle: "Site institucional com áreas, projetos e contato",
metaTitle: "SC Plus Aquicultura: página institucional",
metaDescription:
"Página institucional da SC Plus Aquicultura, com áreas de atuação, projetos, apoiadores e contato, preparada para os buscadores.",
headline:
"Página institucional para a SC Plus Aquicultura ser encontrada na internet",
summary:
"Página institucional da SC Plus Aquicultura, com apresentação da instituição, áreas e projetos, apoiadores e contato, preparada para os buscadores e para o compartilhamento.",
impact:
"A instituição ganhou uma página própria, preparada para ser encontrada nos buscadores.",
context:
"A SC Plus Aquicultura é uma instituição de Garuva, em Santa Catarina, que atua com educação, ciência e tecnologia sustentável. Ela precisava de uma página própria para se apresentar, mostrar suas áreas de atuação e seus projetos e receber contato.",
problem:
"A instituição tem várias áreas de atuação e projetos. Quem chega pela primeira vez precisa entender o que ela faz e saber como entrar em contato. Sem um endereço próprio, isso não fica reunido em um só lugar.",
deliveries: [
"Uma página própria que apresenta a instituição, as áreas de atuação e os projetos.",
"Contato na própria página.",
"Uma seção de apoiadores e de participação, para quem quer apoiar ou participar.",
"Título, descrição e imagem de compartilhamento próprios, para o link aparecer bem nos buscadores e nas redes.",
"Dados estruturados que ajudam o Google a entender de quem é a página.",
],
capabilities: [
"Quem chega pela primeira vez vê a instituição, as áreas de atuação e os projetos, e tem o contato na própria página.",
"Quem quer apoiar ou participar encontra o caminho na própria página.",
"O link aparece com título, descrição e imagem próprios nos buscadores e nas redes.",
],
updatedAt: "2026-10-14",
stack: ["Next.js 15", "React 19", "Tailwind CSS 4", "TypeScript"],
decisions: [
"A página publica título, descrição, endereço canônico e imagem de compartilhamento.",
"Os dados estruturados descrevem a instituição para os buscadores.",
],
demoUrl: "https://scplus.evandro.dev.br",
},
{
id: "gcc-installer",
title: "MinGW GCC Installer",
subtitle: "Instalador do compilador GCC para Windows",
metaTitle: "MinGW GCC Installer: instalador no Windows",
metaDescription:
"Aplicativo para Windows que lista as versões do MinGW-w64, instala o compilador GCC e ajusta o PATH, tudo em uma janela. Projeto próprio.",
headline: "Instalador do compilador GCC para Windows em uma única janela",
summary:
"Aplicativo para Windows que lista as versões do MinGW-w64, baixa a escolhida, instala em C:\\mingw64 e deixa o GCC pronto para uso, tudo em uma janela.",
impact:
"Escolher a versão, baixar, extrair e ajustar o PATH deixam de ser passos manuais: tudo acontece em uma janela.",
context:
"Projeto próprio, criado para resolver uma tarefa repetitiva de quem programa no Windows: instalar o compilador GCC.",
problem:
"Instalar o GCC no Windows exige vários passos manuais: escolher a versão, baixar, extrair os arquivos e configurar o PATH do sistema.",
deliveries: [
"Lista as versões publicadas do MinGW-w64 e destaca as mais usadas (ucrt e posix).",
"Baixa o pacote escolhido e instala na pasta C:\\mingw64.",
"Configura o PATH do usuário e avisa o Windows da mudança, para o GCC funcionar sem ajustes manuais.",
"Deixa o comando make disponível, renomeando o mingw32-make.exe.",
],
stack: ["Python", "Tkinter", "Win32 API", "GitHub API", "7-Zip"],
decisions: [
"A lista de versões vem da API de releases do repositório niXman/mingw-builds-binaries, e as versões com ucrt e posix aparecem em destaque na tabela.",
"A instalação extrai o pacote com o 7-Zip (no caminho padrão) em uma pasta temporária e move o resultado para C:\\mingw64.",
"Adicionar ao PATH grava em HKCU\\Environment e avisa o Windows com WM_SETTINGCHANGE.",
"Os 23 testes automatizados cobrem a lógica do núcleo, que não depende da plataforma.",
],
updatedAt: "2026-10-14",
},
{
id: "as-servicos",
title: "AS Serviços",
subtitle: "Site institucional com cena 3D",
metaTitle: "AS Serviços: site com cena 3D",
metaDescription:
"Site institucional da AS Serviços com uma cena 3D que acompanha a rolagem e conta a engenharia física e o software numa só história.",
headline: "Site institucional com uma cena 3D que acompanha a rolagem",
summary:
"Site institucional da AS Serviços com uma cena 3D criada em código: uma casa e uma placa-mãe desenhadas em linhas que reagem à rolagem da página.",
impact:
"Engenharia física e software contados na mesma história visual, sem depender de um modelo 3D pronto.",
context:
"A AS Serviços reúne engenharia física e software. O site precisava mostrar as duas frentes na mesma história.",
problem:
"A empresa reúne duas frentes bem diferentes: a engenharia física, de um lado, e o software, do outro. Em um site comum, as duas podem virar uma lista de serviços sem relação entre si. O desafio era mostrar as duas na mesma história, de um jeito que prenda a atenção de quem rola a página e que continue leve em celulares e conexões mais simples.",
deliveries: [
"As duas frentes da empresa, a física e a digital, aparecem na mesma história visual.",
"Uma cena 3D que acompanha a rolagem: casa, instalação elétrica e placa-mãe aparecem desenhadas em linhas.",
"A qualidade da cena se ajusta ao aparelho: celulares, conexões mais simples e quem prefere menos movimento recebem uma versão mais leve.",
"Um painel para controle de projetos, desenvolvido junto com a primeira página do site.",
],
capabilities: [
"A empresa conta a engenharia física e o software na mesma história, em vez de duas listas de serviços sem relação.",
"Quem visita no celular ou com conexão mais simples recebe uma versão mais leve da cena.",
"A empresa passou a ter um painel para controle de projetos.",
],
updatedAt: "2026-10-14",
stack: ["Next.js 16", "Three.js", "TypeScript"],
decisions: [
"A cena é gerada em código, sem arquivo 3D pronto: o motor monta casa, instalação elétrica e placa-mãe com geometrias e linhas do Three.js.",
"O canvas converte a rolagem em um progresso de 0 a 1 e o entrega ao motor da cena.",
"A qualidade tem quatro níveis (estático, baixo, médio e alto), escolhidos conforme o WebGL, a preferência por menos movimento, a economia de dados, a conexão e a capacidade do dispositivo.",
],
demoUrl: null,
role: "Desenvolvimento da primeira landing page do site, com animações 3D, e de um painel para controle de projetos.",
},
];
const clientProjectIds = new Set(
portfolio.projects.filter(isClientProject).map(({ id }) => id),
);
/** Projetos feitos para clientes ficam à frente; os pessoais e de estudo vão para o Laboratório. */
export function isClientCase(caseStudy: { id: string }) {
return clientProjectIds.has(caseStudy.id);
}
export const clientCases = caseStudies.filter(isClientCase);
export const labCases = caseStudies.filter(
(caseStudy) => !isClientCase(caseStudy),
);
/**
* Ordem dos clientes na lista de /cases e no mosaico de /servicos: a mesma da vitrine da home (SHOWCASE em
* lib/project-showcase.ts), com a SEV Moda Íntima primeiro. Cliente fora desta lista vai para o fim.
*/
const clientListingOrder = [
"sev-modaintima",
"lavacao-047",
"sc-plus",
"as-servicos",
];
function listingRank({ id }: { id: string }) {
const rank = clientListingOrder.indexOf(id);
return rank === -1 ? clientListingOrder.length : rank;
}
export const clientCasesForListing = [...clientCases].sort(
(a, b) => listingRank(a) - listingRank(b),
);
/** Data (AAAA-MM-DD) da última mudança no conteúdo de cada página fixa: vira o `lastmod` do mapa do site. */
export const pageUpdatedAt = {
home: "2026-10-14",
servicos: "2026-10-14",
cases: "2026-10-14",
ia: "2026-10-14",
curriculo: "2026-10-14",
// a própria página informa a vigência (13 de setembro de 2026)
privacidade: "2026-09-13",
} as const;
export interface ServiceOffer {
id: "site" | "sistema" | "revisao";
/** Nome da oferta, o mesmo da home, da página da oferta, dos dados estruturados e do WhatsApp. */
name: string;
/** Assunto da conversa de WhatsApp, em minúsculas e com artigo, para a frase "Quero conversar sobre {assunto}.". */
whatsappSubject: string;
/** Uma frase sobre a oferta (descrição dos dados estruturados). */
summary: string;
/** Página que explica a oferta. */
href: string;
/** O que a pessoa recebe, em 3 ou 4 itens, só com o que os cases ou a página da oferta já sustentam. A home e a página da oferta mostram esta lista. */
deliverables: string[];
/** Primeiro passo: uma conversa e, depois dela, o escopo e a proposta por escrito (sem prazo nem preço). A página da oferta mostra esta frase; a home, que serve às três, mostra `generalFirstStep`. */
firstStep: string;
/** Onde ver a oferta funcionando: o texto que abre a linha, os cases (links) e uma observação opcional. */
proof: { label: string; caseIds: string[]; note?: string };
}
/** O que vem depois da primeira conversa: o mesmo em cada oferta e na frase geral da home. */
const FIRST_STEP_NEXT = "Depois, escopo e proposta por escrito.";
/** O primeiro passo da home, que vale para as três ofertas: igual ao de cada uma, só sem dizer o que se entende na conversa. */
export const generalFirstStep = `Primeira conversa para entender o seu caso. ${FIRST_STEP_NEXT}`;
/**
* As três ofertas da home, na ordem do H1, com o mesmo nome. Cada texto só diz o que os cases citados, a experiência
* profissional ou a página /ia já sustentam; sem prazo nem preço.
*/
export const serviceOffers: ServiceOffer[] = [
{
id: "site",
...offerLabels.site,
summary:
"Catálogo ou tabela de preços, mensagem pronta no WhatsApp e um painel para você editar preços, textos e fotos sozinho.",
href: "/servicos/criacao-de-sites",
deliverables: [
"Tabela de preços ou catálogo, para o cliente ver o valor antes de chamar.",
"Botão de WhatsApp com a mensagem pronta, para o pedido chegar com o serviço escolhido.",
"Painel para você mudar preços, textos e fotos sem pedir a ninguém.",
"Leitura boa no celular e informações organizadas para o Google.",
],
firstStep: `Primeira conversa para entender o problema. ${FIRST_STEP_NEXT}`,
proof: {
label: "Veja funcionando",
caseIds: ["lavacao-047", "sev-modaintima"],
},
},
{
id: "sistema",
...offerLabels.sistema,
summary:
"Pedidos, estoque e rotinas que hoje vivem em planilhas e mensagens passam para um painel próprio, feito para a sua equipe.",
href: "/servicos/engenharia-de-software",
deliverables: [
"Catálogo e cadastro de produtos em um painel próprio.",
"Pedidos e estoque acompanhados em um só lugar, no lugar de planilhas e mensagens.",
"Acesso por perfil: cada pessoa vê só o que precisa.",
"Uma primeira versão com as funções prioritárias, ampliada em etapas.",
],
firstStep: `Primeira conversa para entender a operação. ${FIRST_STEP_NEXT}`,
proof: {
label: "Veja funcionando",
caseIds: ["sev-modaintima"],
note: "Na Apolo Energia, desde 2022, desenvolvo aplicações web e mobile para rotinas internas, APIs e painéis de operação. Por serem sistemas de uso interno, não há link nem detalhes públicos.",
},
},
{
id: "revisao",
...offerLabels.revisao,
summary:
"Avaliação de um sistema que já existe, inclusive feito com IA: teste das falhas de acesso a dados e separação do que dá para aproveitar do que é melhor refazer.",
href: "/ia",
deliverables: [
"As falhas de acesso a dados: quem consegue ver ou alterar o dado de quem.",
"O que dá para aproveitar do que já está pronto.",
"O que é melhor refazer, com o motivo de cada parte.",
"Um orçamento por escrito para pôr o sistema em produção.",
],
firstStep: `Primeira conversa para entender o app e o que ele precisa fazer. ${FIRST_STEP_NEXT}`,
proof: {
label: "Veja como funciona",
caseIds: [],
note: "A página da revisão mostra o que você recebe, três episódios públicos com plataformas de apps feitos com IA e os cuidados com dados pessoais (LGPD).",
},
},
];
export const serviceHubLinks = servicePages.map((service) => ({
href: `/servicos/${service.slug}`,
label: service.navLabel,
description: service.intro,
}));
export function getServicePage(slug: string) {
return servicePages.find((service) => service.slug === slug);
}
/** A oferta que a página de serviço explica; os serviços que não são oferta (e a revisão, que abre /ia) não têm. */
export function getServiceOffer(slug: string) {
return serviceOffers.find(({ href }) => href === `/servicos/${slug}`);
}
/** Cases na ordem de `caseIds`, com os de cliente à frente dos de laboratório. */
export function getRelatedCases(caseIds: string[]) {
const cases = caseIds.flatMap((id) => {
const caseStudy = caseStudies.find((item) => item.id === id);
return caseStudy ? [caseStudy] : [];
});
return [
...cases.filter(isClientCase),
...cases.filter((caseStudy) => !isClientCase(caseStudy)),
];
}
export function getRelatedServices(caseId: string): ServicePageContent[] {
return servicePages.filter(({ relatedCaseIds }) =>
relatedCaseIds.includes(caseId),
);
}