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

+6 -44
View File
@@ -3,43 +3,13 @@ import {
displayUrl,
} from "@/app/components/showcase/BrowserFrame";
import { PhoneFrame } from "@/app/components/showcase/PhoneFrame";
import type { ShowcaseAssets } from "@/lib/project-showcase";
import { CasePlayer } from "./CasePlayer";
import { getCaseMedia } from "./case-media";
import "../../components/showcase/showcase.css";
function CaseVideo({
assets,
label,
className,
}: {
assets: ShowcaseAssets;
label: string;
className: string;
}) {
return (
<video
className={className}
controls
muted
loop
playsInline
preload="none"
poster={assets.poster}
width={assets.width}
height={assets.height}
aria-label={label}
disablePictureInPicture
>
{assets.sources.map((source) => (
<source key={source.src} src={source.src} type={source.type} />
))}
</video>
);
}
/**
* Pôster e vídeo do projeto: o site no computador (moldura de navegador) e no celular (moldura de celular).
* O vídeo só baixa quando a pessoa aperta o play. Sem captura gravada, não mostra nada.
* Cada quadro mostra o pôster com um botão de play; o vídeo só baixa quando a pessoa aperta o botão.
* Sem captura gravada, não mostra nada.
*/
export function CaseMedia({
id,
@@ -55,16 +25,12 @@ export function CaseMedia({
if (!desktop && !mobile) return null;
return (
<div className="mt-sp-8 grid items-end gap-sp-8 md:grid-cols-[minmax(0,1fr)_auto]">
<div className="mt-sp-8 grid max-w-[1040px] items-end gap-sp-8 md:grid-cols-[minmax(0,1fr)_auto]">
{desktop ? (
<figure className="min-w-0">
<BrowserFrame url={displayUrl({ demoUrl, title })}>
<div className="relative aspect-[16/10] bg-[#0a0a0a]">
<CaseVideo
assets={desktop}
label={`Vídeo do site ${title} no computador`}
className="absolute inset-0 h-full w-full object-cover object-top"
/>
<CasePlayer assets={desktop} title={title} device="desktop" />
</div>
</BrowserFrame>
<figcaption className="mt-sp-3 font-[family-name:var(--font-body)] text-[15px] text-white/70">
@@ -75,11 +41,7 @@ export function CaseMedia({
{mobile ? (
<figure className="mx-auto w-[min(62vw,220px)] md:mx-0">
<PhoneFrame poster={mobile.poster}>
<CaseVideo
assets={mobile}
label={`Vídeo do site ${title} no celular`}
className="absolute inset-0 h-full w-full object-cover object-top"
/>
<CasePlayer assets={mobile} title={title} device="mobile" />
</PhoneFrame>
<figcaption className="mt-sp-3 text-center font-[family-name:var(--font-body)] text-[15px] text-white/70">
No celular.