From 4d0cbb7fb241847ff4784dded1fc8ee05640959c Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 21 Aug 2026 15:46:33 +0200 Subject: [PATCH] Refactor project slug handling and improve project retrieval logic --- app/projects/[projectName]/page.tsx | 18 +++++------------- components/commercial-project-card.tsx | 3 ++- components/project-item.tsx | 3 ++- lib/data.ts | 6 ++++++ lib/slug.ts | 10 ++++++++++ 5 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 lib/slug.ts diff --git a/app/projects/[projectName]/page.tsx b/app/projects/[projectName]/page.tsx index 979c05f..e2fc827 100644 --- a/app/projects/[projectName]/page.tsx +++ b/app/projects/[projectName]/page.tsx @@ -1,5 +1,4 @@ -import { projects } from "@/lib/data"; -import { Project } from "@/lib/types"; +import { getProjectBySlug, projects, projectSlug } from "@/lib/data"; import Chip from "@/components/chip"; import MarkdownContent from "@/components/markdown-content"; import { Metadata } from "next"; @@ -7,16 +6,9 @@ import Image from "next/image"; import { Github, Eye, CloudDownload } from "lucide-react"; import { notFound } from "next/navigation"; -function getProjectByName(name: string): Project | undefined { - const decodedName = decodeURIComponent(name.replace(/\+/g, " ")); - return projects.find( - (p) => p.name.toLowerCase() === decodedName.toLowerCase() - ); -} - export async function generateStaticParams() { return projects.map((project) => ({ - projectName: encodeURIComponent(project.name.replace(/\s/g, "+")), + projectName: projectSlug(project), })); } @@ -26,13 +18,13 @@ export async function generateMetadata({ params: Promise<{ projectName: string }>; }): Promise { const { projectName } = await params; - const project = getProjectByName(projectName); + const project = getProjectBySlug(projectName); if (!project) { return { title: "Project Not Found" }; } - const slug = encodeURIComponent(project.name.replace(/\s/g, "+")); + const slug = projectSlug(project); return { title: `${project.name} | Gabriel Kaszewski`, @@ -70,7 +62,7 @@ export default async function ProjectDetailPage({ params: Promise<{ projectName: string }>; }) { const { projectName } = await params; - const project = getProjectByName(projectName); + const project = getProjectBySlug(projectName); if (!project) { notFound(); diff --git a/components/commercial-project-card.tsx b/components/commercial-project-card.tsx index 7620afd..418663f 100644 --- a/components/commercial-project-card.tsx +++ b/components/commercial-project-card.tsx @@ -2,6 +2,7 @@ import Link from "next/link"; import { Project } from "@/lib/types"; import Chip from "@/components/chip"; import { Eye } from "lucide-react"; +import { projectSlug } from "@/lib/data"; const CommercialProjectCard = ({ project }: { project: Project }) => { return ( @@ -34,7 +35,7 @@ const CommercialProjectCard = ({ project }: { project: Project }) => {
Read more diff --git a/components/project-item.tsx b/components/project-item.tsx index b227f2a..210eb8a 100644 --- a/components/project-item.tsx +++ b/components/project-item.tsx @@ -1,4 +1,5 @@ import Link from "next/link"; +import { projectSlug } from "@/lib/data"; import { Project } from "@/lib/types"; import Chip from "@/components/chip"; import ImageCarousel from "@/components/image-carousel"; @@ -64,7 +65,7 @@ const ProjectItem = ({ project }: ProjectItemProps) => {
Read more diff --git a/lib/data.ts b/lib/data.ts index 3b80bc0..184904f 100644 --- a/lib/data.ts +++ b/lib/data.ts @@ -1,4 +1,5 @@ import { Skill, Job, Project, FunZoneItem, Writing, Photo } from "@/lib/types"; +import { slugify } from "@/lib/slug"; export const skills: Skill[] = [ { name: "Angular" }, @@ -628,3 +629,8 @@ export const photos: Photo[] = [ height: 2000, }, ]; + +export const projectSlug = (project: Project): string => slugify(project.name); + +export const getProjectBySlug = (slug: string): Project | undefined => + projects.find((project) => projectSlug(project) === slug); diff --git a/lib/slug.ts b/lib/slug.ts new file mode 100644 index 0000000..3b5e391 --- /dev/null +++ b/lib/slug.ts @@ -0,0 +1,10 @@ +export function slugify(value: string): string { + return value + .normalize("NFD") + .replace(/\p{Diacritic}/gu, "") + .replace(/ł/g, "l") + .replace(/Ł/g, "L") + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, ""); +}