feat: harden portfolio and add SEO foundations
This commit is contained in:
1 parent
b079afdd73
commit
62bcfbd8fa
121 files changed
+7769
-10469
No files matched your search
@@ -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
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user