-
+
{project.title}
-
+
diff --git a/src/data/projects.ts b/src/data/projects.ts
index 86237aa..9172454 100644
--- a/src/data/projects.ts
+++ b/src/data/projects.ts
@@ -8,6 +8,7 @@ export type Project = {
pills: string[];
/** paragraphs of prose for the detail page */
body: string[];
+ isCert?: boolean;
};
export const PROJECTS: Project[] = [
@@ -65,6 +66,36 @@ export const PROJECTS: Project[] = [
},
];
+export const CERTIFICATIONS: Project[] = [
+ {
+ slug: "foundational-csharp",
+ title: "Foundational C# (Microsoft)",
+ description:
+ "Foundational C# course created by Microsoft, issued by FreeCodeCamp",
+ link: "https://www.freecodecamp.org/certification/alexavf/foundational-c-sharp-with-microsoft",
+ pills: ["Software Development", "C#"],
+ body: [
+ "A course created by Microsoft, a comprehensive intro to the core concepts and the syntax of C#.",
+ "Worked with creating basic, logical console applications and how to work with data and properly debug using Visual Studio.",
+ ],
+ },
+ {
+ slug: "introduction-to-frontend-development",
+ title: "Intro to Frontend Development (Meta)",
+ description: "Intro to frontend created by Meta, issued by Coursera",
+ link: "https://coursera.org/share/df3426a13f7bcdaa9f82f88e77554425",
+ pills: ["Software Development", "JavaScript", "HTML", "CSS"],
+ body: [
+ "A course that took me through the basics of frontend development with JS, CSS, HTML and more.",
+ "Currently working on the full certification from Meta, including experience with React, Git, Figma and more.",
+ ],
+ },
+];
+
export function findProject(slug: string | undefined) {
return PROJECTS.find((p) => p.slug === slug);
}
+
+export function findCertification(slug: string | undefined) {
+ return CERTIFICATIONS.find((p) => p.slug === slug);
+}
diff --git a/src/pages/CertificationDetail.tsx b/src/pages/CertificationDetail.tsx
new file mode 100644
index 0000000..d6abf3d
--- /dev/null
+++ b/src/pages/CertificationDetail.tsx
@@ -0,0 +1,66 @@
+import { Link, useParams } from "react-router-dom";
+import Footer from "../components/Footer";
+import NotFound from "./NotFound";
+import { findCertification } from "../data/projects";
+
+export default function CertificationDetail() {
+ const { slug } = useParams();
+ const cert = findCertification(slug);
+
+ if (!cert) return
;
+
+ return (
+
+
+
+
+
{cert.title}
+
+ {cert.pills.map((pill) => (
+
+ {pill}
+
+ ))}
+
+
+
+
+ {cert.body.map((paragraph, i) => (
+
{paragraph}
+ ))}
+
+
+
+
+
+
+
+
+ < All certifications
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/Certifications.tsx b/src/pages/Certifications.tsx
new file mode 100644
index 0000000..110dafb
--- /dev/null
+++ b/src/pages/Certifications.tsx
@@ -0,0 +1,52 @@
+import { Link } from "react-router-dom";
+import ProjectCard from "../components/ProjectCard";
+import Footer from "../components/Footer";
+import { CERTIFICATIONS } from "../data/projects";
+
+export default function Certifications() {
+ return (
+
+
+
CERTIFICATIONS
+
+ Professional Certifications
+
+
+ All of my personal professional certifications for different things in
+ the software dev /QA testing space.
+
+
+
+
+
+
+
+ ALL CERTIFICATIONS
+
+
+ {CERTIFICATIONS.map((project) => (
+
+ ))}
+
+
+
+
+
+
+
+ < Back home
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx
index 7e28948..99f73d8 100644
--- a/src/pages/Home.tsx
+++ b/src/pages/Home.tsx
@@ -7,7 +7,7 @@ import BlogRow from "../components/BlogRow";
import GameComponent from "../components/info/GameComponent";
import MusicComponent from "../components/info/MusicComponent";
import EmailLink from "../components/EmailLink";
-import { PROJECTS } from "../data/projects";
+import { PROJECTS, CERTIFICATIONS } from "../data/projects";
import { PROFILES } from "../utils/site";
export default function Home() {
@@ -84,6 +84,23 @@ export default function Home() {
+
+
+ CERTIFICATIONS
+
+
+
+ {CERTIFICATIONS.map((project) => (
+
+ ))}
+
+
+
+
+
MY ACTIVITIES
diff --git a/src/routes.tsx b/src/routes.tsx
index 2ae1b60..e23b567 100644
--- a/src/routes.tsx
+++ b/src/routes.tsx
@@ -5,13 +5,22 @@ import ProjectDetail from "./pages/ProjectDetail";
import Sports from "./pages/Sports";
import Pictures from "./pages/Pictures";
import NotFound from "./pages/NotFound";
-import { PROJECTS, findProject } from "./data/projects";
+import {
+ CERTIFICATIONS,
+ PROJECTS,
+ findProject,
+ findCertification,
+} from "./data/projects";
import type { PageMeta } from "./utils/seo";
import {
profilePageGraph,
projectListGraph,
projectGraph,
+ certificationGraph,
+ certificationListGraph,
} from "./utils/structuredData";
+import Certifications from "./pages/Certifications";
+import CertificationDetail from "./pages/CertificationDetail";
type Params = Record;
@@ -78,6 +87,35 @@ export const routes: AppRoute[] = [
};
},
},
+ {
+ path: "/certifications",
+ element: ,
+ sitemapPaths: () => ["/certifications"],
+ meta: () => ({
+ title: "Certifications — Alex Frantz",
+ description:
+ "All of my professionally-issued certifications. From software development to software testing, I am always studying something.",
+ path: "/certifications",
+ jsonLd: certificationListGraph(PROJECTS),
+ }),
+ },
+ {
+ path: "/certifications/:slug",
+ element: ,
+ sitemapPaths: () => CERTIFICATIONS.map((p) => `/certifications/${p.slug}`),
+ meta: (params) => {
+ const certification = findCertification(params.slug);
+ if (!certification) return null;
+
+ return {
+ title: `${certification.title} — Alex Frantz`,
+ description: certification.description,
+ path: `/certifications/${certification.slug}`,
+ type: "article",
+ jsonLd: certificationGraph(certification),
+ };
+ },
+ },
{
path: "/sports",
element: ,
@@ -85,7 +123,7 @@ export const routes: AppRoute[] = [
meta: () => ({
title: "Bills, Sabres & Yankees Scores — Alex Frantz",
description:
- "Live Buffalo Bills, Buffalo Sabres and New York Yankees scores, plus how my fantasy football matchup is going this week.",
+ "Live Buffalo Bills and Buffalo Sabres scores, plus how my fantasy football matchup is going this week.",
path: "/sports",
}),
},
diff --git a/src/utils/structuredData.ts b/src/utils/structuredData.ts
index e0773fd..dae633e 100644
--- a/src/utils/structuredData.ts
+++ b/src/utils/structuredData.ts
@@ -119,3 +119,52 @@ export function projectGraph(project: Project): object[] {
},
];
}
+
+export function certificationListGraph(certifications: Project[]): object[] {
+ return [
+ {
+ "@context": "https://schema.org",
+ "@type": "CollectionPage",
+ url: absoluteUrl("/projects"),
+ name: "Projects",
+ about: { "@id": PERSON_ID },
+ mainEntity: {
+ "@type": "ItemList",
+ itemListElement: certifications.map((project, index) => ({
+ "@type": "ListItem",
+ position: index + 1,
+ url: absoluteUrl(`/certifications/${project.slug}`),
+ name: project.title,
+ })),
+ },
+ },
+ ];
+}
+
+export function certificationGraph(certificate: Project): object[] {
+ return [
+ {
+ "@context": "https://schema.org",
+ "@type": "SoftwareSourceCode",
+ name: certificate.title,
+ description: certificate.description,
+ url: absoluteUrl(`/projects/${certificate.slug}`),
+ codeRepository: certificate.link,
+ programmingLanguage: certificate.pills,
+ author: { "@id": PERSON_ID },
+ },
+ {
+ "@context": "https://schema.org",
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Projects",
+ item: absoluteUrl("/certifications"),
+ },
+ { "@type": "ListItem", position: 2, name: certificate.title },
+ ],
+ },
+ ];
+}