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:.
25 lines
724 B
TypeScript
25 lines
724 B
TypeScript
import "server-only";
|
|
import { existsSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import {
|
|
type Device,
|
|
getShowcaseAssets,
|
|
type ShowcaseAssets,
|
|
} from "@/lib/project-showcase";
|
|
|
|
const idPattern = /^[a-z0-9-]+$/;
|
|
|
|
/**
|
|
* Pôster e vídeo gravados em public/videos/<id>/, ou `undefined` quando o projeto não tem captura.
|
|
* Roda no servidor (na geração das páginas): olha se o pôster existe no disco.
|
|
*/
|
|
export function getCaseMedia(
|
|
id: string,
|
|
device: Device,
|
|
): ShowcaseAssets | undefined {
|
|
if (!idPattern.test(id)) return undefined;
|
|
const assets = getShowcaseAssets(id, device);
|
|
const file = join(process.cwd(), "public", assets.poster);
|
|
return existsSync(file) ? assets : undefined;
|
|
}
|