diff --git a/src/components/Projects/ProjectList.astro b/src/components/Projects/ProjectList.astro index b88b09bf..038cad53 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..b3b85d31 100644 --- a/src/pages/projects/[slug].astro +++ b/src/pages/projects/[slug].astro @@ -2,57 +2,135 @@ 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", + }, + ] + : []), + ...(project.data.goalDocUrl + ? [ + { + href: project.data.goalDocUrl, + label: "GOAL.md", + }, + ] + : []), + ...(project.data.roadmapDocUrl + ? [ + { + href: project.data.roadmapDocUrl, + label: "ROADMAP.md", + }, + ] + : []), +]; --- -
+
-
+
+

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 +138,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] }, + }, + ]); + }); +});