Cases da SEV Moda Íntima e da Lavação 047; case no formato cliente, problema, entrega, mídia e contato, com detalhes técnicos recolhidos; sem GitHub, ressalvas e fontes de commit. /cases separa clientes e Laboratório. Serviços mostram o case de cliente certo e o bloco de investimento e prazo só aparece preenchido. Metadata social própria por página, not-found com noindex, sitemap com /ia.
128 lines
3.5 KiB
TypeScript
128 lines
3.5 KiB
TypeScript
import { existsSync, readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { getOgImagePath, PROJECT_VIDEO_IDS } from "./project-showcase";
|
|
|
|
const brandMark = `data:image/png;base64,${readFileSync(
|
|
join(process.cwd(), "public/brand/mark-dark.png"),
|
|
).toString("base64")}`;
|
|
|
|
export const OG_SIZE = { width: 1200, height: 630 } as const;
|
|
export const OG_CONTENT_TYPE = "image/png";
|
|
|
|
/** Capa 1200x630 gravada da página do projeto (public/videos/<id>/og.jpg), como data URI; `undefined` se não existir. */
|
|
export function readProjectOgBackground(id: string): string | undefined {
|
|
if (!PROJECT_VIDEO_IDS.includes(id)) return undefined;
|
|
const path = join(process.cwd(), "public", getOgImagePath(id));
|
|
if (!existsSync(path)) return undefined;
|
|
return `data:image/jpeg;base64,${readFileSync(path).toString("base64")}`;
|
|
}
|
|
|
|
export function OgCard({
|
|
eyebrow,
|
|
title,
|
|
description,
|
|
backgroundImage,
|
|
}: {
|
|
eyebrow: string;
|
|
title: string;
|
|
description: string;
|
|
/** Imagem de fundo (data URI), escurecida da esquerda para a direita para o texto continuar legível. */
|
|
backgroundImage?: string;
|
|
}) {
|
|
return (
|
|
<div
|
|
style={{
|
|
width: "100%",
|
|
height: "100%",
|
|
display: "flex",
|
|
position: "relative",
|
|
flexDirection: "column",
|
|
justifyContent: "space-between",
|
|
background: "#050505",
|
|
color: "#f4f1e8",
|
|
padding: 72,
|
|
fontFamily: "Arial, sans-serif",
|
|
}}
|
|
>
|
|
{backgroundImage && (
|
|
<>
|
|
{/* biome-ignore lint/performance/noImgElement: o ImageResponse (satori) só desenha <img> */}
|
|
<img
|
|
src={backgroundImage}
|
|
alt=""
|
|
width={OG_SIZE.width}
|
|
height={OG_SIZE.height}
|
|
style={{ position: "absolute", top: 0, left: 0 }}
|
|
/>
|
|
<div
|
|
style={{
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
width: OG_SIZE.width,
|
|
height: OG_SIZE.height,
|
|
display: "flex",
|
|
background:
|
|
"linear-gradient(90deg, rgba(5,5,5,0.97) 0%, rgba(5,5,5,0.9) 48%, rgba(5,5,5,0.58) 100%)",
|
|
}}
|
|
/>
|
|
</>
|
|
)}
|
|
{/* biome-ignore lint/performance/noImgElement: o ImageResponse (satori) só desenha <img> */}
|
|
<img
|
|
src={brandMark}
|
|
alt="Evandro.dev.br"
|
|
width={80}
|
|
height={80}
|
|
style={{ position: "absolute", top: 48, right: 72 }}
|
|
/>
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
paddingRight: 112,
|
|
color: "#ccff00",
|
|
fontSize: 24,
|
|
letterSpacing: "0.16em",
|
|
textTransform: "uppercase",
|
|
}}
|
|
>
|
|
{eyebrow}
|
|
</div>
|
|
<div style={{ display: "flex", flexDirection: "column", gap: 28 }}>
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
fontSize: 64,
|
|
fontWeight: 700,
|
|
lineHeight: 1.08,
|
|
}}
|
|
>
|
|
{title}
|
|
</div>
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
maxWidth: 980,
|
|
color: "#c7c3ba",
|
|
fontSize: 28,
|
|
lineHeight: 1.35,
|
|
}}
|
|
>
|
|
{description}
|
|
</div>
|
|
</div>
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
borderTop: "1px solid #343434",
|
|
paddingTop: 24,
|
|
fontSize: 20,
|
|
letterSpacing: "0.12em",
|
|
}}
|
|
>
|
|
EVANDRO.DEV.BR / ENGENHARIA DE SOFTWARE
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|