feat(servicos): topo, entregáveis e cases por serviço, assunto próprio no WhatsApp e títulos curtos
This commit is contained in:
1 parent
cf360041bd
commit
2fd8b063d9
33 files changed
+1578
-300
No files matched your search
+59
-19
@@ -1,3 +1,4 @@
|
||||
import { offerLabels } from "./offer-labels";
|
||||
import { portfolio } from "./portfolio-data";
|
||||
import { isClientProject } from "./proof";
|
||||
|
||||
@@ -25,7 +26,10 @@ export const buttonLabels = {
|
||||
|
||||
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;
|
||||
@@ -36,6 +40,7 @@ export interface ServicePageContent {
|
||||
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[];
|
||||
@@ -43,6 +48,8 @@ export interface ServicePageContent {
|
||||
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. */
|
||||
@@ -101,12 +108,13 @@ export interface CaseStudyContent {
|
||||
export const servicePages: ServicePageContent[] = [
|
||||
{
|
||||
slug: "criacao-de-sites",
|
||||
navLabel: "Sites profissionais",
|
||||
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: "Site que traz pedidos pelo WhatsApp",
|
||||
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:
|
||||
@@ -138,12 +146,19 @@ export const servicePages: ServicePageContent[] = [
|
||||
"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"],
|
||||
relatedCaseIds: ["lavacao-047", "sc-plus", "as-servicos"],
|
||||
// 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":
|
||||
@@ -169,14 +184,15 @@ export const servicePages: ServicePageContent[] = [
|
||||
},
|
||||
{
|
||||
slug: "engenharia-de-software",
|
||||
navLabel: "Sistemas web e aplicativos mobile",
|
||||
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: "Sistema para tirar a operação da planilha",
|
||||
headline: offerLabels.sistema.name,
|
||||
answer:
|
||||
"Desenvolvo sistemas web, usados no navegador, e aplicativos mobile para celular. Também conecto ferramentas e evoluo sistemas existentes. Definimos juntos os usuários, as funções, as plataformas atendidas e a primeira entrega útil para o negócio.",
|
||||
"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: [
|
||||
@@ -215,6 +231,8 @@ export const servicePages: ServicePageContent[] = [
|
||||
"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?",
|
||||
@@ -235,7 +253,8 @@ export const servicePages: ServicePageContent[] = [
|
||||
},
|
||||
{
|
||||
slug: "consultoria-nextjs",
|
||||
navLabel: "Melhorias em sites e sistemas Next.js",
|
||||
navLabel: "Consultoria em Next.js",
|
||||
whatsappSubject: "uma consultoria em Next.js",
|
||||
eyebrow: "Consultoria Next.js",
|
||||
metaTitle: "Consultoria Next.js para site ou sistema",
|
||||
metaDescription:
|
||||
@@ -301,7 +320,8 @@ export const servicePages: ServicePageContent[] = [
|
||||
},
|
||||
{
|
||||
slug: "tauri-rust",
|
||||
navLabel: "Aplicativos desktop para Windows e Linux",
|
||||
navLabel: "Aplicativos desktop",
|
||||
whatsappSubject: "um aplicativo desktop",
|
||||
eyebrow: "Aplicativos desktop",
|
||||
metaTitle: "Aplicativos desktop para Windows e Linux",
|
||||
metaDescription:
|
||||
@@ -370,7 +390,8 @@ export const servicePages: ServicePageContent[] = [
|
||||
},
|
||||
{
|
||||
slug: "integracao-hardware-software-iot",
|
||||
navLabel: "Integração de equipamentos e sistemas",
|
||||
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:
|
||||
@@ -436,7 +457,8 @@ export const servicePages: ServicePageContent[] = [
|
||||
},
|
||||
{
|
||||
slug: "arquitetura-de-software",
|
||||
navLabel: "Diagnóstico e 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:
|
||||
@@ -816,14 +838,14 @@ export const labCases = caseStudies.filter(
|
||||
);
|
||||
|
||||
/**
|
||||
* Ordem dos clientes na lista de /cases e no mosaico de /servicos: a SEV Moda Íntima, que já abre a página de sistemas
|
||||
* e é a prova da oferta de sistema, vem por último e fica fora das três capas do mosaico. Cliente fora desta lista vai para o fim.
|
||||
* 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",
|
||||
"sev-modaintima",
|
||||
];
|
||||
|
||||
function listingRank({ id }: { id: string }) {
|
||||
@@ -848,18 +870,28 @@ export const pageUpdatedAt = {
|
||||
|
||||
export interface ServiceOffer {
|
||||
id: "site" | "sistema" | "revisao";
|
||||
/** Nome da oferta, o mesmo da home. */
|
||||
/** 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. */
|
||||
/** 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.
|
||||
@@ -867,7 +899,7 @@ export interface ServiceOffer {
|
||||
export const serviceOffers: ServiceOffer[] = [
|
||||
{
|
||||
id: "site",
|
||||
name: "Site que traz pedidos pelo WhatsApp",
|
||||
...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",
|
||||
@@ -877,6 +909,7 @@ export const serviceOffers: ServiceOffer[] = [
|
||||
"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"],
|
||||
@@ -884,7 +917,7 @@ export const serviceOffers: ServiceOffer[] = [
|
||||
},
|
||||
{
|
||||
id: "sistema",
|
||||
name: "Sistema para tirar a operação da planilha",
|
||||
...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",
|
||||
@@ -894,6 +927,7 @@ export const serviceOffers: ServiceOffer[] = [
|
||||
"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"],
|
||||
@@ -902,9 +936,9 @@ export const serviceOffers: ServiceOffer[] = [
|
||||
},
|
||||
{
|
||||
id: "revisao",
|
||||
name: "Revisão de sistema que já existe, inclusive feito com IA",
|
||||
...offerLabels.revisao,
|
||||
summary:
|
||||
"Avaliação do que já existe, teste das falhas de acesso a dados e separação do que dá para aproveitar do que é melhor refazer.",
|
||||
"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.",
|
||||
@@ -912,6 +946,7 @@ export const serviceOffers: ServiceOffer[] = [
|
||||
"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: [],
|
||||
@@ -930,6 +965,11 @@ 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) => {
|
||||
|
||||
Reference in new issue
Block a user