From 0df0a8557934f6827f1bcdf7222f9e7d693e9a0f Mon Sep 17 00:00:00 2001 From: gbanyan Date: Tue, 18 Nov 2025 02:04:43 +0800 Subject: [PATCH] Refresh README to match current layout, color system, and content submodule workflow --- README.md | 166 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 138 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 06cd954..8276d5d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Personal Blog (Next.js + Contentlayer) -This is a personal blog built with **Next.js 13 (App Router)**, **Contentlayer**, and **Tailwind CSS**. +This is a personal blog built with **Next.js 13 (App Router)**, **Contentlayer**, and **Tailwind CSS**. Markdown content (posts & pages) lives in a separate repository and is consumed via a git submodule. ## Tech Stack @@ -9,29 +9,77 @@ Markdown content (posts & pages) lives in a separate repository and is consumed - **Language**: TypeScript - **Styling**: Tailwind CSS + Typography plugin - **Content**: Markdown via Contentlayer (`contentlayer/source-files`) -- **Theming**: `next-themes` (light / dark mode) +- **Theming**: `next-themes` (light/dark), env‑driven accent color system - **Content source**: Git submodule `content` → [`personal-blog`](https://gitea.gbanyan.net/gbanyan/personal-blog.git) ## Project Structure -- `app/` – Next.js App Router pages - - `app/page.tsx` – Home page - - `app/blog/` – Blog index and individual post pages - - `app/pages/` – Static pages (e.g. 關於作者) -- `components/` – Layout shell, header, footer, MDX/markdown components, theme toggle +- `app/` – Next.js App Router + - `app/page.tsx` – Home page (latest posts list) + - `app/blog/page.tsx` – Blog index with sort + pagination + - `app/blog/[slug]/page.tsx` – Single blog post (TOC + reading progress) + - `app/pages/[slug]/page.tsx` – Static content pages (e.g. 關於作者) + - `app/tags/page.tsx` – Tag index (all tags) + - `app/tags/[tag]/page.tsx` – Tag overview (posts for a given tag) +- `components/` + - `layout-shell.tsx` – Global layout (header, sidebar, footer, back‑to‑top) + - `site-header.tsx` – Navbar (title + Blog + pages from contentlayer) + - `right-sidebar.tsx` – Sticky sidebar (avatar, services icons, short about, hot tags) + - `post-list-item.tsx` – Article list row with thumbnail, tags, excerpt + - `post-list-with-controls.tsx` – List with sort + pagination controls + - `post-toc.tsx` – Scroll‑synced table of contents + - `reading-progress.tsx` – Top reading progress bar + - `theme-toggle.tsx` – Sun/moon theme toggle + - `hero.tsx` – (currently unused) hero section using accent colors - `lib/` - - `config.ts` – Site configuration derived from environment variables - - `posts.ts` – Helpers for querying posts & pages from Contentlayer -- `content/` – **Git submodule** pointing to `personal-blog` (markdown content) + - `config.ts` – Site configuration derived from env (name, URLs, avatar, accent colors, etc.) + - `posts.ts` – Helpers for querying posts/pages and tags from Contentlayer +- `content/` – **Git submodule** pointing to `personal-blog` - `posts/` – Blog posts (`.md`) - `pages/` – Static pages (`.md`) - `assets/` – Images referenced from markdown - `public/assets` – Symlink to `content/assets` for serving images at `/assets/...` -- `contentlayer.config.ts` – Contentlayer document type definitions and markdown pipeline +- `contentlayer.config.ts` – Contentlayer document types and markdown pipeline + +## UI Overview + +- **Navbar** + - Left: site title (from env). + - Right: `Blog` + links for each `Page` from Contentlayer (`content/pages`), plus a theme toggle. + - Links use the accent palette on hover/focus. + +- **Home page** (`/`) + - Centered hero heading: `SITE_NAME 的最新動態` + tagline. + - "最新文章" section listing latest posts as cards with thumbnail, date, title, tags, and excerpt. + +- **Blog index** (`/blog`) + - Uses `PostListWithControls`: + - Sort order: new→old or old→new. + - Pagination using `siteConfig.postsPerPage`. + +- **Single post / page** (`/blog/[slug]`, `/pages/[slug]`) + - Left: sticky TOC that highlights the current section as you scroll. + - Top: published date, large title, colored tags. + - Body: `prose` typography with tuned light/dark colors, images, blockquotes, code. + - Top bar: reading progress indicator. + +- **Right sidebar** (on large screens) + - Top hero: + - Gravatar avatar (from env) linking to an "about" page. + - Row of icon‑only service links (GitHub, Mastodon, LinkedIn). + - Short "about me" sentence from env. + - Hot tags: top 5 tags in a small tag cloud using the accent palette and neutral dark‑mode backgrounds. + +- **Tags** + - Each tag chips in lists, post headers, and sidebar link to `/tags/[slug]`. + - `/tags` shows all tags and their counts. + +- **Misc** + - Floating "back to top" button on long pages. ## Prerequisites -- Node.js **18+** (recommended by Next.js 13) +- Node.js **18+** - npm (comes with Node) ## Setup @@ -69,22 +117,47 @@ Markdown content (posts & pages) lives in a separate repository and is consumed cp .env.local.example .env.local ``` - Then edit `.env.local`: + Then edit `.env.local` (examples): ```bash - NEXT_PUBLIC_SITE_NAME="Your Name" - NEXT_PUBLIC_SITE_TITLE="Your Personal Site" - NEXT_PUBLIC_SITE_DESCRIPTION="Personal homepage and blog." + # Core site info + NEXT_PUBLIC_SITE_NAME="Gbanyan" + NEXT_PUBLIC_SITE_TITLE="Gbanyan 的個人網站" + NEXT_PUBLIC_SITE_DESCRIPTION="醫學、科技與生活隨筆。" NEXT_PUBLIC_SITE_URL="https://your-domain.example" - NEXT_PUBLIC_SITE_AUTHOR="Your Name" + NEXT_PUBLIC_SITE_AUTHOR="Gbanyan" + NEXT_PUBLIC_SITE_TAGLINE="醫學、科技與生活的隨筆記錄。" + + # Avatar (Gravatar hash only, no email) + NEXT_PUBLIC_SITE_AVATAR_URL="https://www.gravatar.com/avatar/?s=160&d=identicon" + + # Short "about me" text for right sidebar + NEXT_PUBLIC_SITE_ABOUT_SHORT="醫師,喜歡寫作與技術分享。" + + # Accent color palette + NEXT_PUBLIC_COLOR_ACCENT="#2563eb" + NEXT_PUBLIC_COLOR_ACCENT_SOFT="#dbeafe" + NEXT_PUBLIC_COLOR_ACCENT_TEXT_LIGHT="#1d4ed8" + NEXT_PUBLIC_COLOR_ACCENT_TEXT_DARK="#93c5fd" + + # Social links + NEXT_PUBLIC_TWITTER_HANDLE="@yourhandle" + NEXT_PUBLIC_GITHUB_URL="https://github.com/yourname" + NEXT_PUBLIC_LINKEDIN_URL="https://www.linkedin.com/in/yourname/" + NEXT_PUBLIC_EMAIL_CONTACT="you@example.com" + NEXT_PUBLIC_MASTODON_URL="https://your.instance/@yourhandle" + NEXT_PUBLIC_GITEA_URL="https://gitea.example/yourname" ``` - These values are used by `lib/config.ts` to customize: + Notes: - - Site title and description - - Default SEO metadata - - Header title - - Footer author name + - To compute the Gravatar hash locally (without exposing your email): + + ```bash + echo -n 'your-email@example.com' | md5 # macOS + # or + echo -n 'your-email@example.com' | md5sum | cut -d' ' -f1 # Linux + ``` 5. **Run the development server** @@ -126,17 +199,55 @@ Contentlayer is configured in `contentlayer.config.ts` to read from the `content ![](../assets/my-image.jpg) ``` -- At build time, a small rehype plugin rewrites these to `/assets/my-image.jpg`. +- At build time, a rehype plugin rewrites these to `/assets/my-image.jpg`. - `public/assets` is a symlink to `content/assets`, so Next.js serves them as static files. - `feature_image` fields are also mapped from `../assets/...` → `/assets/...` and rendered above the article content. +## Updating Content from the Submodule + +Content is maintained in the `personal-blog` repo and pulled in via the `content` submodule. + +### Pull new content locally + +From the root of this project: + +```bash +# Option 1: generic update +cd content +git pull +cd .. + +# Option 2: one-liner from root +git -C content pull +``` + +Then update the parent repo to point to the new submodule commit: + +```bash +git add content +git commit -m "Update content submodule to latest main" +git push +``` + +Next.js + Contentlayer will pick up the changes automatically on the next `npm run dev` or `npm run build`. + +### Cloning with submodule updates + +On a fresh clone where the submodule has moved, run: + +```bash +git submodule update --init --recursive +``` + +This ensures your `content` folder matches the commit referenced in `blog-nextjs`. + ## Available npm Scripts -- `npm run dev` – Start Next.js dev server with Contentlayer integration. -- `npm run build` – Run `contentlayer build` and then `next build` for production. +- `npm run dev` – Start Next.js dev server (Contentlayer is integrated via `next-contentlayer`). +- `npm run build` – Run `next build` for production. - `npm run start` – Start the production server (after `npm run build`). - `npm run lint` – Run Next.js / ESLint linting. -- `npm run contentlayer` – Manually run `contentlayer build`. +- `npm run contentlayer` – Manually run `contentlayer build` (optional). ## Deployment Notes @@ -145,9 +256,8 @@ Contentlayer is configured in `contentlayer.config.ts` to read from the `content - Any Node.js host running `npm run build && npm run start` - Make sure to: - Provide the same environment variables in your hosting environment as in `.env.local`. - - Initialize the `content` submodule in your deployment pipeline (or vendor the generated `.contentlayer` output if needed). + - Initialize/update the `content` submodule in your deployment pipeline (or vendor `.contentlayer` if you prefer). ## License This is a personal project. No explicit open-source license is provided; all rights reserved unless otherwise noted. -