feat(cases): mídia no topo, títulos de busca curtos e CreativeWork

Case com mídia ao lado do título e play acessível; problema de cada cliente reescrito com base nos dados; serviços relacionados em 2 cards; FAQ antes do próximo passo e bloco 'Onde já apliquei isso'; Apolo citada em IoT e arquitetura. metaTitle até 43 caracteres e descrições até 155 com teste; JSON-LD CreativeWork; imagens de compartilhamento abaixo de 100 KB; 404 e robots corrigidos; server-only nos módulos com node:.
This commit is contained in:
Evandro Fonseca Junior committed 2026-10-14 14:15:25 -03:00
1 parent c9a0b80656
commit e80f73d075
52 files changed
+2593 -439

No files matched your search

+38 -1
View File
@@ -1,5 +1,11 @@
import type { Metadata } from "next";
import { type ServicePageContent, siteName, siteUrl } from "./site-content";
import {
type CaseStudyContent,
isClientCase,
type ServicePageContent,
siteName,
siteUrl,
} from "./site-content";
export const twitterHandle = "@evandrodevbr";
@@ -78,6 +84,37 @@ export function buildServiceJsonLd(service: ServicePageContent) {
} as const;
}
/** Imagem de compartilhamento do case: a mesma que as redes recebem em `og:image` (rota opengraph-image do case). */
export function getCaseImageUrl(id: string) {
return `${siteUrl}/cases/${id}/opengraph-image/${id}`;
}
/** Trabalho do case como `CreativeWork`: autor ligado à pessoa e, nos projetos de cliente, o cliente em nome de quem foi feito. */
export function buildCaseJsonLd(caseStudy: CaseStudyContent) {
const pageUrl = `${siteUrl}/cases/${caseStudy.id}`;
return {
"@type": "CreativeWork",
"@id": `${pageUrl}#creative-work`,
name: `${caseStudy.title}: ${caseStudy.subtitle}`,
description: caseStudy.metaDescription,
url: pageUrl,
image: getCaseImageUrl(caseStudy.id),
inLanguage: "pt-BR",
creator: { "@id": SEO_IDS.person },
...(isClientCase(caseStudy)
? {
sourceOrganization: {
"@type": "Organization",
name: caseStudy.title,
...(caseStudy.demoUrl ? { url: caseStudy.demoUrl } : {}),
},
}
: {}),
keywords: caseStudy.stack.join(", "),
};
}
export function buildBreadcrumbList(
pageUrl: string,
items: readonly (readonly [name: string, url: string])[],