Add new post and update CLAUDE.md with deployment docs
- New post: 不是所有眼淚,都該被濃縮成重點 - CLAUDE.md: add deployment workflow and content submodule instructions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
79
CLAUDE.md
79
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.
|
||||
|
||||
2
content
2
content
Submodule content updated: 3f72ccb628...cbde394ac2
Reference in New Issue
Block a user