From 9c7f2463aad235d446cae6a0b5e06cb86579bbb8 Mon Sep 17 00:00:00 2001 From: gbanyan Date: Fri, 6 Feb 2026 12:50:36 +0800 Subject: [PATCH] Add new post and update CLAUDE.md with deployment docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New post: 不是所有眼淚,都該被濃縮成重點 - CLAUDE.md: add deployment workflow and content submodule instructions Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 79 +++++++++++++++++++++++++++++++++++++++++++++---------- content | 2 +- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 46d6805..2a74da3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,20 +1,71 @@ -# blog-nextjs +# CLAUDE.md -Personal blog built with Next.js 16 (App Router), Contentlayer2, and Tailwind CSS. +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands -- `npm run dev` - Start dev server (Turbopack + Contentlayer2) -- `npm run build` - Full build (sync-assets → contentlayer2 → next build → pagefind) -- `npm run sync-assets` - Sync content assets to public/ + +- `npm run dev` - Start dev server (runs Contentlayer2 + Next.js with Turbopack concurrently) +- `npm run build` - Full production build: sync-assets → contentlayer2 build → next build → pagefind indexing → copy pagefind to public +- `npm run lint` - ESLint via `next lint` +- `npm run sync-assets` - Copy `content/assets/` to `public/assets/` (also runs automatically before build) + +No test framework is configured. ## Architecture -- `app/` - Next.js App Router pages -- `content/` - Git submodule with MDX posts and pages -- `components/` - React components -- Contentlayer2 processes MDX from `content/` directory -- Pagefind provides client-side search -## Conventions -- TypeScript strict mode -- Tailwind for styling -- MDX for blog content +**Content pipeline**: `content/` git submodule (MDX/Markdown) → Contentlayer2 (`contentlayer.config.ts`) → typed `Post`/`Page` objects imported from `contentlayer2/generated` → consumed by pages and `lib/posts.ts` helpers. + +**Routing** (App Router): +- `/` — Home page with latest posts +- `/blog` — Blog index with search, sort, pagination +- `/blog/[slug]` — Single post with TOC, reading progress, prev/next navigation +- `/pages/[slug]` — Static content pages (from `content/pages/`) +- `/tags`, `/tags/[tag]` — Tag index and per-tag post lists +- `/api/og` — Dynamic OG image generation (`@vercel/og`) +- `/feed.xml` — RSS feed (route handler) + +**Key data flow**: +- `lib/config.ts` — `siteConfig` object built from `NEXT_PUBLIC_*` env vars (all site metadata, social links, accent colors, pagination) +- `lib/posts.ts` — Query helpers: `getAllPostsSorted()`, `getPostBySlug()`, `getPageBySlug()`, `getAllTagsWithCount()`, `getRelatedPosts()`, `getPostNeighbors()` +- `lib/mastodon.ts` — Mastodon API client for sidebar feed widget +- `lib/rehype-callouts.ts` — Custom rehype plugin for GitHub-style `[!NOTE]` callout blocks + +**Layout hierarchy**: `app/layout.tsx` (fonts, theme CSS vars, ThemeProvider, JSON-LD) → `components/layout-shell.tsx` (header, sidebar, footer, back-to-top) → page content. + +**Markdown processing** (configured in `contentlayer.config.ts`): +- Remark: GFM +- Rehype: callouts → pretty-code (shiki, dual theme) → slug → autolink-headings → image path rewriter (`../assets/` → `/assets/`) +- Image paths in markdown are relative (`../assets/foo.jpg`); a rehype plugin rewrites them to `/assets/foo.jpg` at build time + +## Styling + +- Tailwind CSS v3 with `darkMode: 'class'` (toggled by `next-themes`) +- Accent color system via CSS variables set in `app/layout.tsx` from env vars: `--color-accent`, `--color-accent-soft`, `--color-accent-text-light`, `--color-accent-text-dark` +- Tailwind extends these as `accent`, `accent-soft`, `accent-textLight`, `accent-textDark` in `tailwind.config.cjs` +- Typography plugin (`@tailwindcss/typography`) with custom `prose` / `prose-dark` overrides +- English headings use Playfair Display serif (`--font-serif-eng`); body uses Inter + CJK fallback stack +- Config files use CommonJS (`.cjs`): `tailwind.config.cjs`, `postcss.config.cjs` + +## Content Submodule + +The `content/` directory is a git submodule pointing to a separate `personal-blog` repository. It contains `posts/`, `pages/`, and `assets/`. After pulling new content, run `npm run sync-assets` to update `public/assets/`. The build script does this automatically. + +## Path Aliases + +`@/*` maps to project root (configured in `tsconfig.json`). Contentlayer generated types at `.contentlayer/generated` are aliased as `contentlayer2/generated`. + +## Deployment + +Push to `main` on the Gitea remote (`git.gbanyan.net`) triggers CI/CD automatically (server-side hook). No Dockerfile or workflow file in this repo. + +**Content-only update** (new/edited posts) — both steps are required to trigger deploy: +1. Commit and push inside `content/` submodule: `git -C content add . && git -C content commit -m "..." && git -C content push` +2. Update main repo submodule pointer and push: `git add content && git commit -m "Update content submodule" && git push` + +Pushing only to `content/` (personal-blog) does NOT trigger deployment. The main repo must also be pushed because CI/CD is bound to `blog-nextjs`, not `personal-blog`. + +**Code changes**: Commit and push in the main repo as usual — `git push` to `main` triggers the pipeline. + +## Language + +The site's default locale is `zh-TW`. UI text, labels, and timestamps are in Traditional Chinese. diff --git a/content b/content index 3f72ccb..cbde394 160000 --- a/content +++ b/content @@ -1 +1 @@ -Subproject commit 3f72ccb628f0563453ab61789b4d0baa2c446ce1 +Subproject commit cbde394ac23d80d50dea0ea78649af49f5e41edc