feat: harden portfolio and add SEO foundations

This commit is contained in:
Evandro Fonseca Junior committed 2026-09-04 19:25:30 -03:00
1 parent b079afdd73
commit 62bcfbd8fa
121 files changed
+7769 -10469

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
import { render, screen, within } from "@testing-library/react";
import { metadata as rootMetadata } from "../layout";
import CurriculoPage from "./page";
jest.mock("next/font/google", () => ({
Geist_Mono: () => ({ variable: "font-geist-mono" }),
Space_Grotesk: () => ({ variable: "font-space-grotesk" }),
}));
jest.mock("next/font/local", () => () => ({
variable: "font-monument-extended",
}));
const authorizedRegion =
"Base em Garuva, atendimento a projetos no Norte de Santa Catarina e atuação remota.";
it("uses one factual regional description across home metadata", () => {
const description = rootMetadata.description;
expect(typeof description).toBe("string");
expect(description).toContain(authorizedRegion);
expect(description).not.toMatch(
/Joinville|São Francisco do Sul|Itapoá|Jaraguá do Sul|Curitiba/,
);
expect(rootMetadata.openGraph).toMatchObject({ description });
expect(rootMetadata.twitter).toMatchObject({ description });
});
it("shows a matching breadcrumb and keeps consulting secondary to hiring", () => {
render(CurriculoPage());
const breadcrumb = screen.getByRole("navigation", { name: "Breadcrumb" });
const breadcrumbLinks = within(breadcrumb).getAllByRole("link");
expect(breadcrumbLinks.map((link) => link.textContent)).toEqual([
"Início",
"Currículo",
]);
expect(breadcrumbLinks[0]).toHaveAttribute("href", "/");
expect(breadcrumbLinks[1]).toHaveAttribute("href", "/curriculo");
expect(breadcrumbLinks[1]).toHaveAttribute("aria-current", "page");
const hiringLink = screen.getByRole("link", { name: /oportunidade/i });
const consultingLink = screen.getByRole("link", { name: /consultoria/i });
expect(hiringLink).toHaveAttribute("href", "/#contact");
expect(consultingLink).toHaveAttribute("href", "/servicos");
expect(
hiringLink.compareDocumentPosition(consultingLink) &
Node.DOCUMENT_POSITION_FOLLOWING,
).toBeTruthy();
});
+37 -27
View File
@@ -2,19 +2,20 @@ import type { Metadata } from "next";
import Link from "next/link";
import { safeJsonLd } from "@/lib/jsonld";
import { portfolio } from "@/lib/portfolio-data";
import { buildBreadcrumbList, buildProfilePageJsonLd } from "@/lib/seo";
import { siteName, siteUrl } from "@/lib/site-content";
const pageUrl = `${siteUrl}/curriculo`;
export const metadata: Metadata = {
title: "Currículo — Engenheiro e Desenvolvedor de Software",
title: "Currículo de Evandro Fonseca Junior para Contratação",
description:
"Currículo de Evandro Fonseca Junior, engenheiro da computação e desenvolvedor de software em Garuva, Joinville, Norte de Santa Catarina e Curitiba. Experiência em Next.js, TypeScript, Node.js, Rust, IoT e sistemas críticos.",
"Currículo profissional de Evandro Fonseca Junior, engenheiro da computação e desenvolvedor de software, com experiência, formação e competências técnicas.",
alternates: { canonical: pageUrl },
openGraph: {
title: `Currículo de Evandro Fonseca Junior | ${siteName}`,
description:
"Engenheiro da computação e desenvolvedor de software disponível para oportunidades CLT, PJ e projetos estratégicos no Norte de SC, Curitiba e remoto.",
"Experiência profissional, formação e competências técnicas de Evandro Fonseca Junior para avaliação de contratação.",
url: pageUrl,
siteName,
type: "profile",
@@ -24,25 +25,13 @@ export const metadata: Metadata = {
export default function CurriculoPage() {
const jsonLd = {
"@context": "https://schema.org",
"@type": "ProfilePage",
dateModified: new Date().toISOString(),
mainEntity: {
"@type": "Person",
"@id": `${siteUrl}/#person`,
name: portfolio.personal.name,
jobTitle:
"Engenheiro da Computação e Desenvolvedor de Software Full-Stack",
description: portfolio.personal.summary,
url: siteUrl,
sameAs: [portfolio.personal.github, portfolio.personal.linkedin],
homeLocation: {
"@type": "Place",
name: "Garuva, Santa Catarina, Brasil",
},
knowsAbout: portfolio.skills.technical.flatMap(
(category) => category.skills,
),
},
"@graph": [
buildProfilePageJsonLd(),
buildBreadcrumbList(pageUrl, [
["Início", siteUrl],
["Currículo", pageUrl],
] as const),
],
};
return (
@@ -50,15 +39,33 @@ export default function CurriculoPage() {
<script type="application/ld+json">{safeJsonLd(jsonLd)}</script>
<section className="ds-section ds-section-dark">
<div className="ds-section-shell max-w-[960px]">
<nav aria-label="Breadcrumb" className="mb-sp-6">
<ol className="flex flex-wrap items-center gap-sp-2 text-sm">
<li>
<Link className="ds-link ds-link-muted" href="/">
Início
</Link>
</li>
<li className="flex items-center gap-sp-2">
<span aria-hidden="true">/</span>
<Link
aria-current="page"
className="ds-link ds-link-muted"
href="/curriculo"
>
Currículo
</Link>
</li>
</ol>
</nav>
<p className="ds-eyebrow">Currículo profissional</p>
<h1 className="ds-section-title text-white">
Engenheiro da Computação e Desenvolvedor de Software para Garuva,
Joinville, Curitiba e remoto.
Engenheiro da Computação e Desenvolvedor de Software.
</h1>
<p className="ds-copy max-w-[70ch] !text-[rgba(255,255,255,.78)]">
{portfolio.personal.summary} Estou disponível para oportunidades CLT
e PJ, com prioridade para times e empresas do Norte de Santa
Catarina e Curitiba que precisam de execução técnica consistente.
Base em Garuva, atendimento a projetos no Norte de Santa Catarina e
atuação remota. Este currículo reúne experiência profissional,
formação e competências técnicas para avaliação de contratação.
</p>
<div className="mt-sp-6 flex flex-wrap gap-sp-3">
<a className="ds-link ds-link-accent" href="/Profile.pdf" download>
@@ -67,6 +74,9 @@ export default function CurriculoPage() {
<Link className="ds-link ds-link-muted" href="/#contact">
Falar sobre uma oportunidade
</Link>
<Link className="ds-link ds-link-muted" href="/servicos">
Procurando consultoria? Ver serviços
</Link>
</div>
</div>
</section>