import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { getCaseMedia } from "@/app/cases/_components/case-media"; import { compactHero, heroWithMediaGrid, } from "@/app/cases/_components/hero-styles"; import { Breadcrumb } from "@/app/components/Breadcrumb"; import { pageTop, primaryButton, secondaryButtonDark, } from "@/app/components/button-styles"; import { Faq } from "@/app/components/Faq"; import HoverPrefetchLink from "@/app/components/HoverPrefetchLink"; import WhatsAppLink from "@/app/components/WhatsAppLink"; import { safeJsonLd } from "@/lib/jsonld"; import { buildBreadcrumbList, buildPageSocialMetadata, buildServiceJsonLd, } from "@/lib/seo"; import { buttonLabels, caseStudies, getRelatedCases, getServicePage, servicePages, siteUrl, } from "@/lib/site-content"; import { ServiceDiagram } from "../_components/ServiceDiagram"; import { ServiceHeroCover } from "../_components/ServiceHeroCover"; import { ServiceOffer } from "../_components/ServiceOffer"; import { ServiceRelatedCases } from "../_components/ServiceRelatedCases"; interface ServicePageProps { params: Promise<{ slug: string; }>; } export function generateStaticParams() { return servicePages.map((service) => ({ slug: service.slug })); } export async function generateMetadata({ params, }: ServicePageProps): Promise { const { slug } = await params; const service = getServicePage(slug); if (!service) { return { title: `Serviço não encontrado`, }; } const url = `${siteUrl}/servicos/${service.slug}`; return { title: service.metaTitle, description: service.metaDescription, ...buildPageSocialMetadata({ url, title: service.metaTitle, description: service.metaDescription, type: "article", }), }; } export default async function ServicePage({ params }: ServicePageProps) { const { slug } = await params; const service = getServicePage(slug); if (!service) { notFound(); } const relatedCases = getRelatedCases(service.relatedCaseIds); // capa do topo: o case escolhido para o serviço, se tiver captura gravada do aparelho pedido; senão, o esquema de fluxo const heroDevice = service.heroCase?.device ?? "desktop"; const heroCase = caseStudies.find( ({ id }) => id === service.heroCase?.id && Boolean(getCaseMedia(id, heroDevice)), ); const diagram = heroCase ? undefined : service.diagram; const hasHeroSide = Boolean(heroCase || diagram); // o case da capa é citado pela legenda dela, e não ganha cartão em "Onde já apliquei isso" const hasCaseCards = relatedCases.some(({ id }) => id !== heroCase?.id); const pageUrl = `${siteUrl}/servicos/${service.slug}`; const jsonLd = { "@context": "https://schema.org", "@graph": [ buildServiceJsonLd(service), buildBreadcrumbList(pageUrl, [ ["Início", siteUrl], ["Serviços", `${siteUrl}/servicos`], [service.navLabel, pageUrl], ] as const), ], }; return (

{service.eyebrow}

{service.headline}

{service.answer}

{buttonLabels.contact} {hasCaseCards ? ( Ver projetos parecidos ) : null}

O botão abre uma conversa no WhatsApp, sem formulário. Garuva e Joinville (SC) · atendimento remoto em todo o Brasil.

{diagram ? ( ) : ( )}

Para quem faz sentido

    {service.audience.map((item) => (
  • {item}
  • ))}

O que podemos entregar

    {service.outcomes.map((item) => (
  • {item}
  • ))}
Da conversa à entrega

Como trabalhamos

    {service.process.map((step) => (
  1. {step}
  2. ))}
Possibilidades de uso

Imagine na sua rotina

Situações comuns em que este serviço ajuda. A sua será combinada na conversa.

    {service.examples.map((example) => (
  • {example}
  • ))}
Detalhes técnicos e tecnologias
    {service.technicalDetails.map((detail) => (
  • {detail}
  • ))}

Tecnologias que costumo usar neste serviço. A escolha depende do problema e do ambiente.

    {service.stack.map((item) => (
  • {item}
  • ))}
Próximo passo

Conte o que você precisa resolver.

Pode ser uma ideia, uma tarefa que toma tempo ou um sistema que precisa melhorar. Não é preciso chegar com uma solução técnica. Atendo em Garuva e Joinville (SC) e remotamente, em todo o Brasil.

{buttonLabels.contact} {buttonLabels.allServices}
); }