Refresh README to match current layout, color system, and content submodule workflow

This commit is contained in:
2025-11-18 02:04:43 +08:00
parent 00b45950a4
commit 0df0a85579

164
README.md
View File

@@ -9,29 +9,77 @@ Markdown content (posts & pages) lives in a separate repository and is consumed
- **Language**: TypeScript - **Language**: TypeScript
- **Styling**: Tailwind CSS + Typography plugin - **Styling**: Tailwind CSS + Typography plugin
- **Content**: Markdown via Contentlayer (`contentlayer/source-files`) - **Content**: Markdown via Contentlayer (`contentlayer/source-files`)
- **Theming**: `next-themes` (light / dark mode) - **Theming**: `next-themes` (light/dark), envdriven accent color system
- **Content source**: Git submodule `content` → [`personal-blog`](https://gitea.gbanyan.net/gbanyan/personal-blog.git) - **Content source**: Git submodule `content` → [`personal-blog`](https://gitea.gbanyan.net/gbanyan/personal-blog.git)
## Project Structure ## Project Structure
- `app/` Next.js App Router pages - `app/` Next.js App Router
- `app/page.tsx` Home page - `app/page.tsx` Home page (latest posts list)
- `app/blog/` Blog index and individual post pages - `app/blog/page.tsx` Blog index with sort + pagination
- `app/pages/` Static pages (e.g. 關於作者) - `app/blog/[slug]/page.tsx` Single blog post (TOC + reading progress)
- `components/` Layout shell, header, footer, MDX/markdown components, theme toggle - `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, backtotop)
- `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` Scrollsynced 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/` - `lib/`
- `config.ts` Site configuration derived from environment variables - `config.ts` Site configuration derived from env (name, URLs, avatar, accent colors, etc.)
- `posts.ts` Helpers for querying posts & pages from Contentlayer - `posts.ts` Helpers for querying posts/pages and tags from Contentlayer
- `content/` **Git submodule** pointing to `personal-blog` (markdown content) - `content/` **Git submodule** pointing to `personal-blog`
- `posts/` Blog posts (`.md`) - `posts/` Blog posts (`.md`)
- `pages/` Static pages (`.md`) - `pages/` Static pages (`.md`)
- `assets/` Images referenced from markdown - `assets/` Images referenced from markdown
- `public/assets` Symlink to `content/assets` for serving images at `/assets/...` - `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 icononly 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 darkmode 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 ## Prerequisites
- Node.js **18+** (recommended by Next.js 13) - Node.js **18+**
- npm (comes with Node) - npm (comes with Node)
## Setup ## Setup
@@ -69,22 +117,47 @@ Markdown content (posts & pages) lives in a separate repository and is consumed
cp .env.local.example .env.local cp .env.local.example .env.local
``` ```
Then edit `.env.local`: Then edit `.env.local` (examples):
```bash ```bash
NEXT_PUBLIC_SITE_NAME="Your Name" # Core site info
NEXT_PUBLIC_SITE_TITLE="Your Personal Site" NEXT_PUBLIC_SITE_NAME="Gbanyan"
NEXT_PUBLIC_SITE_DESCRIPTION="Personal homepage and blog." NEXT_PUBLIC_SITE_TITLE="Gbanyan 的個人網站"
NEXT_PUBLIC_SITE_DESCRIPTION="醫學、科技與生活隨筆。"
NEXT_PUBLIC_SITE_URL="https://your-domain.example" 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/<your_md5_hash>?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 - To compute the Gravatar hash locally (without exposing your email):
- Default SEO metadata
- Header title ```bash
- Footer author name 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** 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) ![](../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. - `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. - `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 ## Available npm Scripts
- `npm run dev` Start Next.js dev server with Contentlayer integration. - `npm run dev` Start Next.js dev server (Contentlayer is integrated via `next-contentlayer`).
- `npm run build` Run `contentlayer build` and then `next build` for production. - `npm run build` Run `next build` for production.
- `npm run start` Start the production server (after `npm run build`). - `npm run start` Start the production server (after `npm run build`).
- `npm run lint` Run Next.js / ESLint linting. - `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 ## 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` - Any Node.js host running `npm run build && npm run start`
- Make sure to: - Make sure to:
- Provide the same environment variables in your hosting environment as in `.env.local`. - 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 ## License
This is a personal project. No explicit open-source license is provided; all rights reserved unless otherwise noted. This is a personal project. No explicit open-source license is provided; all rights reserved unless otherwise noted.