diff options
| author | Bertrand Yuan <me@bertyuan.com> | 2026-04-27 20:52:54 +0800 |
|---|---|---|
| committer | Bertrand Yuan <me@bertyuan.com> | 2026-04-27 20:53:14 +0800 |
| commit | dbb5e791f0c228369605d126dd590962ebe1eddc (patch) | |
| tree | 8c83fc84bd9547630e6733929dec77e102e055a8 | |
| parent | 658798b3a2378bb6df16cfbb16d707c6fb719e1e (diff) | |
docs: add comprehensive documentation for operations
This commit introduces a complete set of documentation files
covering various aspects of the project, including environment
setup, quality checks, command references, and architecture.
The documentation is structured to assist developers and
contributors in understanding the project's configuration,
workflow, and best practices.
Additionally, translations for Simplified and Traditional
Chinese have been added to ensure accessibility for a wider
audience. This enhances the overall usability and
maintainability of the project.
Signed-off-by: Bertrand Yuan <github@bertyuan.com>
58 files changed, 2887 insertions, 0 deletions
@@ -48,6 +48,9 @@ next-env.d.ts .source next-env.d.ts +# sphinx documentation build output +/Documentation/build/ + # next-sitemap /public/robots.txt /public/sitemap*.xml diff --git a/Documentation/Makefile b/Documentation/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/Documentation/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/Documentation/make.bat b/Documentation/make.bat new file mode 100644 index 0000000..747ffb7 --- /dev/null +++ b/Documentation/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.https://www.sphinx-doc.org/
+ exit /b 1
+)
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/Documentation/source/_static/language-switcher.css b/Documentation/source/_static/language-switcher.css new file mode 100644 index 0000000..1540910 --- /dev/null +++ b/Documentation/source/_static/language-switcher.css @@ -0,0 +1,48 @@ +div.admonition { + clear: both; +} + +div.language-selection { + background: #eeeeee; + border: 1px solid #cccccc; + float: right; + margin-bottom: 1em; + padding: 0.5em; + position: relative; +} + +div.language-selection:focus { + outline: 2px solid #4477aa; + outline-offset: 2px; +} + +div.language-selection a { + color: #333333; + display: block; + padding: 0.5em; + text-decoration: none; +} + +div.language-selection ul { + background: #fafafa; + border: 1px solid #cccccc; + display: none; + list-style: none; + margin: 0; + padding: 0; + position: absolute; + right: 0; + top: 100%; + white-space: nowrap; + z-index: 10; +} + +div.language-selection:hover ul, +div.language-selection:focus-within ul { + display: block; +} + +div.language-selection ul li:hover, +div.language-selection ul li:focus-within { + background: #dddddd; +} diff --git a/Documentation/source/_templates/layout.html b/Documentation/source/_templates/layout.html new file mode 100644 index 0000000..1f5ee78 --- /dev/null +++ b/Documentation/source/_templates/layout.html @@ -0,0 +1,106 @@ +{% extends "!layout.html" %} + +{% macro language_href(lang, section) -%} + {%- if lang == "en" -%} + {%- if section == "index" -%}{{ pathto('index') }} + {%- elif section == "introduction" -%}{{ pathto('introduction') }} + {%- elif section == "getting-started" -%}{{ pathto('getting-started') }} + {%- elif section == "architecture" -%}{{ pathto('architecture/index') }} + {%- elif section == "frontend" -%}{{ pathto('frontend/index') }} + {%- elif section == "operations" -%}{{ pathto('operations/index') }} + {%- elif section == "contributing" -%}{{ pathto('contributing/index') }} + {%- elif section == "reference" -%}{{ pathto('reference/index') }} + {%- endif -%} + {%- elif lang == "zh_CN" -%} + {%- if section == "index" -%}{{ pathto('zh_CN/index') }} + {%- else -%}{{ pathto('zh_CN/' ~ section) }} + {%- endif -%} + {%- elif lang == "zh_TW" -%} + {%- if section == "index" -%}{{ pathto('zh_TW/index') }} + {%- else -%}{{ pathto('zh_TW/' ~ section) }} + {%- endif -%} + {%- elif lang == "ja" -%} + {%- if section == "index" -%}{{ pathto('ja/index') }} + {%- else -%}{{ pathto('ja/' ~ section) }} + {%- endif -%} + {%- endif -%} +{%- endmacro %} + +{% macro language_selection() %} + {% if pagename.startswith("zh_CN/") %} + {% set current_language = "简体中文" %} + {% set normalized = pagename[6:] %} + {% elif pagename.startswith("zh_TW/") %} + {% set current_language = "繁體中文" %} + {% set normalized = pagename[6:] %} + {% elif pagename.startswith("ja/") %} + {% set current_language = "日本語" %} + {% set normalized = pagename[3:] %} + {% else %} + {% set current_language = "English" %} + {% set normalized = pagename %} + {% endif %} + + {% if normalized == "index" %} + {% set section = "index" %} + {% elif normalized == "introduction" %} + {% set section = "introduction" %} + {% elif normalized == "getting-started" %} + {% set section = "getting-started" %} + {% elif normalized.startswith("architecture") %} + {% set section = "architecture" %} + {% elif normalized.startswith("frontend") %} + {% set section = "frontend" %} + {% elif normalized.startswith("operations") %} + {% set section = "operations" %} + {% elif normalized.startswith("contributing") %} + {% set section = "contributing" %} + {% elif normalized.startswith("reference") %} + {% set section = "reference" %} + {% else %} + {% set section = "index" %} + {% endif %} + + <div class="language-selection" tabindex="0" aria-label="Select language"> + {{ current_language }} + <ul> + <li><a href="{{ language_href('en', section)|e }}">English</a></li> + <li><a href="{{ language_href('zh_CN', section)|e }}">简体中文</a></li> + <li><a href="{{ language_href('zh_TW', section)|e }}">繁體中文</a></li> + <li><a href="{{ language_href('ja', section)|e }}">日本語</a></li> + </ul> + </div> +{% endmacro %} + +{% block document %} + <div class="documentwrapper"> + {%- if render_sidebar %} + <div class="bodywrapper"> + {%- endif %} + + {%- block relbar_top %} + {%- if theme_show_relbar_top|tobool %} + <div class="related top"> + + </div> + {%- endif %} + {% endblock %} + + <div class="body" role="main"> + {{ language_selection() }} + {% block body %} {% endblock %} + </div> + + {%- block relbar_bottom %} + {%- if theme_show_relbar_bottom|tobool %} + <div class="related bottom"> + + </div> + {%- endif %} + {% endblock %} + + {%- if render_sidebar %} + </div> + {%- endif %} + </div> +{% endblock %} diff --git a/Documentation/source/architecture/content-model.rst b/Documentation/source/architecture/content-model.rst new file mode 100644 index 0000000..12ed092 --- /dev/null +++ b/Documentation/source/architecture/content-model.rst @@ -0,0 +1,65 @@ +Content Model +============= + +Payload CMS is configured in ``payload.config.ts`` and collection definitions +live under ``src/payload/collections``. + +Collections +----------- + +.. list-table:: + :header-rows: 1 + :widths: 18 58 + + * - Collection + - Purpose + * - ``Posts`` + - Blog entries with slug, summary, rich text body, status, tags, + publication time, author, and optional featured image. + * - ``Users`` + - Admin users for Payload and shared user representation. + * - ``Media`` + - Uploaded images and assets used by posts and the admin. + +Post Lifecycle +-------------- + +Posts are authored in Payload and exposed publicly only when their status is +``published``. Public queries in ``src/lib/payload-posts.ts`` consistently +filter on this status before returning data to pages, feeds, search, or tag +views. + +The normalized frontend shape is ``BlogPost``. It includes: + +* ``id`` and ``slug`` for stable identity; +* ``url`` for public route generation; +* ``title`` and ``description`` for listing and metadata; +* ``content`` for Lexical rich text rendering; +* ``image`` for cover or preview assets; +* ``author`` and dates for byline display; +* ``tags`` for topic navigation. + +Tag Strategy +------------ + +Tags are currently embedded in post documents and counted in memory by +``getAllTags``. This is simple and sufficient for a small blog. If content +volume grows, tag aggregation should move closer to the database or a cached +index. + +MDX Content +----------- + +The ``content`` directory is processed by Fumadocs through ``source.config.ts``. +Its frontmatter includes date, author, tags, and optional image fields. Treat +MDX content as local authored pages, distinct from Payload-managed posts. + +Generated Types +--------------- + +Payload writes generated TypeScript types to ``payload-types.ts``. Regenerate +them after collection schema changes: + +.. code-block:: bash + + pnpm payload:generate diff --git a/Documentation/source/architecture/data-and-auth.rst b/Documentation/source/architecture/data-and-auth.rst new file mode 100644 index 0000000..44736bd --- /dev/null +++ b/Documentation/source/architecture/data-and-auth.rst @@ -0,0 +1,72 @@ +Data, Auth, and Comments +======================== + +Database Ownership +------------------ + +The repository uses PostgreSQL for both CMS data and application-owned data. +The separation is logical: + +* Payload stores CMS data in the ``payload`` schema. +* Application auth and comments use Drizzle schema objects and ``blog_*`` + tables. + +This keeps CMS-managed structures separate from reader interaction data and +allows application migrations to evolve without coupling every change to +Payload internals. + +Authentication +-------------- + +Authentication is configured in ``src/server/auth/index.ts`` with better-auth +and the Drizzle adapter. Current providers: + +* Google OAuth; +* GitHub OAuth. + +The user model includes an additional ``role`` field with a default value of +``user``. Session lookup is wrapped by ``getSession`` so route and component +code does not need to call the better-auth API directly. + +Comments +-------- + +Comments are configured in ``src/server/comments/config.ts``. The Fuma Comments +storage adapter receives the Drizzle database connection and these schemas: + +* ``comments``; +* ``rates``; +* ``roles``; +* ``users``. + +The comment API route is mounted under ``/api/comments/[...comment]``. Frontend +comment rendering belongs on post detail pages, while moderation and role +policy should remain server-controlled. + +Migration Commands +------------------ + +.. list-table:: + :header-rows: 1 + :widths: 26 50 + + * - Command + - Use + * - ``pnpm db:generate`` + - Generate Drizzle migration files after schema changes. + * - ``pnpm db:migrate`` + - Apply Drizzle migrations. + * - ``pnpm db:push`` + - Push schema changes directly during local development. + * - ``pnpm payload:migrate`` + - Run Payload migrations. + * - ``pnpm payload:migrate:create`` + - Create a new Payload migration. + +Implementation Rule +------------------- + +When adding data-backed features, decide first whether the data is editorial or +application-owned. Editorial content should be modeled in Payload collections. +Account, interaction, moderation, and operational records should be modeled in +Drizzle. diff --git a/Documentation/source/architecture/distribution.rst b/Documentation/source/architecture/distribution.rst new file mode 100644 index 0000000..80b87d0 --- /dev/null +++ b/Documentation/source/architecture/distribution.rst @@ -0,0 +1,45 @@ +Search, Feeds, and Metadata +=========================== + +The application exposes several distribution surfaces in addition to HTML +pages. These endpoints help readers, search clients, crawlers, and social +previews consume the site. + +Search +------ + +The search index endpoint lives at ``src/app/(main)/api/search/route.ts`` and +is served from ``/api/search``. It is intended for the Fumadocs search UI and +should return normalized, public, published content only. + +Feeds +----- + +The feed route lives at ``src/app/(main)/rss.xml/route.ts`` and is exposed as +``/rss.xml``. Keep this canonical path consistent in page metadata, sitemap +configuration, and external documentation. + +Open Graph Images +----------------- + +Dynamic image generation is implemented under: + +* ``src/app/(main)/banner.png`` for site-level banner output; +* ``src/app/(main)/og/[...slug]`` for post-specific Open Graph output. + +The font JSON assets in these folders support image rendering. Treat them as +runtime assets for the route handlers. + +Metadata +-------- + +Metadata helpers live in ``src/lib/metadata.ts`` and page-level JSON-LD +rendering is handled by ``src/components/json-ld.tsx``. New public routes +should define metadata intentionally instead of relying on generic defaults. + +Sitemap +------- + +``next-sitemap.config.cjs`` controls sitemap generation after application +builds. Generated ``public/robots.txt`` and ``public/sitemap*.xml`` are ignored +by Git and should be regenerated by the build pipeline. diff --git a/Documentation/source/architecture/index.rst b/Documentation/source/architecture/index.rst new file mode 100644 index 0000000..34d2630 --- /dev/null +++ b/Documentation/source/architecture/index.rst @@ -0,0 +1,15 @@ +Architecture +============ + +This section documents how the major subsystems fit together: the public +frontend, Payload CMS, database-backed application services, content rendering, +and distribution endpoints. + +.. toctree:: + :maxdepth: 2 + + system-overview + content-model + data-and-auth + distribution + risks diff --git a/Documentation/source/architecture/risks.rst b/Documentation/source/architecture/risks.rst new file mode 100644 index 0000000..604bc78 --- /dev/null +++ b/Documentation/source/architecture/risks.rst @@ -0,0 +1,55 @@ +Risks and Technical Debt +======================== + +This page tracks known architectural risks and follow-up work. Keep entries +short, actionable, and tied to repository evidence. + +Current Risk Register +--------------------- + +.. list-table:: + :header-rows: 1 + :widths: 10 26 28 30 + + * - Priority + - Finding + - Evidence + - Recommendation + * - P0 + - Email utility type dependency should be verified. + - ``src/lib/resend.ts`` imports project-local types. + - Keep type sources explicit and covered by type checks. + * - P0 + - Payload secret fallback is unsafe for production. + - ``payload.config.ts`` falls back to ``your-secret-key``. + - Fail fast in production when ``PAYLOAD_SECRET`` is missing. + * - P1 + - RSS canonical path must stay consistent. + - Route is ``/rss.xml``. + - Use the same path in metadata, README, docs, and sitemap config. + * - P1 + - In-memory aggregation can become expensive. + - Search, RSS, and tag counts read batches of posts. + - Add caching or database-side aggregation when content volume grows. + * - P1 + - Canonical URL configuration needs production hardening. + - Deployment URL handling depends on environment conventions. + - Prefer an explicit public site URL for production. + * - P2 + - Comment role governance needs policy tests. + - Comment storage includes roles. + - Define moderation behavior before adding privileged comment actions. + +Roadmap +------- + +Phase 1: correctness and configuration hardening + Fix production secret handling, verify email types, and align feed paths. + +Phase 2: scalability + Cache expensive public indexes, move tag aggregation closer to storage, and + add clear revalidation boundaries. + +Phase 3: governance + Add architecture decision records, route-level integration tests, and CI + checks for type safety, tests, linting, and documentation links. diff --git a/Documentation/source/architecture/system-overview.rst b/Documentation/source/architecture/system-overview.rst new file mode 100644 index 0000000..c876096 --- /dev/null +++ b/Documentation/source/architecture/system-overview.rst @@ -0,0 +1,61 @@ +System Overview +=============== + +Layered View +------------ + +.. list-table:: + :header-rows: 1 + :widths: 22 34 44 + + * - Layer + - Main Files + - Responsibility + * - Presentation + - ``src/app/(main)``, ``src/components`` + - Render public pages, route handlers, shared UI, rich text, and layout. + * - Content access + - ``src/lib/payload-posts.ts`` + - Query Payload and normalize CMS documents into frontend-friendly types. + * - CMS admin + - ``payload.config.ts``, ``src/payload``, ``src/app/(payload)`` + - Define editorial collections and expose the admin experience. + * - Auth and comments + - ``src/server/auth``, ``src/server/comments`` + - Authenticate users and persist comment data. + * - Data + - ``src/server/db``, ``src/migrations`` + - Own Drizzle schema, connection setup, and application migrations. + * - Content pipeline + - ``content``, ``source.config.ts`` + - Build local MDX content through Fumadocs. + +Request Flow: Reading a Post +---------------------------- + +1. A route under ``src/app/(main)/(home)/posts/[slug]`` receives a slug. +2. The server component calls ``getPostBySlug``. +3. ``src/lib/payload-posts.ts`` obtains a Payload client and queries + ``posts`` where ``status`` is ``published``. +4. The raw Payload document is transformed into ``BlogPost``. +5. The page renders rich text content and mounts client-side interactions such + as sharing and comments. + +Request Flow: Writing a Comment +------------------------------- + +1. The post detail page renders the Fuma Comments client component. +2. The client calls ``/api/comments/[...comment]``. +3. The route delegates to the Fuma Comments Next.js handler. +4. better-auth validates the session. +5. The Drizzle adapter writes comment, rate, and role data to application-owned + tables. + +Boundaries +---------- + +Payload owns editorial content and media metadata. The application owns auth, +comments, UI state, route behavior, and integration logic. Keep that boundary +clear when adding features: editorial fields belong in Payload collections; +reader interaction and account behavior belong in ``src/server`` and the app +routes. diff --git a/Documentation/source/conf.py b/Documentation/source/conf.py new file mode 100644 index 0000000..e14731c --- /dev/null +++ b/Documentation/source/conf.py @@ -0,0 +1,30 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'Next Blog' +copyright = '2026, Bertrand Yuan' +author = 'Bertrand Yuan' +release = 'v1.1' +language = 'en' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [] + +templates_path = ['_templates'] +exclude_patterns = [] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'alabaster' +html_static_path = ['_static'] +html_css_files = ['language-switcher.css'] diff --git a/Documentation/source/contributing/code-integrity.rst b/Documentation/source/contributing/code-integrity.rst new file mode 100644 index 0000000..7ead918 --- /dev/null +++ b/Documentation/source/contributing/code-integrity.rst @@ -0,0 +1,43 @@ +Code Integrity +============== + +This project should preserve a reviewable and trustworthy history. The raw +``docs/protecting-code-integrity.md`` note covers broader PGP background; this +page records repository-level expectations. + +Source Provenance +----------------- + +* Prefer signed commits and signed tags when publishing releases. +* Protect credentials and signing keys outside the repository. +* Do not commit generated secrets, local database state, or build output. +* Review dependency changes with the same care as source changes. + +Git Practices +------------- + +* Keep commits focused by subsystem or behavior. +* Avoid mixing generated files with hand-written changes unless the generated + files are required for the change. +* Use branches for non-trivial work. +* Rebase or merge deliberately; avoid history rewrites on shared branches + unless the team has agreed. + +Release Tags +------------ + +Release tags should be annotated and signed when possible: + +.. code-block:: bash + + git tag -s v1.2.0 -m "v1.2.0" + +Verification +------------ + +Before trusting a release or dependency bump, verify: + +* tag or commit signature when available; +* changelog and diff scope; +* dependency lockfile changes; +* CI result for the exact commit being released. diff --git a/Documentation/source/contributing/commit-messages.rst b/Documentation/source/contributing/commit-messages.rst new file mode 100644 index 0000000..22bda0d --- /dev/null +++ b/Documentation/source/contributing/commit-messages.rst @@ -0,0 +1,85 @@ +Commit Messages +=============== + +Commit messages should be structured enough to support readable history and +future changelog generation. + +Format +------ + +.. code-block:: text + + <type>(<scope>): <short summary> + + <body> + + <footer> + +The header is required. The body is recommended for all non-trivial changes and +should explain why the change exists. + +Types +----- + +.. list-table:: + :header-rows: 1 + :widths: 18 52 + + * - Type + - Use + * - ``build`` + - Build system or dependency changes. + * - ``ci`` + - CI configuration and automation. + * - ``docs`` + - Documentation-only changes. + * - ``feat`` + - New user-facing capability. + * - ``fix`` + - Bug fix. + * - ``perf`` + - Performance improvement. + * - ``refactor`` + - Code change that does not add behavior or fix a bug. + * - ``test`` + - Test additions or corrections. + +Scopes +------ + +Use a scope when it clarifies ownership. Recommended repository scopes: + +* ``app``; +* ``payload``; +* ``auth``; +* ``comments``; +* ``db``; +* ``ui``; +* ``email``; +* ``docs``; +* ``tooling``. + +Summary Rules +------------- + +* Use imperative present tense. +* Do not capitalize the first word unless it is a proper noun. +* Do not end the summary with a period. +* Keep the summary concise. + +Examples +-------- + +.. code-block:: text + + feat(comments): add moderation role checks + + fix(feed): keep rss canonical path consistent + + docs: add Sphinx architecture guide + +Reverts +------- + +Revert commits should start with ``revert:`` and include the SHA of the commit +being reverted in the body. diff --git a/Documentation/source/contributing/index.rst b/Documentation/source/contributing/index.rst new file mode 100644 index 0000000..0a2394d --- /dev/null +++ b/Documentation/source/contributing/index.rst @@ -0,0 +1,12 @@ +Contributing +============ + +This section describes contribution expectations for commits, review, and +source integrity. + +.. toctree:: + :maxdepth: 2 + + workflow + commit-messages + code-integrity diff --git a/Documentation/source/contributing/workflow.rst b/Documentation/source/contributing/workflow.rst new file mode 100644 index 0000000..8457cbd --- /dev/null +++ b/Documentation/source/contributing/workflow.rst @@ -0,0 +1,42 @@ +Workflow +======== + +Before Coding +------------- + +1. Identify which subsystem owns the change. +2. Read the nearest existing implementation and tests. +3. Decide whether the change affects runtime behavior, schema, UI, docs, or + operations. +4. Keep the patch scoped to the requested behavior. + +During Implementation +--------------------- + +* Follow local patterns before introducing new abstractions. +* Keep data fetching in server routes or ``src/lib`` helpers. +* Use existing UI primitives and tokens. +* Update tests when behavior changes. +* Update this documentation when a public contract, architecture, or workflow + changes. + +Before Submitting +----------------- + +Run the most relevant checks: + +.. code-block:: bash + + pnpm lint + pnpm test + make -C Documentation html + +For schema changes, include the appropriate migration and generated type +updates. + +Review Expectations +------------------- + +Reviews should prioritize correctness, behavior regressions, missing tests, +security-sensitive configuration, and unclear contracts. Style comments should +point to an existing repository convention or a maintainability issue. diff --git a/Documentation/source/frontend/accessibility.rst b/Documentation/source/frontend/accessibility.rst new file mode 100644 index 0000000..bca6fbf --- /dev/null +++ b/Documentation/source/frontend/accessibility.rst @@ -0,0 +1,48 @@ +Accessibility +============= + +Baseline +-------- + +The current frontend already uses semantic landmarks such as ``main``, +``section``, and ``article`` in key routes. Several icon buttons include +accessible labels, and theme-aware colors are centralized through design +tokens. + +Required Practices +------------------ + +* Give icon-only controls an accessible name. +* Preserve visible keyboard focus for custom controls. +* Keep text readable in both light and dark themes. +* Use semantic elements before ARIA. +* Do not hide essential navigation or status only behind animation. +* Validate empty, loading, success, and error states for forms. + +Review Checklist +---------------- + +.. list-table:: + :header-rows: 1 + :widths: 34 42 + + * - Check + - Expected Result + * - Keyboard navigation + - Header, menus, buttons, form controls, and links are reachable. + * - Screen reader labels + - Icon-only actions have clear names. + * - Contrast + - Text and UI states remain readable in light and dark modes. + * - Layout + - Text does not overlap or overflow at mobile and desktop breakpoints. + * - Feedback + - Form errors and success states are visible and announced where needed. + +Known Follow-ups +---------------- + +* Improve visible focus states for all custom controls. +* Audit icon-only social and action links. +* Add reusable empty states for posts and tags. +* Add visual regression coverage for critical routes. diff --git a/Documentation/source/frontend/components.rst b/Documentation/source/frontend/components.rst new file mode 100644 index 0000000..fc6fa58 --- /dev/null +++ b/Documentation/source/frontend/components.rst @@ -0,0 +1,52 @@ +Components +========== + +Component Groups +---------------- + +.. list-table:: + :header-rows: 1 + :widths: 26 52 + + * - Area + - Files + * - Layout + - ``src/components/section.tsx``, ``src/components/sections`` + * - Navigation + - ``src/components/active-link.tsx``, header menu and navbar files + * - Posts and tags + - ``src/components/posts/post-card.tsx``, ``src/components/tags`` + * - Forms + - ``src/components/newsletter-form.tsx``, ``src/components/ui/form.tsx`` + * - Auth + - ``src/components/auth/user-button.tsx``, ``user-avatar.tsx`` + * - Rich text + - ``src/components/rich-text`` + * - Base UI + - ``src/components/ui`` + +Component Rules +--------------- + +Use existing primitives first + Before creating a new component, check ``src/components/ui`` and existing + page components for a matching pattern. + +Keep data access out of presentational components + Shared components should receive normalized props. Server components and + ``src/lib`` helpers should handle data fetching. + +Preserve accessibility names + Icon-only buttons and links need explicit labels. Existing tests cover some + components; extend tests when adding new interactive behavior. + +Keep variants local and typed + Use existing ``class-variance-authority`` patterns for variant-heavy + controls instead of ad hoc class switches. + +Testing +------- + +Component tests live beside components using ``*.test.tsx`` or ``*.test.ts``. +Prefer focused tests that assert user-visible behavior, accessibility labels, +and variant output instead of implementation details. diff --git a/Documentation/source/frontend/index.rst b/Documentation/source/frontend/index.rst new file mode 100644 index 0000000..d293dca --- /dev/null +++ b/Documentation/source/frontend/index.rst @@ -0,0 +1,13 @@ +Frontend +======== + +This section describes page responsibilities, UI conventions, component usage, +and accessibility expectations for the public site. + +.. toctree:: + :maxdepth: 2 + + routes + ui-guidelines + components + accessibility diff --git a/Documentation/source/frontend/routes.rst b/Documentation/source/frontend/routes.rst new file mode 100644 index 0000000..ed2c618 --- /dev/null +++ b/Documentation/source/frontend/routes.rst @@ -0,0 +1,66 @@ +Routes and Page Responsibilities +================================ + +Public Routes +------------- + +.. list-table:: + :header-rows: 1 + :widths: 22 34 44 + + * - Route + - Main File + - Responsibility + * - ``/`` + - ``src/app/(main)/(home)/page.tsx`` + - Home page with hero, recent posts, and newsletter CTA. + * - ``/posts`` + - ``src/app/(main)/(home)/posts/page.tsx`` + - Paginated list of published posts. + * - ``/posts/[slug]`` + - ``src/app/(main)/(home)/posts/[slug]/page.tsx`` + - Post detail page with rich text, metadata, sharing, and comments. + * - ``/tags`` + - ``src/app/(main)/(home)/tags/page.tsx`` + - Tag index with post counts. + * - ``/tags/[tag]`` + - ``src/app/(main)/(home)/tags/[...slug]/page.tsx`` + - Tag-filtered post list. + * - ``/about`` + - ``src/app/(main)/(home)/(mdx)/about/page.mdx`` + - MDX profile page. + * - ``/login`` + - ``src/app/(main)/(auth)/login/page.tsx`` + - OAuth login entry. + * - ``/admin`` + - ``src/app/(payload)/admin`` + - Payload CMS admin. + +API and Generated Routes +------------------------ + +.. list-table:: + :header-rows: 1 + :widths: 24 56 + + * - Route + - Responsibility + * - ``/api/auth/[...all]`` + - better-auth route handler. + * - ``/api/comments/[...comment]`` + - Fuma Comments route handler. + * - ``/api/search`` + - Public search index endpoint. + * - ``/rss.xml`` + - Feed output. + * - ``/banner.png`` + - Site-level Open Graph image. + * - ``/og/[...slug]`` + - Post-specific Open Graph image. + +Routing Rule +------------ + +Add new public pages under ``src/app/(main)`` and preserve the existing layout +split between the public site and Payload admin. New API routes should document +their public contract in :doc:`../reference/api`. diff --git a/Documentation/source/frontend/ui-guidelines.rst b/Documentation/source/frontend/ui-guidelines.rst new file mode 100644 index 0000000..d3e8a9d --- /dev/null +++ b/Documentation/source/frontend/ui-guidelines.rst @@ -0,0 +1,63 @@ +UI Guidelines +============= + +Product Positioning +------------------- + +The UI should feel like a content-first technical blog: readable, restrained, +and efficient. It should avoid marketing-heavy layouts unless the page itself +is explicitly promotional. + +Design Principles +----------------- + +* Reading first: typography, line length, and contrast should favor long-form + reading. +* Lightweight navigation: posts, tags, search, theme switching, and account + actions should remain easy to reach. +* Consistent visual language: dashed borders, corner markers, and subtle + motion are part of the current identity. +* Low learning cost: anonymous and authenticated flows should be obvious. +* Cross-device consistency: mobile and desktop should share the same hierarchy. + +Visual Conventions +------------------ + +Typography + Use the configured Geist font family for prose and Geist Mono for code-like + metadata. Avoid oversized headings inside dense cards or sidebars. + +Color + Use existing design tokens from ``src/styles/globals.css``. The site + supports light, dark, and system theme modes. + +Shape + Prefer the existing dashed-border and corner-marker treatment for major + framed sections. Avoid adding unrelated decorative systems. + +Motion + Keep motion short, functional, and tied to state changes. Current examples + include hero fade-in, hover transitions, theme transition, and share toast. + +Page Notes +---------- + +Home + Hero, latest posts, and newsletter CTA should establish identity and expose + current content quickly. + +Post list + Cards should support scanning title, summary, tags, date, and image without + requiring a detail-page visit. + +Post detail + The article body is primary. Side metadata, share controls, and comments + should support the reading flow rather than compete with it. + +Tags + Tag pages should make topic discovery fast and preserve the post-list visual + pattern. + +Login + OAuth options should be clear and minimal. Do not add account-management + concepts to the login page unless the backend supports them. diff --git a/Documentation/source/getting-started.rst b/Documentation/source/getting-started.rst new file mode 100644 index 0000000..890c01f --- /dev/null +++ b/Documentation/source/getting-started.rst @@ -0,0 +1,99 @@ +Getting Started +=============== + +This page describes the local development path for contributors who want to run +the application, connect a database, and validate changes. + +Prerequisites +------------- + +Install the following tools before starting: + +* Node.js compatible with Next.js 15; +* pnpm 10.x; +* Docker or Podman for local PostgreSQL; +* Git; +* optional: Sphinx for building ``Documentation`` locally. + +Environment +----------- + +Copy the example environment file and fill in values for your local setup: + +.. code-block:: bash + + cp .env.example .env + +The application validates environment variables through ``src/env.js``. For +development-only workflows where external services are not needed, some +commands can be run with ``SKIP_ENV_VALIDATION=1``. + +Database +-------- + +The repository includes ``start-database.sh`` for local PostgreSQL bootstrap. +It checks for an occupied port, reuses an existing container when possible, and +warns about the default password placeholder. + +.. code-block:: bash + + ./start-database.sh + +After the database is available, run Payload and Drizzle migrations as needed: + +.. code-block:: bash + + pnpm payload:migrate + pnpm db:push + +Install and Run +--------------- + +Install dependencies: + +.. code-block:: bash + + pnpm install + +Start the development server: + +.. code-block:: bash + + pnpm dev + +The public site is served at ``http://localhost:3000``. The Payload admin is +available at ``/admin``. + +Validation Commands +------------------- + +Use the repository scripts for routine checks: + +.. list-table:: + :header-rows: 1 + :widths: 24 50 + + * - Command + - Purpose + * - ``pnpm lint`` + - Validate content links and run Biome linting. + * - ``pnpm check`` + - Run Biome checks. + * - ``pnpm test`` + - Run the Vitest suite once. + * - ``pnpm test:coverage`` + - Run tests with coverage. + * - ``pnpm build`` + - Build the Next.js application and generate sitemap output. + +Build the Documentation +----------------------- + +From the repository root: + +.. code-block:: bash + + make -C Documentation html + +The generated HTML is written to ``Documentation/build/html`` and should not be +committed. diff --git a/Documentation/source/index.rst b/Documentation/source/index.rst new file mode 100644 index 0000000..1f7103b --- /dev/null +++ b/Documentation/source/index.rst @@ -0,0 +1,83 @@ +Next Blog Documentation +======================= + +Next Blog is a full-stack blog platform built with Next.js, Payload CMS, +PostgreSQL, Drizzle ORM, better-auth, and Fuma Comments. This documentation +tree describes the product intent, system architecture, runtime operations, +frontend conventions, and contribution workflow for the repository. + +The structure intentionally follows a subsystem-oriented layout: top-level +indexes introduce each area, while deeper pages describe concrete flows, +interfaces, and operational responsibilities. Keep this page small; add new +material under the nearest subsystem directory. + +Audience +-------- + +This documentation is written for: + +* maintainers who need to understand the shape of the codebase; +* contributors who need repeatable setup and contribution rules; +* operators who need environment, database, and release notes; +* designers and frontend engineers who need UI conventions. + +Project Map +----------- + +.. list-table:: + :header-rows: 1 + :widths: 24 56 + + * - Area + - Responsibility + * - ``src/app/(main)`` + - Public site routes, layouts, API endpoints, feeds, and Open Graph images. + * - ``src/app/(payload)`` + - Payload CMS admin routes and API bridge. + * - ``src/components`` + - Shared UI, rich text rendering, layout sections, auth widgets, and forms. + * - ``src/lib`` + - Application helpers for content access, metadata, validation, actions, + email, and client utilities. + * - ``src/server`` + - Database connection, Drizzle schema, authentication, and comment storage. + * - ``src/payload`` + - Payload collection definitions for posts, users, and media. + * - ``content`` + - MDX content consumed by the Fumadocs content pipeline. + * - ``Documentation/source`` + - Sphinx source files for this documentation set. + +Contents +-------- + +.. toctree:: + :maxdepth: 2 + + introduction + getting-started + +.. toctree:: + :maxdepth: 2 + + architecture/index + +.. toctree:: + :maxdepth: 2 + + frontend/index + +.. toctree:: + :maxdepth: 2 + + operations/index + +.. toctree:: + :maxdepth: 2 + + contributing/index + +.. toctree:: + :maxdepth: 2 + + reference/index diff --git a/Documentation/source/introduction.rst b/Documentation/source/introduction.rst new file mode 100644 index 0000000..5a42d23 --- /dev/null +++ b/Documentation/source/introduction.rst @@ -0,0 +1,61 @@ +Introduction +============ + +Next Blog is a reading-first personal publishing platform. It combines a +Next.js App Router frontend with Payload CMS for editorial workflows and a +PostgreSQL-backed application layer for authentication, comments, and related +state. + +Product Scope +------------- + +The current product scope is intentionally focused: + +* publish and manage posts through Payload CMS; +* render public blog pages, tag pages, and post detail pages; +* support OAuth login through better-auth; +* allow signed-in users to comment through Fuma Comments; +* expose RSS, search, metadata, JSON-LD, sitemap, and Open Graph outputs; +* provide a newsletter form and React Email template for future email flows. + +The platform is not a generic community CMS. It is a controlled publishing +site with a public reading surface and a private admin surface. + +Primary Roles +------------- + +.. list-table:: + :header-rows: 1 + :widths: 20 34 36 + + * - Role + - Goal + - Main Routes + * - Visitor + - Browse and read content. + - ``/``, ``/posts``, ``/posts/[slug]``, ``/tags`` + * - Returning reader + - Filter by topic and follow updates. + - ``/tags/[tag]``, ``/rss.xml`` + * - Authenticated user + - Comment and use account-aware actions. + - ``/login``, ``/posts/[slug]`` + * - Content admin + - Create, edit, schedule, and publish content. + - ``/admin`` + +Design Direction +---------------- + +The public site should stay content-first: clear hierarchy, low visual noise, +predictable navigation, and fast access to posts and tags. The existing visual +language uses dashed borders, corner markers, restrained motion, and system +theme support. + +Documentation Direction +----------------------- + +This Sphinx tree is the canonical documentation system for the repository. +Short product briefs and research notes can still live in ``docs/`` as raw +inputs, but durable engineering documentation should be promoted into +``Documentation/source`` as reStructuredText. diff --git a/Documentation/source/ja/architecture.rst b/Documentation/source/ja/architecture.rst new file mode 100644 index 0000000..1f8464e --- /dev/null +++ b/Documentation/source/ja/architecture.rst @@ -0,0 +1,50 @@ +アーキテクチャ +============== + +レイヤー構成 +------------ + +.. list-table:: + :header-rows: 1 + :widths: 22 34 44 + + * - レイヤー + - 主なファイル + - 責務 + * - 表示層 + - ``src/app/(main)``、``src/components`` + - 公開ページ、ルートハンドラー、共通 UI、リッチテキスト、レイアウト。 + * - コンテンツアクセス層 + - ``src/lib/payload-posts.ts`` + - Payload を問い合わせ、CMS ドキュメントをフロントエンド向けの形に正規化する。 + * - CMS 管理層 + - ``payload.config.ts``、``src/payload`` + - コレクションを定義し、管理画面を提供する。 + * - 認証とコメント + - ``src/server/auth``、``src/server/comments`` + - OAuth、セッション、コメント保存、コメント権限を扱う。 + * - データ層 + - ``src/server/db``、``src/migrations`` + - Drizzle schema、データベース接続、アプリケーション移行を管理する。 + +記事読み込みフロー +------------------ + +1. ``/posts/[slug]`` ページが記事 slug を受け取る。 +2. Server Component が ``getPostBySlug`` を呼び出す。 +3. ``src/lib/payload-posts.ts`` が Payload client を取得し、``published`` の記事を問い合わせる。 +4. 生の Payload ドキュメントを ``BlogPost`` に変換する。 +5. ページがリッチテキストを表示し、共有やコメントの操作を有効にする。 + +データ境界 +---------- + +Payload は編集コンテンツとメディアメタデータを所有します。アプリケーション層は認証、コメント、ルート動作、UI 状態、統合ロジックを所有します。新機能では、編集データは Payload collection に、アカウント・操作・モデレーション・運用記録は Drizzle schema に置く方針です。 + +既知のリスク +------------ + +* 本番環境では Payload secret のデフォルト値を使わない。 +* RSS の正規パスは ``/rss.xml`` に統一する。 +* タグ集計と検索インデックスは現在バッチ読み込みに依存しているため、規模が大きくなったらキャッシュまたは DB 側集計を導入する。 +* コメントのロール方針には、より明確なサーバー側ルールとテストが必要。 diff --git a/Documentation/source/ja/contributing.rst b/Documentation/source/ja/contributing.rst new file mode 100644 index 0000000..cfd63bc --- /dev/null +++ b/Documentation/source/ja/contributing.rst @@ -0,0 +1,38 @@ +コントリビューション +==================== + +作業フロー +---------- + +1. 変更を所有するサブシステムを判断する。 +2. 近い実装とテストを読む。 +3. 実行時動作、schema、UI、ドキュメント、運用手順への影響を確認する。 +4. patch は対象の挙動に絞り、無関係なリファクタリングを避ける。 + +コミットメッセージ +------------------ + +推奨形式: + +.. code-block:: text + + <type>(<scope>): <short summary> + +よく使う type は ``build``、``ci``、``docs``、``feat``、``fix``、``perf``、``refactor``、``test`` です。summary は命令形の現在形で書き、末尾にピリオドを付けません。 + +コード完全性 +------------ + +* リリースでは署名付き commit と署名付き tag を優先する。 +* 秘密情報、ローカル DB 状態、ビルド成果物をコミットしない。 +* 依存関係の変更はソース変更と同じ慎重さでレビューする。 +* 重要な変更はブランチで作業し、テストとドキュメントビルドを通す。 + +提出前チェック +-------------- + +.. code-block:: bash + + pnpm lint + pnpm test + make -C Documentation html diff --git a/Documentation/source/ja/frontend.rst b/Documentation/source/ja/frontend.rst new file mode 100644 index 0000000..a85ae22 --- /dev/null +++ b/Documentation/source/ja/frontend.rst @@ -0,0 +1,49 @@ +フロントエンド +============== + +ページ責務 +---------- + +.. list-table:: + :header-rows: 1 + :widths: 22 34 44 + + * - ルート + - 主なファイル + - 責務 + * - ``/`` + - ``src/app/(main)/(home)/page.tsx`` + - Hero、最新記事、Newsletter CTA を含むホーム。 + * - ``/posts`` + - ``src/app/(main)/(home)/posts/page.tsx`` + - 公開済み記事のページ付き一覧。 + * - ``/posts/[slug]`` + - ``src/app/(main)/(home)/posts/[slug]/page.tsx`` + - 記事詳細、リッチテキスト、メタデータ、共有、コメント。 + * - ``/tags`` + - ``src/app/(main)/(home)/tags/page.tsx`` + - タグ一覧と記事数。 + * - ``/tags/[tag]`` + - ``src/app/(main)/(home)/tags/[...slug]/page.tsx`` + - タグで絞り込んだ記事一覧。 + * - ``/login`` + - ``src/app/(main)/(auth)/login/page.tsx`` + - OAuth ログイン入口。 + +UI 原則 +------- + +* 読みやすさを優先し、タイポグラフィ、行幅、コントラストを調整する。 +* 記事、タグ、検索、テーマ切替、アカウント操作にすぐアクセスできるようにする。 +* 点線ボーダー、角マーカー、控えめなモーションという既存の視覚言語を保つ。 +* モバイルとデスクトップで同じ情報階層を維持する。 + +コンポーネント規約 +------------------ + +新しいコンポーネントを作る前に ``src/components/ui`` と既存ページの実装を確認します。共通コンポーネントは正規化された props を受け取り、データ取得は Server Component または ``src/lib`` helper に置きます。アイコンのみのボタンには必ずアクセシブルな名前を付けます。 + +アクセシビリティ +---------------- + +カスタム操作にはキーボードフォーカスを残します。アイコンボタンやリンクには読み上げ可能な名前を付けます。ライトテーマとダークテーマの両方で十分なコントラストを保ち、フォームは空・読み込み・成功・エラー状態を扱います。 diff --git a/Documentation/source/ja/getting-started.rst b/Documentation/source/ja/getting-started.rst new file mode 100644 index 0000000..4d11693 --- /dev/null +++ b/Documentation/source/ja/getting-started.rst @@ -0,0 +1,72 @@ +はじめに +======== + +このページでは、ローカル開発の基本手順を説明します。依存関係、環境変数、データベース、アプリケーション起動、ドキュメントビルドを扱います。 + +必要なツール +------------ + +次のツールを用意してください。 + +* Next.js 15 に対応した Node.js; +* pnpm 10.x; +* ローカル PostgreSQL 用の Docker または Podman; +* Git; +* 任意: Sphinx。 + +環境変数 +-------- + +サンプルをコピーします。 + +.. code-block:: bash + + cp .env.example .env + +環境変数は ``src/env.js`` で ``@t3-oss/env-nextjs`` と ``zod`` により検証されます。ローカル UI やドキュメント確認だけであれば ``SKIP_ENV_VALIDATION=1`` を一時的に使えますが、本番では使わないでください。 + +データベース +------------ + +ローカル PostgreSQL を起動します。 + +.. code-block:: bash + + ./start-database.sh + +必要に応じて次を実行します。 + +.. code-block:: bash + + pnpm payload:migrate + pnpm db:push + +アプリケーション起動 +-------------------- + +.. code-block:: bash + + pnpm install + pnpm dev + +公開サイトは通常 ``http://localhost:3000``、Payload 管理画面は ``/admin`` です。 + +よく使うチェック +---------------- + +.. list-table:: + :header-rows: 1 + :widths: 24 50 + + * - コマンド + - 目的 + * - ``pnpm lint`` + - コンテンツリンク検証と Biome lint。 + * - ``pnpm check`` + - Biome チェック。 + * - ``pnpm test`` + - Vitest テスト。 + * - ``pnpm build`` + - Next.js アプリケーションのビルドとサイトマップ生成。 + * - ``make -C Documentation html`` + - Sphinx ドキュメントのビルド。 diff --git a/Documentation/source/ja/index.rst b/Documentation/source/ja/index.rst new file mode 100644 index 0000000..3376190 --- /dev/null +++ b/Documentation/source/ja/index.rst @@ -0,0 +1,17 @@ +:orphan: + +Next Blog ドキュメント(日本語) +================================ + +これは Next Blog ドキュメントの日本語版です。保守担当者、コントリビューター、運用担当者に向けて、プロダクトの範囲、アーキテクチャ、フロントエンド規約、運用手順、貢献ルールをまとめています。 + +.. toctree:: + :maxdepth: 2 + + introduction + getting-started + architecture + frontend + operations + contributing + reference diff --git a/Documentation/source/ja/introduction.rst b/Documentation/source/ja/introduction.rst new file mode 100644 index 0000000..731db1e --- /dev/null +++ b/Documentation/source/ja/introduction.rst @@ -0,0 +1,46 @@ +プロジェクト概要 +================ + +Next Blog は、読む体験を中心にしたフルスタックのブログプラットフォームです。公開サイトは Next.js App Router で構築し、コンテンツ管理には Payload CMS を使います。認証、コメント、アプリケーションデータは PostgreSQL、Drizzle ORM、better-auth、Fuma Comments で扱います。 + +プロダクト範囲 +-------------- + +現在の主な機能は次のとおりです。 + +* Payload CMS による記事の作成、編集、公開; +* ホーム、記事一覧、記事詳細、タグページ、プロフィールページの表示; +* Google と GitHub OAuth によるログイン; +* ログインユーザー向けのコメント機能; +* 検索インデックス、RSS、サイトマップ、JSON-LD、Open Graph 画像の出力; +* Newsletter フォームと React Email テンプレート。 + +このプロジェクトは汎用コミュニティ CMS ではありません。公開側は読書体験に、管理側は編集作業に集中した個人向けの発信基盤です。 + +主要なロール +------------ + +.. list-table:: + :header-rows: 1 + :widths: 20 34 36 + + * - ロール + - 目的 + - 主な入口 + * - 訪問者 + - コンテンツを閲覧して読む。 + - ``/``、``/posts``、``/posts/[slug]``、``/tags`` + * - リピーター + - タグで絞り込み、更新を追う。 + - ``/tags/[tag]``、``/rss.xml`` + * - ログインユーザー + - コメントやアカウント関連操作を行う。 + - ``/login``、``/posts/[slug]`` + * - コンテンツ管理者 + - 記事を管理、予約、公開する。 + - ``/admin`` + +ドキュメント方針 +---------------- + +``Documentation/source`` はこのリポジトリの正式な Sphinx ドキュメントソースです。``docs/`` の Markdown は調査メモや下書きとして残せますが、継続的に参照するエンジニアリング文書は reStructuredText としてここに整理します。 diff --git a/Documentation/source/ja/operations.rst b/Documentation/source/ja/operations.rst new file mode 100644 index 0000000..5436fd4 --- /dev/null +++ b/Documentation/source/ja/operations.rst @@ -0,0 +1,65 @@ +運用 +==== + +環境設定 +-------- + +主要な環境変数は ``src/env.js`` で検証されます。 + +.. list-table:: + :header-rows: 1 + :widths: 34 44 + + * - 変数 + - 用途 + * - ``DATABASE_URL`` + - PostgreSQL 接続文字列。 + * - ``RESEND_API_KEY`` + - Resend API key。 + * - ``RESEND_AUDIENCE_ID`` + - Resend audience ID。 + * - ``EMAIL_FROM`` + - 送信元メールアドレス。 + * - ``BETTER_AUTH_SECRET`` + - better-auth secret。本番では必須。 + * - ``GOOGLE_CLIENT_ID`` / ``GOOGLE_CLIENT_SECRET`` + - Google OAuth 認証情報。 + * - ``GITHUB_CLIENT_ID`` / ``GITHUB_CLIENT_SECRET`` + - GitHub OAuth 認証情報。 + +データベース手順 +---------------- + +Payload collection の変更: + +.. code-block:: bash + + pnpm payload:migrate:create + pnpm payload:migrate + pnpm payload:generate + +アプリケーション schema の変更: + +.. code-block:: bash + + pnpm db:generate + pnpm db:migrate + +品質チェック +------------ + +.. code-block:: bash + + pnpm lint + pnpm check + pnpm test + pnpm build + +ドキュメントビルド +------------------ + +.. code-block:: bash + + make -C Documentation html + +生成される ``Documentation/build`` はコミットしません。 diff --git a/Documentation/source/ja/reference.rst b/Documentation/source/ja/reference.rst new file mode 100644 index 0000000..aa0600a --- /dev/null +++ b/Documentation/source/ja/reference.rst @@ -0,0 +1,57 @@ +リファレンス +============ + +よく使うコマンド +---------------- + +.. list-table:: + :header-rows: 1 + :widths: 26 50 + + * - コマンド + - 説明 + * - ``pnpm dev`` + - 開発サーバーを起動する。 + * - ``pnpm build`` + - 本番アプリケーションをビルドする。 + * - ``pnpm lint`` + - コンテンツリンク検証と Biome lint を実行する。 + * - ``pnpm test`` + - テストを実行する。 + * - ``pnpm db:migrate`` + - Drizzle migration を適用する。 + * - ``pnpm payload:generate`` + - Payload TypeScript 型を生成する。 + +ルート +------ + +.. code-block:: text + + / + /posts + /posts/[slug] + /tags + /tags/[tag] + /about + /login + /admin + /api/auth/[...all] + /api/comments/[...comment] + /api/search + /rss.xml + +用語 +---- + +Payload + 記事、ユーザー、メディア、管理画面を扱う CMS。 + +Drizzle + アプリケーション所有のデータベーステーブルを扱う TypeScript ORM。 + +better-auth + OAuth とセッションを提供する認証ライブラリ。 + +BlogPost + ``src/lib/payload-posts.ts`` が返すフロントエンド向けの正規化済み記事構造。 diff --git a/Documentation/source/operations/database.rst b/Documentation/source/operations/database.rst new file mode 100644 index 0000000..37c0cba --- /dev/null +++ b/Documentation/source/operations/database.rst @@ -0,0 +1,59 @@ +Database +======== + +Local Bootstrap +--------------- + +Use the included helper when developing locally: + +.. code-block:: bash + + ./start-database.sh + +The script is designed for local development and should not be used as a +production database management tool. + +Schema Areas +------------ + +.. list-table:: + :header-rows: 1 + :widths: 24 50 + + * - Area + - Ownership + * - Payload schema + - CMS collections, admin content, media metadata, and Payload-managed + structures. + * - Drizzle ``blog_*`` tables + - better-auth users, sessions, accounts, verifications, comments, rates, + and roles. + +Migration Workflow +------------------ + +For Payload collection changes: + +.. code-block:: bash + + pnpm payload:migrate:create + pnpm payload:migrate + pnpm payload:generate + +For application schema changes: + +.. code-block:: bash + + pnpm db:generate + pnpm db:migrate + +During local iteration, ``pnpm db:push`` can be useful, but committed schema +changes should still have a deliberate migration story. + +Operational Cautions +-------------------- + +* Keep Payload and application-owned tables conceptually separate. +* Regenerate Payload types after collection changes. +* Keep ``drizzle.config.ts`` filters aligned with application-owned tables. +* Do not commit local database data directories or generated build artifacts. diff --git a/Documentation/source/operations/documentation.rst b/Documentation/source/operations/documentation.rst new file mode 100644 index 0000000..b7fcb71 --- /dev/null +++ b/Documentation/source/operations/documentation.rst @@ -0,0 +1,51 @@ +Documentation +============= + +Source Layout +------------- + +Sphinx source files live in ``Documentation/source``. Use reStructuredText for +all Sphinx pages. + +.. list-table:: + :header-rows: 1 + :widths: 26 50 + + * - Directory + - Purpose + * - ``architecture`` + - System design, data model, auth, comments, feeds, and risk register. + * - ``frontend`` + - Routes, UI conventions, components, and accessibility. + * - ``operations`` + - Setup, environment, database, quality, and documentation workflow. + * - ``contributing`` + - Commit, review, and code integrity practices. + * - ``reference`` + - Stable route, command, glossary, and API references. + +Build Commands +-------------- + +Build HTML: + +.. code-block:: bash + + make -C Documentation html + +Clean generated output: + +.. code-block:: bash + + make -C Documentation clean + +Authoring Rules +--------------- + +* Write durable documentation in ``.rst`` files under ``Documentation/source``. +* Keep raw notes in ``docs/`` only when they are not yet ready for the formal + documentation tree. +* Prefer small pages with focused toctrees over long mixed-topic pages. +* Use literal paths and commands with double backticks. +* Add new pages to the nearest ``index.rst`` toctree. +* Do not commit ``Documentation/build`` output. diff --git a/Documentation/source/operations/environment.rst b/Documentation/source/operations/environment.rst new file mode 100644 index 0000000..64e5c8e --- /dev/null +++ b/Documentation/source/operations/environment.rst @@ -0,0 +1,60 @@ +Environment +=========== + +Validation Source +----------------- + +Environment validation is defined in ``src/env.js`` with +``@t3-oss/env-nextjs`` and ``zod``. Empty strings are treated as undefined. + +Server Variables +---------------- + +.. list-table:: + :header-rows: 1 + :widths: 34 44 + + * - Variable + - Purpose + * - ``DATABASE_URL`` + - PostgreSQL connection string. + * - ``RESEND_API_KEY`` + - Resend API key. Must start with ``re_``. + * - ``RESEND_AUDIENCE_ID`` + - Resend audience identifier. + * - ``EMAIL_FROM`` + - Sender email address. + * - ``BETTER_AUTH_SECRET`` + - better-auth secret. Required in production. + * - ``BETTER_AUTH_URL`` + - Optional explicit auth base URL. + * - ``GOOGLE_CLIENT_ID`` / ``GOOGLE_CLIENT_SECRET`` + - Google OAuth credentials. + * - ``GITHUB_CLIENT_ID`` / ``GITHUB_CLIENT_SECRET`` + - GitHub OAuth credentials. + +Client Variables +---------------- + +.. list-table:: + :header-rows: 1 + :widths: 34 44 + + * - Variable + - Purpose + * - ``NEXT_PUBLIC_UMAMI_URL`` + - Optional Umami analytics script URL. + * - ``NEXT_PUBLIC_UMAMI_WEBSITE_ID`` + - Optional Umami site identifier. + +Skipping Validation +------------------- + +``SKIP_ENV_VALIDATION=1`` can be used for limited local or container workflows. +Do not rely on it for production builds. + +Production Notes +---------------- + +Production should use explicit, non-default secrets for Payload and better-auth +and an explicit public site URL for canonical links and generated metadata. diff --git a/Documentation/source/operations/index.rst b/Documentation/source/operations/index.rst new file mode 100644 index 0000000..41b6431 --- /dev/null +++ b/Documentation/source/operations/index.rst @@ -0,0 +1,13 @@ +Operations +========== + +This section covers runtime configuration, database workflows, testing, +documentation builds, and release-oriented tasks. + +.. toctree:: + :maxdepth: 2 + + environment + database + quality + documentation diff --git a/Documentation/source/operations/quality.rst b/Documentation/source/operations/quality.rst new file mode 100644 index 0000000..4be1cfd --- /dev/null +++ b/Documentation/source/operations/quality.rst @@ -0,0 +1,56 @@ +Quality +======= + +Tooling +------- + +.. list-table:: + :header-rows: 1 + :widths: 20 54 + + * - Tool + - Role + * - Vitest + - Unit and component tests. + * - Testing Library + - DOM-oriented component assertions. + * - Biome + - Linting and formatting checks. + * - ``scripts/lint.mts`` + - Project-specific content and link validation. + * - TypeScript + - Static type checking through project build and editor tooling. + +Common Checks +------------- + +.. code-block:: bash + + pnpm lint + pnpm check + pnpm test + pnpm build + +Testing Guidance +---------------- + +Add tests when a change affects: + +* shared UI components; +* route-visible behavior; +* metadata generation; +* validation logic; +* content transformation; +* pagination; +* authentication or comment policy boundaries. + +Keep tests focused on observable behavior. Avoid locking tests to incidental +implementation details unless the implementation itself is the contract. + +CI Direction +------------ + +A complete CI gate should run lint, tests, type-sensitive build checks, and +documentation build checks. If a command requires external secrets, provide a +mocked or validation-skipped CI mode rather than weakening production +validation. diff --git a/Documentation/source/reference/api.rst b/Documentation/source/reference/api.rst new file mode 100644 index 0000000..85081aa --- /dev/null +++ b/Documentation/source/reference/api.rst @@ -0,0 +1,53 @@ +API Reference +============= + +Search Index +------------ + +Path + ``/api/search`` + +Purpose + Provides search data for the frontend search experience. + +Rules + Return public published content only. Keep the response shape stable for the + search client. + +Comments +-------- + +Path + ``/api/comments/[...comment]`` + +Purpose + Handles Fuma Comments operations. + +Rules + Authentication and authorization belong on the server side. Client code + should not decide comment privileges. + +Auth +---- + +Path + ``/api/auth/[...all]`` + +Purpose + Handles better-auth routes for OAuth and session behavior. + +Rules + Keep provider configuration in ``src/server/auth`` and environment + validation in ``src/env.js``. + +Feed +---- + +Path + ``/rss.xml`` + +Purpose + Publishes feed output for readers and feed clients. + +Rules + Include published content only and keep route references canonical. diff --git a/Documentation/source/reference/commands.rst b/Documentation/source/reference/commands.rst new file mode 100644 index 0000000..8268400 --- /dev/null +++ b/Documentation/source/reference/commands.rst @@ -0,0 +1,96 @@ +Command Reference +================= + +Application +----------- + +.. list-table:: + :header-rows: 1 + :widths: 24 52 + + * - Command + - Description + * - ``pnpm dev`` + - Start the Next.js development server. + * - ``pnpm build`` + - Build the production application. + * - ``pnpm start`` + - Start a built production server. + * - ``pnpm preview`` + - Build and start the production server. + +Quality +------- + +.. list-table:: + :header-rows: 1 + :widths: 24 52 + + * - Command + - Description + * - ``pnpm lint`` + - Run project link validation and Biome linting. + * - ``pnpm check`` + - Run Biome checks. + * - ``pnpm format`` + - Format files with Biome. + * - ``pnpm test`` + - Run Vitest once. + * - ``pnpm test:watch`` + - Run Vitest in watch mode. + * - ``pnpm test:coverage`` + - Run tests with coverage. + +Data and CMS +------------ + +.. list-table:: + :header-rows: 1 + :widths: 28 48 + + * - Command + - Description + * - ``pnpm db:generate`` + - Generate Drizzle migration files. + * - ``pnpm db:migrate`` + - Apply Drizzle migrations. + * - ``pnpm db:push`` + - Push Drizzle schema changes directly. + * - ``pnpm db:studio`` + - Open Drizzle Studio. + * - ``pnpm payload:generate`` + - Generate Payload TypeScript types. + * - ``pnpm payload:migrate`` + - Run Payload migrations. + * - ``pnpm payload:migrate:create`` + - Create a Payload migration. + +Email +----- + +.. list-table:: + :header-rows: 1 + :widths: 24 52 + + * - Command + - Description + * - ``pnpm email:dev`` + - Start React Email preview server on port 3001. + * - ``pnpm email:build`` + - Build email templates. + * - ``pnpm email:export`` + - Export email templates. + +Documentation +------------- + +.. list-table:: + :header-rows: 1 + :widths: 28 48 + + * - Command + - Description + * - ``make -C Documentation html`` + - Build Sphinx HTML documentation. + * - ``make -C Documentation clean`` + - Remove generated Sphinx build output. diff --git a/Documentation/source/reference/glossary.rst b/Documentation/source/reference/glossary.rst new file mode 100644 index 0000000..d2d648b --- /dev/null +++ b/Documentation/source/reference/glossary.rst @@ -0,0 +1,32 @@ +Glossary +======== + +App Router + Next.js routing model used by this project under ``src/app``. + +better-auth + Authentication library used for OAuth and sessions. + +BlogPost + Normalized frontend post shape returned by ``src/lib/payload-posts.ts``. + +Drizzle + TypeScript ORM used for application-owned database tables. + +Fuma Comments + Comment UI and server package used for post discussions. + +Fumadocs + MDX content and UI tooling used by the site. + +Lexical + Rich text editor used by Payload CMS. + +Payload + CMS used for posts, users, media, and the admin interface. + +Sphinx + Documentation generator used for ``Documentation/source``. + +Tag + Topic label stored on posts and used for tag index and filtered post pages. diff --git a/Documentation/source/reference/index.rst b/Documentation/source/reference/index.rst new file mode 100644 index 0000000..1f52bcf --- /dev/null +++ b/Documentation/source/reference/index.rst @@ -0,0 +1,13 @@ +Reference +========= + +Reference pages collect stable facts that are useful during implementation and +review. + +.. toctree:: + :maxdepth: 2 + + commands + routes + api + glossary diff --git a/Documentation/source/reference/routes.rst b/Documentation/source/reference/routes.rst new file mode 100644 index 0000000..93bcfd3 --- /dev/null +++ b/Documentation/source/reference/routes.rst @@ -0,0 +1,50 @@ +Route Reference +=============== + +Public Pages +------------ + +.. code-block:: text + + / + /posts + /posts/[slug] + /tags + /tags/[tag] + /about + /login + +Admin and Payload +----------------- + +.. code-block:: text + + /admin + /api/[...slug] + /api/graphql + /api/graphql-playground + +Application APIs +---------------- + +.. code-block:: text + + /api/auth/[...all] + /api/comments/[...comment] + /api/search + +Generated Assets +---------------- + +.. code-block:: text + + /rss.xml + /banner.png + /og/[...slug] + +Route Ownership +--------------- + +Routes under ``src/app/(main)`` belong to the public application. Routes under +``src/app/(payload)`` belong to Payload CMS integration and should be changed +with care because they affect the admin and CMS API surface. diff --git a/Documentation/source/zh_CN/architecture.rst b/Documentation/source/zh_CN/architecture.rst new file mode 100644 index 0000000..55d5b54 --- /dev/null +++ b/Documentation/source/zh_CN/architecture.rst @@ -0,0 +1,50 @@ +架构 +==== + +分层视图 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 22 34 44 + + * - 层 + - 主要文件 + - 职责 + * - 展示层 + - ``src/app/(main)``、``src/components`` + - 渲染公开页面、路由处理器、共享 UI、富文本和布局。 + * - 内容访问层 + - ``src/lib/payload-posts.ts`` + - 查询 Payload,并把 CMS 文档规范化为前端可用的数据结构。 + * - CMS 后台 + - ``payload.config.ts``、``src/payload`` + - 定义内容集合并提供后台管理体验。 + * - 认证与评论 + - ``src/server/auth``、``src/server/comments`` + - 处理 OAuth、会话、评论存储和评论权限。 + * - 数据层 + - ``src/server/db``、``src/migrations`` + - 管理 Drizzle schema、数据库连接和应用迁移。 + +文章读取流程 +------------ + +1. ``/posts/[slug]`` 页面接收文章 slug。 +2. Server Component 调用 ``getPostBySlug``。 +3. ``src/lib/payload-posts.ts`` 获取 Payload client 并查询 ``published`` 状态的文章。 +4. 原始 Payload 文档被转换为 ``BlogPost``。 +5. 页面渲染富文本,并挂载分享、评论等交互。 + +数据边界 +-------- + +Payload 负责编辑内容和媒体元数据;应用层负责认证、评论、路由行为、UI 状态和集成逻辑。新增功能前应先判断数据归属:编辑内容放入 Payload collection;账号、互动、审核和运营记录放入 Drizzle schema。 + +已知风险 +-------- + +* 生产环境不应使用 Payload secret 默认值。 +* RSS 路径应统一为 ``/rss.xml``。 +* 标签统计和搜索索引当前依赖批量读取,内容规模变大后应引入缓存或数据库侧聚合。 +* 评论角色策略需要更明确的服务端规则和测试覆盖。 diff --git a/Documentation/source/zh_CN/contributing.rst b/Documentation/source/zh_CN/contributing.rst new file mode 100644 index 0000000..cc0b39f --- /dev/null +++ b/Documentation/source/zh_CN/contributing.rst @@ -0,0 +1,38 @@ +贡献指南 +======== + +工作流程 +-------- + +1. 先判断变更属于哪个子系统。 +2. 阅读相邻实现和测试。 +3. 确认变更是否影响运行时行为、schema、UI、文档或运维流程。 +4. 保持 patch 聚焦,不做无关重构。 + +提交信息 +-------- + +推荐格式: + +.. code-block:: text + + <type>(<scope>): <short summary> + +常用类型包括 ``build``、``ci``、``docs``、``feat``、``fix``、``perf``、``refactor`` 和 ``test``。摘要使用祈使句、现在时,不以句号结尾。 + +代码完整性 +---------- + +* 发布版本时优先使用签名 commit 和签名 tag。 +* 不提交密钥、本地数据库状态或构建产物。 +* 依赖变更应和源代码变更一样认真审查。 +* 非平凡变更应在分支上开发,并通过测试和文档构建。 + +提交前检查 +---------- + +.. code-block:: bash + + pnpm lint + pnpm test + make -C Documentation html diff --git a/Documentation/source/zh_CN/frontend.rst b/Documentation/source/zh_CN/frontend.rst new file mode 100644 index 0000000..4c58ed6 --- /dev/null +++ b/Documentation/source/zh_CN/frontend.rst @@ -0,0 +1,49 @@ +前端 +==== + +页面职责 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 22 34 44 + + * - 路由 + - 主要文件 + - 职责 + * - ``/`` + - ``src/app/(main)/(home)/page.tsx`` + - 首页,包含 Hero、最新文章和 Newsletter CTA。 + * - ``/posts`` + - ``src/app/(main)/(home)/posts/page.tsx`` + - 已发布文章的分页列表。 + * - ``/posts/[slug]`` + - ``src/app/(main)/(home)/posts/[slug]/page.tsx`` + - 文章详情、富文本、元数据、分享和评论。 + * - ``/tags`` + - ``src/app/(main)/(home)/tags/page.tsx`` + - 标签索引与文章数量。 + * - ``/tags/[tag]`` + - ``src/app/(main)/(home)/tags/[...slug]/page.tsx`` + - 按标签筛选的文章列表。 + * - ``/login`` + - ``src/app/(main)/(auth)/login/page.tsx`` + - OAuth 登录入口。 + +UI 原则 +------- + +* 阅读优先:排版、行宽和对比度应服务长文阅读。 +* 导航轻量:文章、标签、搜索、主题切换和账号入口应容易找到。 +* 视觉一致:延续虚线边框、角标和克制动效。 +* 跨端一致:移动端和桌面端保持相同信息层级。 + +组件约定 +-------- + +新增组件前先检查 ``src/components/ui`` 和现有页面组件。共享组件应接收规范化 props,数据获取应放在 Server Component 或 ``src/lib`` helper 中。图标按钮必须有明确的可访问名称。 + +可访问性 +-------- + +自定义控件要保留键盘焦点;图标按钮和链接需要可读名称;浅色和深色主题都要保持足够对比度;表单必须覆盖空、加载、成功和错误状态。 diff --git a/Documentation/source/zh_CN/getting-started.rst b/Documentation/source/zh_CN/getting-started.rst new file mode 100644 index 0000000..88a6a87 --- /dev/null +++ b/Documentation/source/zh_CN/getting-started.rst @@ -0,0 +1,72 @@ +快速开始 +======== + +本页说明本地开发的基本流程:安装依赖、准备环境变量、启动数据库、运行应用和构建文档。 + +准备工具 +-------- + +需要安装: + +* Node.js,版本需满足 Next.js 15; +* pnpm 10.x; +* Docker 或 Podman,用于本地 PostgreSQL; +* Git; +* 可选:Sphinx,用于本地构建文档。 + +环境变量 +-------- + +复制示例文件: + +.. code-block:: bash + + cp .env.example .env + +环境变量由 ``src/env.js`` 通过 ``@t3-oss/env-nextjs`` 和 ``zod`` 校验。只做本地 UI 或文档调试时,可以临时使用 ``SKIP_ENV_VALIDATION=1``,但生产环境不应依赖它。 + +数据库 +------ + +启动本地 PostgreSQL: + +.. code-block:: bash + + ./start-database.sh + +数据库可用后,按需要运行: + +.. code-block:: bash + + pnpm payload:migrate + pnpm db:push + +运行项目 +-------- + +.. code-block:: bash + + pnpm install + pnpm dev + +公开站点默认位于 ``http://localhost:3000``,Payload 后台位于 ``/admin``。 + +常用检查 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 24 50 + + * - 命令 + - 作用 + * - ``pnpm lint`` + - 校验内容链接并运行 Biome lint。 + * - ``pnpm check`` + - 运行 Biome 检查。 + * - ``pnpm test`` + - 运行 Vitest 测试。 + * - ``pnpm build`` + - 构建 Next.js 应用并生成站点地图。 + * - ``make -C Documentation html`` + - 构建 Sphinx 文档。 diff --git a/Documentation/source/zh_CN/index.rst b/Documentation/source/zh_CN/index.rst new file mode 100644 index 0000000..44f9f58 --- /dev/null +++ b/Documentation/source/zh_CN/index.rst @@ -0,0 +1,17 @@ +:orphan: + +Next Blog 文档(简体中文) +============================= + +这是 Next Blog 文档的简体中文版本。本文档面向维护者、贡献者和部署人员,说明项目的产品边界、架构设计、前端约定、运维流程和贡献规则。 + +.. toctree:: + :maxdepth: 2 + + introduction + getting-started + architecture + frontend + operations + contributing + reference diff --git a/Documentation/source/zh_CN/introduction.rst b/Documentation/source/zh_CN/introduction.rst new file mode 100644 index 0000000..1746b00 --- /dev/null +++ b/Documentation/source/zh_CN/introduction.rst @@ -0,0 +1,46 @@ +项目介绍 +======== + +Next Blog 是一个以阅读体验为核心的全栈博客平台。它使用 Next.js App Router 构建公开站点,使用 Payload CMS 管理内容,并通过 PostgreSQL、Drizzle ORM、better-auth 和 Fuma Comments 提供认证、评论与应用数据能力。 + +产品范围 +-------- + +当前项目聚焦在以下能力: + +* 通过 Payload CMS 创建、编辑、发布文章; +* 渲染首页、文章列表、文章详情、标签页和个人页面; +* 通过 Google 与 GitHub OAuth 登录; +* 为登录用户提供评论功能; +* 输出搜索索引、RSS、站点地图、JSON-LD 和 Open Graph 图片; +* 提供 Newsletter 表单与 React Email 模板。 + +这个项目不是通用社区 CMS,而是一个受控的个人发布系统:公开侧重阅读,后台侧重内容管理。 + +核心角色 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 20 34 36 + + * - 角色 + - 目标 + - 主要入口 + * - 访客 + - 浏览和阅读内容。 + - ``/``、``/posts``、``/posts/[slug]``、``/tags`` + * - 回访读者 + - 通过标签筛选内容并订阅读者入口。 + - ``/tags/[tag]``、``/rss.xml`` + * - 登录用户 + - 发表评论和使用账号相关操作。 + - ``/login``、``/posts/[slug]`` + * - 内容管理员 + - 维护、排期和发布内容。 + - ``/admin`` + +文档定位 +-------- + +``Documentation/source`` 是本项目正式的 Sphinx 文档源目录。``docs/`` 中的 Markdown 文件可以继续作为调研或草稿材料,但稳定的工程文档应整理为 reStructuredText 后进入本目录。 diff --git a/Documentation/source/zh_CN/operations.rst b/Documentation/source/zh_CN/operations.rst new file mode 100644 index 0000000..ddacb09 --- /dev/null +++ b/Documentation/source/zh_CN/operations.rst @@ -0,0 +1,65 @@ +运维 +==== + +环境配置 +-------- + +关键环境变量在 ``src/env.js`` 中校验: + +.. list-table:: + :header-rows: 1 + :widths: 34 44 + + * - 变量 + - 用途 + * - ``DATABASE_URL`` + - PostgreSQL 连接字符串。 + * - ``RESEND_API_KEY`` + - Resend API key。 + * - ``RESEND_AUDIENCE_ID`` + - Resend audience ID。 + * - ``EMAIL_FROM`` + - 发件邮箱。 + * - ``BETTER_AUTH_SECRET`` + - better-auth secret,生产环境必填。 + * - ``GOOGLE_CLIENT_ID`` / ``GOOGLE_CLIENT_SECRET`` + - Google OAuth 凭据。 + * - ``GITHUB_CLIENT_ID`` / ``GITHUB_CLIENT_SECRET`` + - GitHub OAuth 凭据。 + +数据库流程 +---------- + +Payload collection 变更: + +.. code-block:: bash + + pnpm payload:migrate:create + pnpm payload:migrate + pnpm payload:generate + +应用 schema 变更: + +.. code-block:: bash + + pnpm db:generate + pnpm db:migrate + +质量检查 +-------- + +.. code-block:: bash + + pnpm lint + pnpm check + pnpm test + pnpm build + +文档构建 +-------- + +.. code-block:: bash + + make -C Documentation html + +生成的 ``Documentation/build`` 不应提交。 diff --git a/Documentation/source/zh_CN/reference.rst b/Documentation/source/zh_CN/reference.rst new file mode 100644 index 0000000..c295315 --- /dev/null +++ b/Documentation/source/zh_CN/reference.rst @@ -0,0 +1,57 @@ +参考 +==== + +常用命令 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 26 50 + + * - 命令 + - 说明 + * - ``pnpm dev`` + - 启动开发服务器。 + * - ``pnpm build`` + - 构建生产应用。 + * - ``pnpm lint`` + - 运行内容链接校验和 Biome lint。 + * - ``pnpm test`` + - 运行测试。 + * - ``pnpm db:migrate`` + - 应用 Drizzle 迁移。 + * - ``pnpm payload:generate`` + - 生成 Payload TypeScript 类型。 + +路由 +---- + +.. code-block:: text + + / + /posts + /posts/[slug] + /tags + /tags/[tag] + /about + /login + /admin + /api/auth/[...all] + /api/comments/[...comment] + /api/search + /rss.xml + +术语 +---- + +Payload + 管理文章、用户、媒体和后台界面的 CMS。 + +Drizzle + 管理应用自有数据库表的 TypeScript ORM。 + +better-auth + 提供 OAuth 和会话能力的认证库。 + +BlogPost + ``src/lib/payload-posts.ts`` 返回的前端规范化文章结构。 diff --git a/Documentation/source/zh_TW/architecture.rst b/Documentation/source/zh_TW/architecture.rst new file mode 100644 index 0000000..7c8da41 --- /dev/null +++ b/Documentation/source/zh_TW/architecture.rst @@ -0,0 +1,50 @@ +架構 +==== + +分層視圖 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 22 34 44 + + * - 層 + - 主要檔案 + - 職責 + * - 展示層 + - ``src/app/(main)``、``src/components`` + - 呈現公開頁面、路由處理器、共用 UI、富文字和版面。 + * - 內容存取層 + - ``src/lib/payload-posts.ts`` + - 查詢 Payload,並把 CMS 文件正規化為前端可用的資料結構。 + * - CMS 後台 + - ``payload.config.ts``、``src/payload`` + - 定義內容集合並提供後台管理體驗。 + * - 認證與留言 + - ``src/server/auth``、``src/server/comments`` + - 處理 OAuth、Session、留言儲存與留言權限。 + * - 資料層 + - ``src/server/db``、``src/migrations`` + - 管理 Drizzle schema、資料庫連線與應用遷移。 + +文章讀取流程 +------------ + +1. ``/posts/[slug]`` 頁面接收文章 slug。 +2. Server Component 呼叫 ``getPostBySlug``。 +3. ``src/lib/payload-posts.ts`` 取得 Payload client 並查詢 ``published`` 狀態的文章。 +4. 原始 Payload 文件被轉換為 ``BlogPost``。 +5. 頁面呈現富文字,並掛載分享、留言等互動。 + +資料邊界 +-------- + +Payload 負責編輯內容與媒體中繼資料;應用層負責認證、留言、路由行為、UI 狀態與整合邏輯。新增功能前應先判斷資料歸屬:編輯內容放入 Payload collection;帳號、互動、審核與營運記錄放入 Drizzle schema。 + +已知風險 +-------- + +* 正式環境不應使用 Payload secret 預設值。 +* RSS 路徑應統一為 ``/rss.xml``。 +* 標籤統計與搜尋索引目前依賴批次讀取,內容規模變大後應引入快取或資料庫側聚合。 +* 留言角色策略需要更明確的服務端規則與測試覆蓋。 diff --git a/Documentation/source/zh_TW/contributing.rst b/Documentation/source/zh_TW/contributing.rst new file mode 100644 index 0000000..8b12920 --- /dev/null +++ b/Documentation/source/zh_TW/contributing.rst @@ -0,0 +1,38 @@ +貢獻指南 +======== + +工作流程 +-------- + +1. 先判斷變更屬於哪個子系統。 +2. 閱讀相鄰實作和測試。 +3. 確認變更是否影響執行期行為、schema、UI、文件或維運流程。 +4. 保持 patch 聚焦,不做無關重構。 + +提交訊息 +-------- + +推薦格式: + +.. code-block:: text + + <type>(<scope>): <short summary> + +常用類型包括 ``build``、``ci``、``docs``、``feat``、``fix``、``perf``、``refactor`` 和 ``test``。摘要使用祈使句、現在式,不以句號結尾。 + +程式碼完整性 +------------ + +* 發布版本時優先使用簽名 commit 和簽名 tag。 +* 不提交密鑰、本機資料庫狀態或建置產物。 +* 依賴變更應和原始碼變更一樣認真審查。 +* 非平凡變更應在分支上開發,並通過測試和文件建置。 + +提交前檢查 +---------- + +.. code-block:: bash + + pnpm lint + pnpm test + make -C Documentation html diff --git a/Documentation/source/zh_TW/frontend.rst b/Documentation/source/zh_TW/frontend.rst new file mode 100644 index 0000000..b13a747 --- /dev/null +++ b/Documentation/source/zh_TW/frontend.rst @@ -0,0 +1,49 @@ +前端 +==== + +頁面職責 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 22 34 44 + + * - 路由 + - 主要檔案 + - 職責 + * - ``/`` + - ``src/app/(main)/(home)/page.tsx`` + - 首頁,包含 Hero、最新文章和 Newsletter CTA。 + * - ``/posts`` + - ``src/app/(main)/(home)/posts/page.tsx`` + - 已發布文章的分頁列表。 + * - ``/posts/[slug]`` + - ``src/app/(main)/(home)/posts/[slug]/page.tsx`` + - 文章詳情、富文字、metadata、分享和留言。 + * - ``/tags`` + - ``src/app/(main)/(home)/tags/page.tsx`` + - 標籤索引與文章數量。 + * - ``/tags/[tag]`` + - ``src/app/(main)/(home)/tags/[...slug]/page.tsx`` + - 按標籤篩選的文章列表。 + * - ``/login`` + - ``src/app/(main)/(auth)/login/page.tsx`` + - OAuth 登入入口。 + +UI 原則 +------- + +* 閱讀優先:排版、行寬和對比度應服務長文閱讀。 +* 導航輕量:文章、標籤、搜尋、主題切換和帳號入口應容易找到。 +* 視覺一致:延續虛線邊框、角標和克制動效。 +* 跨端一致:行動端和桌面端保持相同資訊層級。 + +元件約定 +-------- + +新增元件前先檢查 ``src/components/ui`` 和現有頁面元件。共用元件應接收正規化 props,資料取得應放在 Server Component 或 ``src/lib`` helper 中。圖示按鈕必須有明確的可存取名稱。 + +可存取性 +-------- + +自訂控制項要保留鍵盤焦點;圖示按鈕和連結需要可讀名稱;淺色和深色主題都要保持足夠對比度;表單必須覆蓋空、載入、成功和錯誤狀態。 diff --git a/Documentation/source/zh_TW/getting-started.rst b/Documentation/source/zh_TW/getting-started.rst new file mode 100644 index 0000000..5ab7907 --- /dev/null +++ b/Documentation/source/zh_TW/getting-started.rst @@ -0,0 +1,72 @@ +快速開始 +======== + +本頁說明本機開發的基本流程:安裝依賴、準備環境變數、啟動資料庫、執行應用與建置文件。 + +準備工具 +-------- + +需要安裝: + +* Node.js,版本需符合 Next.js 15; +* pnpm 10.x; +* Docker 或 Podman,用於本機 PostgreSQL; +* Git; +* 可選:Sphinx,用於本機建置文件。 + +環境變數 +-------- + +複製範例檔: + +.. code-block:: bash + + cp .env.example .env + +環境變數由 ``src/env.js`` 透過 ``@t3-oss/env-nextjs`` 和 ``zod`` 驗證。只做本機 UI 或文件除錯時,可以暫時使用 ``SKIP_ENV_VALIDATION=1``,但正式環境不應依賴它。 + +資料庫 +------ + +啟動本機 PostgreSQL: + +.. code-block:: bash + + ./start-database.sh + +資料庫可用後,按需要執行: + +.. code-block:: bash + + pnpm payload:migrate + pnpm db:push + +執行專案 +-------- + +.. code-block:: bash + + pnpm install + pnpm dev + +公開站台預設位於 ``http://localhost:3000``,Payload 後台位於 ``/admin``。 + +常用檢查 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 24 50 + + * - 命令 + - 作用 + * - ``pnpm lint`` + - 驗證內容連結並執行 Biome lint。 + * - ``pnpm check`` + - 執行 Biome 檢查。 + * - ``pnpm test`` + - 執行 Vitest 測試。 + * - ``pnpm build`` + - 建置 Next.js 應用並產生網站地圖。 + * - ``make -C Documentation html`` + - 建置 Sphinx 文件。 diff --git a/Documentation/source/zh_TW/index.rst b/Documentation/source/zh_TW/index.rst new file mode 100644 index 0000000..1dc6fb7 --- /dev/null +++ b/Documentation/source/zh_TW/index.rst @@ -0,0 +1,17 @@ +:orphan: + +Next Blog 文件(繁體中文) +============================= + +這是 Next Blog 文件的繁體中文版本。本文面向維護者、貢獻者與部署人員,說明專案的產品邊界、架構設計、前端約定、維運流程與貢獻規則。 + +.. toctree:: + :maxdepth: 2 + + introduction + getting-started + architecture + frontend + operations + contributing + reference diff --git a/Documentation/source/zh_TW/introduction.rst b/Documentation/source/zh_TW/introduction.rst new file mode 100644 index 0000000..8ca15d4 --- /dev/null +++ b/Documentation/source/zh_TW/introduction.rst @@ -0,0 +1,46 @@ +專案介紹 +======== + +Next Blog 是一個以閱讀體驗為核心的全端部落格平台。它使用 Next.js App Router 建置公開站台,使用 Payload CMS 管理內容,並透過 PostgreSQL、Drizzle ORM、better-auth 與 Fuma Comments 提供認證、留言與應用資料能力。 + +產品範圍 +-------- + +目前專案聚焦於以下能力: + +* 透過 Payload CMS 建立、編輯、發布文章; +* 呈現首頁、文章列表、文章詳情、標籤頁與個人頁面; +* 透過 Google 與 GitHub OAuth 登入; +* 為登入使用者提供留言功能; +* 輸出搜尋索引、RSS、網站地圖、JSON-LD 與 Open Graph 圖片; +* 提供 Newsletter 表單與 React Email 範本。 + +這個專案不是通用社群 CMS,而是一個受控的個人發布系統:公開側重閱讀,後台側重內容管理。 + +核心角色 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 20 34 36 + + * - 角色 + - 目標 + - 主要入口 + * - 訪客 + - 瀏覽和閱讀內容。 + - ``/``、``/posts``、``/posts/[slug]``、``/tags`` + * - 回訪讀者 + - 透過標籤篩選內容並使用訂閱入口。 + - ``/tags/[tag]``、``/rss.xml`` + * - 登入使用者 + - 發表留言與使用帳號相關操作。 + - ``/login``、``/posts/[slug]`` + * - 內容管理員 + - 維護、排程與發布內容。 + - ``/admin`` + +文件定位 +-------- + +``Documentation/source`` 是本專案正式的 Sphinx 文件來源目錄。``docs/`` 中的 Markdown 檔案可以作為調研或草稿材料,但穩定的工程文件應整理為 reStructuredText 後進入本目錄。 diff --git a/Documentation/source/zh_TW/operations.rst b/Documentation/source/zh_TW/operations.rst new file mode 100644 index 0000000..a513a10 --- /dev/null +++ b/Documentation/source/zh_TW/operations.rst @@ -0,0 +1,65 @@ +維運 +==== + +環境設定 +-------- + +關鍵環境變數在 ``src/env.js`` 中驗證: + +.. list-table:: + :header-rows: 1 + :widths: 34 44 + + * - 變數 + - 用途 + * - ``DATABASE_URL`` + - PostgreSQL 連線字串。 + * - ``RESEND_API_KEY`` + - Resend API key。 + * - ``RESEND_AUDIENCE_ID`` + - Resend audience ID。 + * - ``EMAIL_FROM`` + - 寄件信箱。 + * - ``BETTER_AUTH_SECRET`` + - better-auth secret,正式環境必填。 + * - ``GOOGLE_CLIENT_ID`` / ``GOOGLE_CLIENT_SECRET`` + - Google OAuth 憑證。 + * - ``GITHUB_CLIENT_ID`` / ``GITHUB_CLIENT_SECRET`` + - GitHub OAuth 憑證。 + +資料庫流程 +---------- + +Payload collection 變更: + +.. code-block:: bash + + pnpm payload:migrate:create + pnpm payload:migrate + pnpm payload:generate + +應用 schema 變更: + +.. code-block:: bash + + pnpm db:generate + pnpm db:migrate + +品質檢查 +-------- + +.. code-block:: bash + + pnpm lint + pnpm check + pnpm test + pnpm build + +文件建置 +-------- + +.. code-block:: bash + + make -C Documentation html + +產生的 ``Documentation/build`` 不應提交。 diff --git a/Documentation/source/zh_TW/reference.rst b/Documentation/source/zh_TW/reference.rst new file mode 100644 index 0000000..4da4c12 --- /dev/null +++ b/Documentation/source/zh_TW/reference.rst @@ -0,0 +1,57 @@ +參考 +==== + +常用命令 +-------- + +.. list-table:: + :header-rows: 1 + :widths: 26 50 + + * - 命令 + - 說明 + * - ``pnpm dev`` + - 啟動開發伺服器。 + * - ``pnpm build`` + - 建置正式應用。 + * - ``pnpm lint`` + - 執行內容連結驗證和 Biome lint。 + * - ``pnpm test`` + - 執行測試。 + * - ``pnpm db:migrate`` + - 套用 Drizzle 遷移。 + * - ``pnpm payload:generate`` + - 產生 Payload TypeScript 型別。 + +路由 +---- + +.. code-block:: text + + / + /posts + /posts/[slug] + /tags + /tags/[tag] + /about + /login + /admin + /api/auth/[...all] + /api/comments/[...comment] + /api/search + /rss.xml + +術語 +---- + +Payload + 管理文章、使用者、媒體和後台介面的 CMS。 + +Drizzle + 管理應用自有資料庫表的 TypeScript ORM。 + +better-auth + 提供 OAuth 和 Session 能力的認證庫。 + +BlogPost + ``src/lib/payload-posts.ts`` 回傳的前端正規化文章結構。 |
