From e8436106c7695c88a4bb3dabc8db3b6e307fdb44 Mon Sep 17 00:00:00 2001 From: gbanyan Date: Mon, 17 Nov 2025 16:37:48 +0800 Subject: [PATCH] Add project README --- README.md | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..06cd954 --- /dev/null +++ b/README.md @@ -0,0 +1,153 @@ +# Personal Blog (Next.js + Contentlayer) + +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 + +- **Framework**: Next.js 13 (App Router) +- **Language**: TypeScript +- **Styling**: Tailwind CSS + Typography plugin +- **Content**: Markdown via Contentlayer (`contentlayer/source-files`) +- **Theming**: `next-themes` (light / dark mode) +- **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 +- `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) + - `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 + +## Prerequisites + +- Node.js **18+** (recommended by Next.js 13) +- npm (comes with Node) + +## Setup + +1. **Clone the repository** + + ```bash + git clone https://gitea.gbanyan.net/gbanyan/blog-nextjs.git + cd blog-nextjs + ``` + +2. **Initialize the content submodule** + + ```bash + git submodule update --init --recursive + ``` + + This checks out the `content` submodule pointing to `personal-blog`, which contains: + + - `posts/` – posts in markdown + - `pages/` – static pages in markdown + - `assets/` – images used by posts/pages + +3. **Install dependencies** + + ```bash + npm install + ``` + +4. **Configure environment variables** + + Copy the example env file and update it with your personal information: + + ```bash + cp .env.local.example .env.local + ``` + + Then edit `.env.local`: + + ```bash + NEXT_PUBLIC_SITE_NAME="Your Name" + NEXT_PUBLIC_SITE_TITLE="Your Personal Site" + NEXT_PUBLIC_SITE_DESCRIPTION="Personal homepage and blog." + NEXT_PUBLIC_SITE_URL="https://your-domain.example" + NEXT_PUBLIC_SITE_AUTHOR="Your Name" + ``` + + These values are used by `lib/config.ts` to customize: + + - Site title and description + - Default SEO metadata + - Header title + - Footer author name + +5. **Run the development server** + + ```bash + npm run dev + ``` + + Then open in your browser. + +## Content Model + +Contentlayer is configured in `contentlayer.config.ts` to read from the `content` submodule: + +- **Posts** + - Path: `content/posts/**/*.md` + - Type: `Post` + - Important frontmatter fields: + - `title` (string, required) + - `slug` (string, optional – overrides path-based slug) + - `tags` (string list, optional) + - `published_at` (date, optional) + - `description` (string, optional – used as excerpt / meta) + - `feature_image` (string, optional – usually `../assets/xxx.jpg`) + +- **Pages** + - Path: `content/pages/**/*.md` + - Type: `Page` + - Important frontmatter fields: + - `title` (string, required) + - `slug` (string, optional) + - `description` (string, optional) + - `feature_image` (string, optional) + +### Images + +- Markdown uses relative paths like: + + ```markdown + ![](../assets/my-image.jpg) + ``` + +- At build time, a small 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. + +## 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 start` – Start the production server (after `npm run build`). +- `npm run lint` – Run Next.js / ESLint linting. +- `npm run contentlayer` – Manually run `contentlayer build`. + +## Deployment Notes + +- This is a standard Next.js 13 App Router project and can be deployed to: + - Vercel + - 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). + +## License + +This is a personal project. No explicit open-source license is provided; all rights reserved unless otherwise noted. +