diff --git a/src/content.config.ts b/src/content.config.ts
index edcde99..6d24e98 100644
--- a/src/content.config.ts
+++ b/src/content.config.ts
@@ -4,14 +4,11 @@ import { defineCollection, z } from 'astro:content';
import { isValidTime } from './utils/time';
const blog = defineCollection({
- // Load Markdown and MDX files in the `src/content/blog/` directory.
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
- // Type-check frontmatter using a schema
schema: z.object({
title: z.string(),
summary: z.string(),
image: z.string().optional(),
- // Transform string to ZonedDateTime object
pubDate: z.string().refine(isValidTime),
updatedDate: z.string().refine(isValidTime).optional(),
unlisted: z.boolean().optional(),
@@ -20,4 +17,13 @@ const blog = defineCollection({
}),
});
-export const collections = { blog };
+const projects = defineCollection({
+ loader: glob({ base: './src/content/projects', pattern: '**/*.{md,mdx}' }),
+ schema: z.object({
+ name: z.string(),
+ url: z.string(),
+ image: z.string().optional(),
+ })
+})
+
+export const collections = { blog, projects };
diff --git a/src/content/projects/00-orchid.mdx b/src/content/projects/00-orchid.mdx
new file mode 100644
index 0000000..ed9e2c4
--- /dev/null
+++ b/src/content/projects/00-orchid.mdx
@@ -0,0 +1,6 @@
+---
+name: Orchid
+url: https://github.com/lbfalvy/orchid
+image: https://raw.githubusercontent.com/lbfalvy/orchid/refs/heads/master/icon.svg
+---
+An embeddable functional scripting language I've been developing for many years now both as a recreational activity and to learn Rust.
\ No newline at end of file
diff --git a/src/content/projects/10-f.engine.mdx b/src/content/projects/10-f.engine.mdx
new file mode 100644
index 0000000..2deee8c
--- /dev/null
+++ b/src/content/projects/10-f.engine.mdx
@@ -0,0 +1,6 @@
+---
+name: f.engine
+url: https://lbfalvy.github.io/f.engine/
+image: https://assets-for-gh-pages.gb-lon-1.linodeobjects.com/f-engine.png
+---
+A small lambda calculus executor made in Javascript to demonstrate lambda calc to my friends. It works with repeated string splicing so it gets very slow.
\ No newline at end of file
diff --git a/src/content/projects/20-mockable-timer.mdx b/src/content/projects/20-mockable-timer.mdx
new file mode 100644
index 0000000..21129d2
--- /dev/null
+++ b/src/content/projects/20-mockable-timer.mdx
@@ -0,0 +1,5 @@
+---
+name: Mockable Timer
+url: https://github.com/lbfalvy/mockable-timer
+---
+An API that replaces `Date.now()`, `setTimeout` and `setImmediate` for dependency injection, and a carefully crafted mock implementation with an easy to use interface.
\ No newline at end of file
diff --git a/src/content/projects/30-react-context-menu.mdx b/src/content/projects/30-react-context-menu.mdx
new file mode 100644
index 0000000..f7133b1
--- /dev/null
+++ b/src/content/projects/30-react-context-menu.mdx
@@ -0,0 +1,5 @@
+---
+name: React Context Menu
+url: https://www.npmjs.com/package/@lbfalvy/react-context-menu
+---
+A multilevel custom context menu for React. The API relies on React context so that menus can be combined within nested containers
\ No newline at end of file
diff --git a/src/content/projects/40-simple-rtr.mdx b/src/content/projects/40-simple-rtr.mdx
new file mode 100644
index 0000000..3b429a1
--- /dev/null
+++ b/src/content/projects/40-simple-rtr.mdx
@@ -0,0 +1,5 @@
+---
+name: Simple RTR
+url: https://github.com/lbfalvy/buffered-dispatch
+---
+A library for Refresh Token Rotation that can scale to many concurrent open tabs without a service worker.
\ No newline at end of file
diff --git a/src/pages/projects.astro b/src/pages/projects.astro
index cbcc749..bc35295 100644
--- a/src/pages/projects.astro
+++ b/src/pages/projects.astro
@@ -1,7 +1,34 @@
---
+import { getCollection, render } from "astro:content";
import Main from "../layouts/Main.astro";
+
+const projects = await getCollection("projects");
+const projReady = await Promise.all(
+ projects.map(async (proj) => [proj, (await render(proj)).Content] as const),
+);
---