From b005f02b7b9992d7d956bcaaefc91520cb35e636 Mon Sep 17 00:00:00 2001 From: gbanyan Date: Tue, 17 Mar 2026 20:42:45 +0800 Subject: [PATCH] fix: use getTagSlug() for tag links to prevent empty tag pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tags containing both spaces and dashes (e.g. "Writings - 創作") produced mismatched slugs: inline generation created "writings---創作" while getTagSlug() collapsed dashes to "writings-創作", causing tag pages to show no articles. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/commands/new-post.md | 17 +++++++++++------ app/blog/[slug]/page.tsx | 6 ++---- app/pages/[slug]/page.tsx | 6 ++---- app/sitemap.ts | 3 ++- next-env.d.ts | 2 +- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.claude/commands/new-post.md b/.claude/commands/new-post.md index fb1ca01..1d8462c 100644 --- a/.claude/commands/new-post.md +++ b/.claude/commands/new-post.md @@ -50,14 +50,19 @@ Ask the user if they want to preview with `npm run dev` before publishing. ## Step 5: Publish -Execute the two-step deployment: +**IMPORTANT**: The `.gitmodules` URL for `content/` points to GitHub. The CI/CD server clones the submodule from that URL, so the content submodule **must be pushed to GitHub first** before pushing the main repo. Otherwise the server will check out stale content and posts will disappear from the site. + +Execute the deployment in order: ```bash -# 1. Commit and push content submodule -git -C content add . && git -C content commit -m "Add new post: " && git -C content push +# 1. Commit content submodule +git -C content add . && git -C content commit -m "Add new post: <title>" -# 2. Update main repo submodule pointer and push (triggers CI/CD) -git add content && git commit -m "Update content submodule" && git push +# 2. Push content submodule to ALL remotes (GitHub first — CI/CD depends on it) +git -C content push github main && git -C content push origin main + +# 3. Update main repo submodule pointer, commit, and push to both remotes +git add content && git commit -m "Update content submodule" && git push origin main && git push github main ``` -Confirm both pushes succeeded. The CI/CD pipeline on git.gbanyan.net will handle deployment automatically (and crontab mirrors to gitea.gbanyan.net). +Confirm all pushes succeeded. The CI/CD pipeline on git.gbanyan.net will handle deployment automatically (and crontab mirrors to gitea.gbanyan.net). diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index 6848b1c..8de2a34 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -3,7 +3,7 @@ import Image from 'next/image'; import { notFound } from 'next/navigation'; import type { Metadata } from 'next'; import { allPosts } from 'contentlayer2/generated'; -import { getPostBySlug, getRelatedPosts, getPostNeighbors } from '@/lib/posts'; +import { getPostBySlug, getRelatedPosts, getPostNeighbors, getTagSlug } from '@/lib/posts'; import { siteConfig } from '@/lib/config'; import { ReadingProgress } from '@/components/reading-progress'; import { ScrollReveal } from '@/components/scroll-reveal'; @@ -217,9 +217,7 @@ export default async function BlogPostPage({ params }: Props) { {post.tags.map((t) => ( <Link key={t} - href={`/tags/${encodeURIComponent( - t.toLowerCase().replace(/\s+/g, '-') - )}`} + href={`/tags/${encodeURIComponent(getTagSlug(t))}`} className="tag-chip rounded-full bg-accent-soft px-3 py-1 text-sm text-accent-textLight dark:bg-slate-800 dark:text-slate-100 dark:hover:bg-slate-700 dark:hover:text-white" > #{t} diff --git a/app/pages/[slug]/page.tsx b/app/pages/[slug]/page.tsx index d45bdfa..40e80fb 100644 --- a/app/pages/[slug]/page.tsx +++ b/app/pages/[slug]/page.tsx @@ -3,7 +3,7 @@ import Image from 'next/image'; import { notFound } from 'next/navigation'; import type { Metadata } from 'next'; import { allPages } from 'contentlayer2/generated'; -import { getPageBySlug } from '@/lib/posts'; +import { getPageBySlug, getTagSlug } from '@/lib/posts'; import { siteConfig } from '@/lib/config'; import { ReadingProgress } from '@/components/reading-progress'; import { PostLayout } from '@/components/post-layout'; @@ -130,9 +130,7 @@ export default async function StaticPage({ params }: Props) { {page.tags.map((t) => ( <Link key={t} - href={`/tags/${encodeURIComponent( - t.toLowerCase().replace(/\s+/g, '-') - )}`} + href={`/tags/${encodeURIComponent(getTagSlug(t))}`} className="tag-chip rounded-full bg-accent-soft px-3 py-1 text-sm text-accent-textLight dark:bg-slate-800 dark:text-slate-100" > #{t} diff --git a/app/sitemap.ts b/app/sitemap.ts index 9f8e0ee..ff93030 100644 --- a/app/sitemap.ts +++ b/app/sitemap.ts @@ -1,5 +1,6 @@ import { MetadataRoute } from 'next'; import { allPosts, allPages } from 'contentlayer2/generated'; +import { getTagSlug } from '@/lib/posts'; export default function sitemap(): MetadataRoute.Sitemap { const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000'; @@ -58,7 +59,7 @@ export default function sitemap(): MetadataRoute.Sitemap { ); const tagPages = allTags.map((tag) => ({ - url: `${siteUrl}/tags/${encodeURIComponent(tag.toLowerCase().replace(/\s+/g, '-'))}`, + url: `${siteUrl}/tags/${encodeURIComponent(getTagSlug(tag))}`, lastModified: new Date(), changeFrequency: 'weekly' as const, priority: 0.5, diff --git a/next-env.d.ts b/next-env.d.ts index c4b7818..9edff1c 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// <reference types="next" /> /// <reference types="next/image-types/global" /> -import "./.next/dev/types/routes.d.ts"; +import "./.next/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.