From 603ac95f13030905ea0ca204753480a559476500 Mon Sep 17 00:00:00 2001 From: Schalk Neethling Date: Mon, 6 Jul 2026 11:48:35 +0200 Subject: [PATCH 1/2] Add project detail pages --- src/components/Projects/ProjectList.astro | 3 +- src/content.config.ts | 7 + src/content/projects/css-community-reset.md | 8 + src/content/projects/ossreleasefeed-v2.md | 8 + src/content/projects/web-platform-pulse.md | 8 + src/lib/projectPages.ts | 16 ++ src/pages/projects/[slug].astro | 256 +++++++++++++++++--- tests/projectPages.test.ts | 31 +++ 8 files changed, 303 insertions(+), 34 deletions(-) create mode 100644 src/lib/projectPages.ts create mode 100644 tests/projectPages.test.ts diff --git a/src/components/Projects/ProjectList.astro b/src/components/Projects/ProjectList.astro index 68259d14..7f6db914 100644 --- a/src/components/Projects/ProjectList.astro +++ b/src/components/Projects/ProjectList.astro @@ -2,6 +2,7 @@ import type { CollectionEntry } from "astro:content"; import ProjectCard from "./ProjectCard.astro"; +import { getProjectPath } from "../../lib/projectPages"; interface Props { heading: string; @@ -24,7 +25,7 @@ const { heading, headingId, intro, minColumnWidth = 280, projects } = ( + projects: readonly ProjectEntry[], +) { + return projects.map((project) => ({ + params: { slug: project.id }, + props: { project }, + })); +} diff --git a/src/pages/projects/[slug].astro b/src/pages/projects/[slug].astro index 695c6e45..ae60a32d 100644 --- a/src/pages/projects/[slug].astro +++ b/src/pages/projects/[slug].astro @@ -2,57 +2,131 @@ import { getCollection } from "astro:content"; import BaseLayout from "../../layouts/BaseLayout.astro"; +import { getProjectStaticPaths } from "../../lib/projectPages"; export async function getStaticPaths() { const projects = await getCollection("projects"); - return projects.map((project) => ({ - params: { slug: project.id }, - props: { project }, - })); + return getProjectStaticPaths(projects); } const { project } = Astro.props; const pageTitle = project.data.title; const pageDescription = project.data.description; const technologies = project.data.technologies ?? []; +const whatAndWhy = project.data.whatAndWhy ?? project.data.description; +const goalSummary = + project.data.goalSummary ?? + "A fuller project goal summary is coming as this page is expanded from the repository docs."; +const currentState = + project.data.currentState ?? + "This project has a place in the curated list. The deeper status notes will be filled in as the starter project pages are completed."; +const nextSteps = project.data.nextSteps ?? [ + "Write the project-specific goal summary.", + "Connect the page to the repository documentation workflow.", +]; +const contributionGuidance = + project.data.contributionGuidance ?? + "Follow the repository for now. Contribution notes will become more specific as the project page is completed."; +const projectLinks = [ + { + href: project.data.repoUrl, + label: "Repository", + }, + project.data.liveUrl + ? { + href: project.data.liveUrl, + label: "Live project", + } + : null, + project.data.goalDocUrl + ? { + href: project.data.goalDocUrl, + label: "GOAL.md", + } + : null, + project.data.roadmapDocUrl + ? { + href: project.data.roadmapDocUrl, + label: "ROADMAP.md", + } + : null, +].filter(Boolean); --- -
+
-
+
+

Project

{pageTitle}

-

{pageDescription}

+

{whatAndWhy}

+ +
+ { + project.data.language && ( + <> +
Primary language
+
{project.data.language}
+ + ) + } +
Kind
+
{project.data.category === "demo" ? "Little demo" : "Open source project"}
+
- { - technologies.length > 0 && ( -
-

Technologies

+
+

Goal

+

{goalSummary}

+
+ +
+
+

Where it is

+

{currentState}

+
+ +
+

What comes next

+
    + {nextSteps.map((nextStep) =>
  • {nextStep}
  • )} +
+
+
+ +
+

Technologies used

+ { + technologies.length > 0 ? (
    {technologies.map((technology) =>
  • {technology}
  • )}
-
- ) - } + ) : ( +

Technology notes will be added as this project page is expanded.

+ ) + } +
+ +
+

How people can get involved

+

{contributionGuidance}

+
-
+ @@ -60,18 +134,89 @@ const technologies = project.data.technologies ?? []; diff --git a/tests/projectPages.test.ts b/tests/projectPages.test.ts new file mode 100644 index 00000000..182bac72 --- /dev/null +++ b/tests/projectPages.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, it } from "vitest"; + +import { getProjectPath, getProjectStaticPaths } from "../src/lib/projectPages"; + +const projects = [ + { id: "css-community-reset", data: { title: "css-community-reset" } }, + { id: "web-platform-pulse", data: { title: "web-platform-pulse" } }, +] as const; + +describe("getProjectPath", () => { + it("returns the internal detail page URL for a project id", () => { + expect(getProjectPath("css-community-reset")).toBe( + "/projects/css-community-reset", + ); + }); +}); + +describe("getProjectStaticPaths", () => { + it("maps project entries into Astro static paths with project props", () => { + expect(getProjectStaticPaths(projects)).toEqual([ + { + params: { slug: "css-community-reset" }, + props: { project: projects[0] }, + }, + { + params: { slug: "web-platform-pulse" }, + props: { project: projects[1] }, + }, + ]); + }); +}); From 756321f1dceb57e07449481d9411cb2192d92291 Mon Sep 17 00:00:00 2001 From: Schalk Neethling Date: Mon, 6 Jul 2026 14:27:42 +0200 Subject: [PATCH 2/2] Narrow project detail links --- src/pages/projects/[slug].astro | 58 ++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/pages/projects/[slug].astro b/src/pages/projects/[slug].astro index ae60a32d..b3b85d31 100644 --- a/src/pages/projects/[slug].astro +++ b/src/pages/projects/[slug].astro @@ -33,25 +33,31 @@ const projectLinks = [ href: project.data.repoUrl, label: "Repository", }, - project.data.liveUrl - ? { - href: project.data.liveUrl, - label: "Live project", - } - : null, - project.data.goalDocUrl - ? { - href: project.data.goalDocUrl, - label: "GOAL.md", - } - : null, - project.data.roadmapDocUrl - ? { - href: project.data.roadmapDocUrl, - label: "ROADMAP.md", - } - : null, -].filter(Boolean); + ...(project.data.liveUrl + ? [ + { + href: project.data.liveUrl, + label: "Live project", + }, + ] + : []), + ...(project.data.goalDocUrl + ? [ + { + href: project.data.goalDocUrl, + label: "GOAL.md", + }, + ] + : []), + ...(project.data.roadmapDocUrl + ? [ + { + href: project.data.roadmapDocUrl, + label: "ROADMAP.md", + }, + ] + : []), +]; --- @@ -118,14 +124,12 @@ const projectLinks = [