Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
355c43c
Curate projects listing
schalkneethling Jul 6, 2026
98ae281
Add minimal project detail pages
schalkneethling Jul 6, 2026
603ac95
Add project detail pages
schalkneethling Jul 6, 2026
4a7bbd5
Fix projects masonry card visibility
schalkneethling Jul 6, 2026
e758af1
Merge branch 'codex/curated-projects-listing-1344' into codex/project…
schalkneethling Jul 6, 2026
7a7c079
Restore project card image headers
schalkneethling Jul 6, 2026
55368f4
Merge branch 'codex/curated-projects-listing-1344' into codex/project…
schalkneethling Jul 6, 2026
95300d9
Polish project card metadata and links
schalkneethling Jul 6, 2026
8ebd7c2
Merge branch 'codex/curated-projects-listing-1344' into codex/project…
schalkneethling Jul 6, 2026
756321f
Narrow project detail links
schalkneethling Jul 6, 2026
8be9ce0
Merge pull request #1352 from schalkneethling/codex/project-detail-pa…
schalkneethling Jul 6, 2026
3f13757
Complete starter project content
schalkneethling Jul 6, 2026
8b0dccb
Redesign project detail pages
schalkneethling Jul 6, 2026
3ed784f
Merge pull request #1353 from schalkneethling/codex/complete-starter-…
schalkneethling Jul 6, 2026
5688e3b
Add manual project doc cache refresh
schalkneethling Jul 6, 2026
d2d37e0
Merge pull request #1357 from schalkneethling/codex/manual-repo-doc-c…
schalkneethling Jul 6, 2026
4bacc26
Add project-local projects skill
schalkneethling Jul 6, 2026
2c64f5c
Merge pull request #1358 from schalkneethling/codex/project-local-wha…
schalkneethling Jul 6, 2026
3c52dfb
Refine project detail page design
schalkneethling Jul 6, 2026
2a07735
Merge branch 'main' into codex/curated-projects-listing-1344
schalkneethling Jul 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ export default defineConfig({
/* Run your local dev server before starting the tests */
webServer: {
command: "pnpm run dev --host 127.0.0.1",
env: {
ASTRO_DEV_BACKGROUND: "1",
},
url: "http://localhost:4321",
reuseExistingServer: !process.env.CI,
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/Header/Navigation.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<li><a href="/">Return home</a></li>
<li><a href="/now">What I'm doing now</a></li>
<li><a href="/about">#whoami</a></li>
<li><a href="/projects">Things I build</a></li>
<li><a href="/projects">What I want to exist</a></li>
<li><a href="/blog">My writing</a></li>
<li><a href="/contact">Get in touch</a></li>
</ul>
Expand Down
5 changes: 3 additions & 2 deletions src/components/Projects/ProjectCard.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ interface Props {
stars: number;
imageUrl: string;
featured?: boolean;
linkLabel?: string;
}

const { name, description, url, language, stars, imageUrl, featured } =
const { name, description, url, language, stars, imageUrl, featured, linkLabel } =
Astro.props;
---

Expand Down Expand Up @@ -46,7 +47,7 @@ const { name, description, url, language, stars, imageUrl, featured } =
</span>
</footer>
<a href={url} class="project-card-link">
View on GitHub <span aria-hidden="true">&rarr;</span>
{linkLabel ?? "View on GitHub"} <span aria-hidden="true">&rarr;</span>
</a>
</div>
</article>
Expand Down
56 changes: 56 additions & 0 deletions src/components/Projects/ProjectList.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
import type { CollectionEntry } from "astro:content";

import ProjectCard from "./ProjectCard.astro";

interface Props {
heading: string;
headingId: string;
intro?: string;
minColumnWidth?: number;
projects: CollectionEntry<"projects">[];
}

const { heading, headingId, intro, minColumnWidth = 280, projects } =
Astro.props;
---

<section aria-labelledby={headingId}>
<h2 id={headingId} class="gradient-text">{heading}</h2>
{intro && <p>{intro}</p>}
<masonry-grid-lanes min-column-width={minColumnWidth} gap="24">
{
projects.map((project) => (
<ProjectCard
name={project.data.title}
description={project.data.description}
url={`/projects/${project.id}`}
language={project.data.language ?? null}
stars={project.data.stars ?? 0}
imageUrl={project.data.imageUrl ?? ""}
featured={project.data.category === "main"}
linkLabel="View project"
/>
))
Comment thread
schalkneethling marked this conversation as resolved.
}
</masonry-grid-lanes>
</section>

<style>
section {
margin-block-start: var(--spacing-section-large);
}

masonry-grid-lanes {
display: block;
inline-size: 100%;
margin-block-start: var(--size-24);
position: relative;
}

masonry-grid-lanes:not(:defined) {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
</style>
20 changes: 20 additions & 0 deletions src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ const postsCollection = defineCollection({
}),
});

const projectsCollection = defineCollection({
loader: glob({
pattern: "**/*.md",
base: "./src/content/projects",
}),
schema: z.object({
category: z.enum(["main", "demo"]),
description: z.string(),
imageUrl: z.string().optional(),
language: z.string().optional(),
liveUrl: z.string().url().optional(),
order: z.number().int().positive(),
repoUrl: z.string().url(),
stars: z.number().int().nonnegative().optional(),
technologies: z.array(z.string()).optional(),
title: z.string(),
}),
});

export const collections = {
posts: postsCollection,
projects: projectsCollection,
};
7 changes: 7 additions & 0 deletions src/content/drafts/throwing-confetti-with-css-random.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: "Throwing Confetti with CSS Random"
pubDate: 2026-07-07
description: ""
author: "Schalk Neethling"
tags: ["css", "frontend-engineering-explained"]
---
10 changes: 10 additions & 0 deletions src/content/projects/common-components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "common-components"
description: "A collection of commonly used components as either HTML or Web Components."
category: "main"
order: 10
repoUrl: "https://github.com/schalkneethling/common-components"
language: "HTML"
stars: 3
technologies: ["HTML", "Web Components", "CSS"]
---
10 changes: 10 additions & 0 deletions src/content/projects/create-project-calavera.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "create-project-calavera"
description: "A simple starting skeleton of linters and formatters for common web projects."
category: "main"
order: 7
repoUrl: "https://github.com/schalkneethling/create-project-calavera"
language: "JavaScript"
stars: 7
technologies: ["JavaScript", "CLI", "Project Scaffolding"]
---
10 changes: 10 additions & 0 deletions src/content/projects/css-benchpress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "css-benchpress"
description: "Grow realistic web-platform CSS test cases until measurable performance regressions appear."
category: "main"
order: 8
repoUrl: "https://github.com/schalkneethling/css-benchpress"
language: "TypeScript"
stars: 9
technologies: ["TypeScript", "CSS", "Performance"]
---
10 changes: 10 additions & 0 deletions src/content/projects/css-community-reset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "css-community-reset"
description: "A CSS reset inspired by the community."
category: "main"
order: 1
repoUrl: "https://github.com/schalkneethling/css-community-reset"
language: "CSS"
stars: 16
technologies: ["CSS"]
---
10 changes: 10 additions & 0 deletions src/content/projects/css-custom-property-inspector.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "css-custom-property-inspector"
description: "A VS Code extension that shows CSS custom property values, definitions, and resolved references on hover."
category: "main"
order: 9
repoUrl: "https://github.com/schalkneethling/css-custom-property-inspector"
language: "TypeScript"
stars: 0
technologies: ["TypeScript", "VS Code", "CSS"]
---
10 changes: 10 additions & 0 deletions src/content/projects/css-expect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "css-expect"
description: "Write browser-native expectations for CSS custom functions and mixins."
category: "main"
order: 5
repoUrl: "https://github.com/schalkneethling/css-expect"
language: "TypeScript"
stars: 4
technologies: ["TypeScript", "CSS", "Testing"]
---
10 changes: 10 additions & 0 deletions src/content/projects/css-media-pseudo-polyfill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "css-media-pseudo-polyfill"
description: "A CSS polyfill for media pseudo-classes such as :playing, :paused, :seeking, and :muted."
category: "main"
order: 11
repoUrl: "https://github.com/schalkneethling/css-media-pseudo-polyfill"
language: "TypeScript"
stars: 3
technologies: ["TypeScript", "CSS", "Polyfill"]
---
10 changes: 10 additions & 0 deletions src/content/projects/css-property-type-validator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "css-property-type-validator"
description: "Standalone tooling for validating CSS custom property registrations declared with @property."
category: "main"
order: 6
repoUrl: "https://github.com/schalkneethling/css-property-type-validator"
language: "TypeScript"
stars: 10
technologies: ["TypeScript", "CSS", "Tooling"]
---
10 changes: 10 additions & 0 deletions src/content/projects/css-tree-ast-viewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "css-tree-ast-viewer"
description: "A focused CSS AST explorer for writing CSS in one pane and viewing the CSS Tree AST in another."
category: "demo"
order: 2
repoUrl: "https://github.com/schalkneethling/css-tree-ast-viewer"
language: "TypeScript"
stars: 1
technologies: ["TypeScript", "CSS", "AST"]
---
10 changes: 10 additions & 0 deletions src/content/projects/jsconsole.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "jsconsole"
description: "A focused JavaScript REPL for quickly testing browser-style JavaScript snippets."
category: "demo"
order: 3
repoUrl: "https://github.com/schalkneethling/jsconsole"
language: "TypeScript"
stars: 0
technologies: ["TypeScript", "JavaScript", "REPL"]
---
10 changes: 10 additions & 0 deletions src/content/projects/little-demos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "little-demos"
description: "A collection of little web platform feature demos."
category: "demo"
order: 1
repoUrl: "https://github.com/schalkneethling/little-demos"
language: "CSS"
stars: 0
technologies: ["HTML", "CSS", "JavaScript"]
---
10 changes: 10 additions & 0 deletions src/content/projects/masonry-gridlanes-wc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "masonry-gridlanes-wc"
description: "A light-DOM custom element for CSS Grid Lanes masonry with a JavaScript fallback."
category: "main"
order: 4
repoUrl: "https://github.com/schalkneethling/masonry-gridlanes-wc"
language: "JavaScript"
stars: 11
technologies: ["JavaScript", "Web Components", "CSS Grid"]
---
10 changes: 10 additions & 0 deletions src/content/projects/ossreleasefeed-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "ossreleasefeed-v2"
description: "Create custom RSS release feeds for GitHub topic repositories or starred projects."
category: "main"
order: 2
repoUrl: "https://github.com/schalkneethling/ossreleasefeed-v2"
language: "TypeScript"
stars: 0
technologies: ["TypeScript", "RSS", "GitHub"]
---
10 changes: 10 additions & 0 deletions src/content/projects/refined-plan-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "refined-plan-mode"
description: "A local web app for reviewing AI coding-agent plans with anchored feedback."
category: "main"
order: 13
repoUrl: "https://github.com/schalkneethling/refined-plan-mode"
language: "TypeScript"
stars: 3
technologies: ["TypeScript", "AI Agents", "Review Tools"]
---
10 changes: 10 additions & 0 deletions src/content/projects/skills-autoresearch-flue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "skills-autoresearch-flue"
description: "A Flue agent harness for autoresearching, evaluating, and improving agent skills."
category: "main"
order: 12
repoUrl: "https://github.com/schalkneethling/skills-autoresearch-flue"
language: "TypeScript"
stars: 12
technologies: ["TypeScript", "Agents", "Evaluation"]
---
10 changes: 10 additions & 0 deletions src/content/projects/web-platform-pulse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "web-platform-pulse"
description: "Keep your finger on the pulse of the web platform."
category: "main"
order: 3
repoUrl: "https://github.com/schalkneethling/web-platform-pulse"
language: "TypeScript"
stars: 0
technologies: ["TypeScript", "Web Platform"]
---
25 changes: 25 additions & 0 deletions src/lib/projectFilters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export type ProjectCategory = "main" | "demo";

type OrderedProject = {
data: {
category: ProjectCategory;
order: number;
};
};

export function sortProjectsByOrder<TProject extends OrderedProject>(
projects: readonly TProject[],
) {
return [...projects].sort((projectA, projectB) => {
return projectA.data.order - projectB.data.order;
});
}

export function getProjectsByCategory<TProject extends OrderedProject>(
projects: readonly TProject[],
category: ProjectCategory,
) {
return sortProjectsByOrder(
projects.filter((project) => project.data.category === category),
);
}
Loading