Skip to content

Commit 17dd130

Browse files
just-be-devclaudegithub-actions[bot]
authored
Restructure URL paths (#136)
* Restructure URLs to use separate code and slug segments Change URL format from `/blog/b24f9--the-values-i-build-by/` to `/blog/b24f9/the-values-i-build-by/` for cleaner, more semantic URLs. - Add Code.parseId() and Code.buildUrl() utility functions - Restructure routes from [slug].astro to [code]/[slug].astro - Update all index pages and components to generate new URL format - Update middleware to handle new URL structure and redirects - Add support for talks in middleware (was missing) * Extract repeated getStaticPaths pattern into Code.getStaticPaths() helper Add Code.getStaticPaths() static method to reduce duplication across route files. Previously each route file had ~9 lines of boilerplate to map collection entries to params/props. Now it's just 3 lines using the helper. Updated files: - src/utils/code.ts: Added Code.getStaticPaths() helper method - src/pages/talks/[code]/[slug].astro: Use helper - src/pages/blog/[code]/[slug].astro: Use helper - src/pages/projects/[code]/[slug].astro: Use helper - src/pages/research/[code]/[slug].astro: Use helper Co-authored-by: Justin Bennett <just-be-dev@users.noreply.github.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Justin Bennett <just-be-dev@users.noreply.github.com>
1 parent 321dbbb commit 17dd130

11 files changed

Lines changed: 109 additions & 30 deletions

File tree

src/components/LatestPosts.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const latestPosts = (await getCollection("blog", ({ data }) => !data.draft))
2424
return (
2525
<li class="contents before:content-none">
2626
<a
27-
href={`/blog/${post.id}/`}
27+
href={Code.buildUrl("blog", post.id)}
2828
class="bg-0 hocus:invert group col-span-3 -mx-[1ch] grid grid-cols-subgrid outline-none"
2929
>
3030
<code class="text-fg-2 group-hocus:text-accent">{post.code.toString()}</code>

src/middleware.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { defineMiddleware } from "astro:middleware";
22
import { getCollection } from "astro:content";
3+
import { Code } from "@/utils/code";
34

45
export const onRequest = defineMiddleware(async (context, next) => {
56
const url = new URL(context.request.url);
67

7-
// Handle /blog/*, /projects/*, and /research/* paths
8-
const match = url.pathname.match(/^\/(blog|projects|research)\//);
9-
const matchedType = match?.[1] as "blog" | "projects" | "research" | undefined;
8+
// Handle /blog/*, /projects/*, /research/*, and /talks/* paths
9+
const match = url.pathname.match(/^\/(blog|projects|research|talks)\//);
10+
const matchedType = match?.[1] as "blog" | "projects" | "research" | "talks" | undefined;
1011

1112
if (!matchedType) {
1213
return next();
@@ -17,19 +18,28 @@ export const onRequest = defineMiddleware(async (context, next) => {
1718
return next();
1819
}
1920

20-
const slug = parts[1];
21+
// Extract the code from the URL (first segment after collection name)
22+
const urlCode = parts[1];
23+
24+
// Find the entry by matching the code (first 5 characters of the ID)
2125
const entry = (
2226
await getCollection(matchedType, ({ id }) => {
23-
return slug.slice(0, 5).toLowerCase() === id.slice(0, 5).toLowerCase();
27+
return urlCode.slice(0, 5).toLowerCase() === id.slice(0, 5).toLowerCase();
2428
})
2529
).at(0);
2630

2731
if (entry) {
28-
// We're going to the right page, continue
29-
if (context.props.id === entry.id) return next();
30-
// Redirect to the full ID
32+
const { code, slug } = Code.parseId(entry.id);
33+
const correctPath = `/${matchedType}/${code}/${slug}/`;
34+
35+
// Check if we're already on the correct path
36+
if (url.pathname === correctPath) {
37+
return next();
38+
}
39+
40+
// Redirect to the correct URL format
3141
const newUrl = new URL(url);
32-
newUrl.pathname = `/${matchedType}/${entry.id}/`;
42+
newUrl.pathname = correctPath;
3343
return context.redirect(newUrl.toString());
3444
}
3545

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ import { Code } from "@/utils/code";
99
1010
export async function getStaticPaths() {
1111
const posts = await getCollection("blog");
12-
return posts.map((post) => ({
13-
params: { slug: post.id },
14-
props: post,
15-
}));
12+
return Code.getStaticPaths(posts);
1613
}
1714
1815
type Props = Awaited<ReturnType<typeof getStaticPaths>>[number]["props"];

src/pages/blog/index.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const sortedTags = Array.from(tagCounts.entries())
6363
return (
6464
<li class="contents before:content-none">
6565
<a
66-
href={`/blog/${post.id}/`}
66+
href={Code.buildUrl("blog", post.id)}
6767
class="bg-0 hocus:invert group col-span-3 -mx-[1ch] grid grid-cols-subgrid px-[1ch] outline-none"
6868
>
6969
<code class="text-fg-2 group-hocus:text-accent">{post.code.toString()}</code>
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ import { Code } from "@/utils/code";
99
1010
export async function getStaticPaths() {
1111
const projects = await getCollection("projects");
12-
return projects.map((project) => ({
13-
params: { slug: project.id },
14-
props: project,
15-
}));
12+
return Code.getStaticPaths(projects);
1613
}
1714
1815
type Props = Awaited<ReturnType<typeof getStaticPaths>>[number]["props"];

src/pages/projects/index.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const projects = (await getCollection("projects"))
1919
projects.map((project) => (
2020
<li class="contents before:content-none">
2121
<a
22-
href={`/projects/${project.id}/`}
22+
href={Code.buildUrl("projects", project.id)}
2323
class="bg-0 hocus:invert group col-span-3 -mx-[1ch] grid grid-cols-subgrid px-[1ch] outline-none"
2424
>
2525
<code class="text-fg-2 group-hocus:text-accent">{project.code.toString()}</code>
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
import { getCollection, render } from "astro:content";
33
import FormattedDate from "@/components/FormattedDate.astro";
44
import Layout from "@/layouts/Layout.astro";
5+
import { Code } from "@/utils/code";
56
67
export async function getStaticPaths() {
78
const research = await getCollection("research");
8-
return research.map((item) => ({
9-
params: { slug: item.id },
10-
props: item,
11-
}));
9+
return Code.getStaticPaths(research);
1210
}
1311
1412
type Props = Awaited<ReturnType<typeof getStaticPaths>>[number]["props"];

src/pages/rss.xml.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { getCollection } from "astro:content";
22
import rss from "@astrojs/rss";
33
import { SITE_DESCRIPTION, SITE_TITLE } from "@/consts";
4+
import { Code } from "@/utils/code";
45

56
export async function GET(context) {
67
const posts = await getCollection("blog", ({ data }) => !data.draft);
@@ -13,7 +14,7 @@ export async function GET(context) {
1314
title: post.data.title,
1415
pubDate: post.data.date,
1516
description: post.data.description,
16-
link: `/blog/${post.id}/`,
17+
link: Code.buildUrl("blog", post.id),
1718
})),
1819
});
1920
}
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ import { Code } from "@/utils/code";
88
99
export async function getStaticPaths() {
1010
const talks = await getCollection("talks");
11-
return talks.map((talk) => ({
12-
params: { slug: talk.id },
13-
props: talk,
14-
}));
11+
return Code.getStaticPaths(talks);
1512
}
1613
1714
type Props = Awaited<ReturnType<typeof getStaticPaths>>[number]["props"];

src/pages/talks/index.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const talks = (await getCollection("talks"))
2020
return (
2121
<li class="contents before:content-none">
2222
<a
23-
href={`/talks/${talk.id}/`}
23+
href={Code.buildUrl("talks", talk.id)}
2424
class="bg-0 hocus:invert group col-span-3 -mx-[1ch] grid grid-cols-subgrid px-[1ch] outline-none"
2525
>
2626
<code class="text-fg-2 group-hocus:text-accent">{talk.code.toString()}</code>

0 commit comments

Comments
 (0)