From ae6d191b914ccefcf941a15a8831b8d119a48598 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath <2+defunkt@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:21:48 -0700 Subject: [PATCH] project urls --- packages/cubby/src/components/Project.tsx | 13 +++++++-- packages/cubby/src/server.tsx | 34 +++++++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/packages/cubby/src/components/Project.tsx b/packages/cubby/src/components/Project.tsx index dc93d2b..a983c67 100644 --- a/packages/cubby/src/components/Project.tsx +++ b/packages/cubby/src/components/Project.tsx @@ -1,12 +1,14 @@ import { marked } from "marked" +import { type ProjectMetadata } from "../server" interface ProjectProps { - name: string + project: ProjectMetadata readme: string files: string[] } -export function Project({ name, readme, files }: ProjectProps) { +export function Project({ project, readme, files }: ProjectProps) { + const name = project.name return ( <>

« Back

@@ -15,6 +17,13 @@ export function Project({ name, readme, files }: ProjectProps) {

+

Links

+ {files.length > 0 && ( <>

Files

diff --git a/packages/cubby/src/server.tsx b/packages/cubby/src/server.tsx index f930239..378940b 100644 --- a/packages/cubby/src/server.tsx +++ b/packages/cubby/src/server.tsx @@ -9,10 +9,19 @@ import { Layout } from "./components/Layout" import { Project } from "./components/Project" import { Projects } from "./components/Projects" -const PROJECTS_DIR = ".." -const WORKSHOP_REPO = "https://github.com/probablycorey/the-workshop" +export const REPO_URL = "https://github.com/probablycorey/the-workshop" +export const PROJECTS_DIR = ".." +const WORKSHOP_APP_DOMAIN = "theworkshop.cc" const CUBBY_DIR = "./cubby" +export type ProjectMetadata = { + name: string + mtime: Date + status: "recent" | "active" | "inactive", + github: string, + url: string | null, +} + // ---------------------------------------------------------------------------- // Setup // ---------------------------------------------------------------------------- @@ -51,6 +60,9 @@ app.get("/", async (c) => { app.get("/p/:name", async (c) => { const name = c.req.param("name").replace("..", "") + const project = await projectsWithMetadata().then(projects => projects.find(p => p.name === name)) + if (!project) return c.json({ error: 'Project not found' }, 404) + const readme = await Bun.file(`${PROJECTS_DIR}/${name}/README.md`).text() const cubbyPath = join(CUBBY_DIR, `project_${name}`) let files: string[] = [] @@ -63,7 +75,7 @@ app.get("/p/:name", async (c) => { } } - return c.html(tsx()) + return c.html(tsx()) }) app.get('/p/:id/:filename', async c => { @@ -133,6 +145,22 @@ async function projects(): Promise { return subdirs } +async function projectsWithMetadata(): Promise { + const projects = await projectsWithDates() + return Promise.all(projects.map(async project => ({ + name: project.name, + mtime: project.mtime, + status: project.status, + github: `${REPO_URL}/tree/main/packages/${project.name}`, + url: await isWorkshopApp(project.name) ? `https://${project.name}.${WORKSHOP_APP_DOMAIN}` : null, + }))) +} + +async function isWorkshopApp(projectName: string): Promise { + const json = await Bun.file(`${PROJECTS_DIR}/${projectName}/package.json`).json() + return json.scripts && json.scripts["subdomain:start"] !== undefined +} + async function projectsWithDates(): Promise<{ name: string, mtime: Date, status: "recent" | "active" | "inactive" }[]> { const names = await projects() const projectsWithDates = await Promise.all(names.map(async name => {