Quy ước repository
Cách tổ chức, viết, liên kết và kiểm tra tài liệu trong repository OpenTelemetry Learning.
Phạm vi của trang này
Đây là quy ước của repository hiện tại, không phải một template chung cho mọi
dự án OpenTelemetry. Repository này là website docs-only dùng Next.js,
Fumadocs và static export. Hãy ưu tiên cây thư mục, script và cấu hình đang có
thay vì tự tạo thư mục examples/, configs/ hoặc một app demo chưa tồn tại.
Mục lục
- Tổng quan repository
- Cây thư mục thực tế
- Nội dung docs và navigation
- Quy ước đặt tên và routing
- Frontmatter, mục lục và liên kết
- Components và code blocks
- Quy trình thêm hoặc sửa trang
- Tệp được sinh tự động
- Checklist review
Tổng quan repository
otel-learn là website tài liệu tiếng Việt về OpenTelemetry. Đây là repository
docs-only: source chính là các trang MDX trong content/docs/, còn src/ chứa
ứng dụng Next.js và lớp tích hợp Fumadocs để đọc các trang đó.
Next.js được cấu hình với output: 'export'. Nghĩa là quá trình build tạo các
tệp HTML tĩnh thay vì yêu cầu Next.js server runtime khi deploy. dist/ là thư
mục output được đặt tên riêng trong next.config.mjs. Route docs ở root nên
website mở trực tiếp vào docs, không có landing page riêng.
Một trang MDX đi qua pipeline sau:
content/docs/*.mdx
│
▼
fumadocs-mdx ──► .source/ (generated source)
│
▼
src/lib/source.ts + Next.js
│
▼
/<category>/<slug>/ ──► dist/ (static export sau build)source.config.ts khai báo collection ở content/docs, dùng pageSchema cho
frontmatter và metaSchema cho navigation metadata. Cấu hình này cũng bật
remarkMdxMermaid, tức plugin chuyển fenced block mermaid thành component
Mermaid trong pipeline MDX.
Cây thư mục thực tế
Các thư mục và file source chính hiện có:
Trong cây trên, các category được liệt kê theo content/docs/meta.json. Mỗi
category hiện có một meta.json riêng. Các trang chi tiết khác nằm trong cùng
các folder đó; không nên suy ra một thư mục con chỉ vì một chủ đề có thể cần nó
trong tương lai.
Nội dung docs và navigation
Trang MDX
Mỗi file .mdx dưới content/docs/ là một trang tài liệu. index.mdx đại
diện cho trang đầu của category. Ví dụ:
content/docs/getting-started/index.mdxtạo route/getting-started/.content/docs/getting-started/environment.mdxtạo route/getting-started/environment/.content/docs/fundamentals/index.mdxtạo route/fundamentals/.
src/lib/source.ts gọi docs.toFumadocsSource() rồi đưa collection cho
Fumadocs loader. src/app/[[...slug]]/page.tsx lấy page theo slug, render
frontmatter và body MDX. Vì vậy, nội dung trang nên nằm trong content/docs/;
không copy nội dung docs vào component React.
Tệp meta.json
content/docs/meta.json quyết định thứ tự các category trong navigation. Ví dụ,
slug getting-started trỏ tới folder content/docs/getting-started/.
content/docs/getting-started/meta.json quyết định thứ tự các trang trong nhóm
Bắt đầu:
{
"title": "Bắt đầu",
"pages": [
"index",
"learning-path",
"environment",
"first-trace",
"local-stack",
"repository-conventions",
"next-steps"
]
}Giá trị trong pages là slug hoặc tên file bỏ phần mở rộng .mdx. Không thêm
.mdx vào giá trị này. Khi đổi thứ tự, hãy nhớ rằng thứ tự đó cũng là thứ tự
người học nhìn thấy trong sidebar.
Khi thêm trang vào một category, cập nhật meta.json của category đó. Nếu
trang không cần xuất hiện trong sidebar, trước tiên phải xác nhận đó là chủ ý;
đừng tạo một file meta.json mới ở nơi không có category tương ứng.
Quy ước đặt tên và routing
- Dùng chữ thường cho tên folder và file.
- Dùng kebab-case cho slug nhiều từ, ví dụ
first-trace.mdxvàrepository-conventions.mdx. - Giữ tên
index.mdxcho trang đầu category. - Giữ đúng tên
meta.json,source.config.tsvà các file cấu hình đã có. - Không đổi tên file chỉ để dịch slug. Slug ổn định giúp link và bookmark của người đọc không bị hỏng.
next.config.mjs bật trailingSlash: true, nên route public luôn có dấu /
ở cuối. Mapping quan trọng là:
content/docs/<category>/<page>.mdx
│
└── /<category>/<page>/
content/docs/<category>/index.mdx
│
└── /<category>/Route của một trang không phải là đường dẫn tuyệt đối trên filesystem. Trong
nội dung, dùng route public như /getting-started/environment/; khi sửa source,
dùng path file như content/docs/getting-started/environment.mdx.
Frontmatter, mục lục và liên kết
Frontmatter
Mỗi trang phải có YAML frontmatter ở đầu file. pageSchema trong
source.config.ts dùng frontmatter đó để tạo metadata của Fumadocs.
---
title: "Tên trang"
description: "Một câu mô tả ngắn cho kết quả tìm kiếm và phần đầu trang."
---title được render thành H1 bởi layout docs. Vì vậy, không thêm # Tên trang
ở body. Sau frontmatter, có thể đặt một <Callout> giới thiệu phạm vi hoặc
đối tượng đọc trước phần ## Mục lục.
description nên nói rõ người đọc sẽ làm được gì hoặc hiểu điều gì sau khi đọc.
Đừng đặt một đoạn dài hoặc nhiều ý không liên quan vào trường này.
Mục lục thủ công
Mỗi trang cần một mục ## Mục lục viết tay. Đặt nó sau frontmatter và phần
callout mở đầu, trước section nội dung đầu tiên. Mục lục phải liệt kê mọi
heading ## và ### thật sự có trong trang, với ### thụt vào dưới ##:
## Mục lục
- [Tổng quan](#tổng-quan)
- [Cài đặt](#cài-đặt)
- [Kiểm tra](#kiểm-tra)Fumadocs tạo anchor bằng cách viết thường, thay khoảng trắng bằng dấu gạch ngang và bỏ dấu câu; chữ tiếng Việt có dấu được giữ lại. Sau khi đổi heading, phải đổi anchor tương ứng trong mục lục. Không dùng H1 trong body và không đưa các heading không tồn tại vào mục lục.
Liên kết nội bộ
Liên kết đến trang docs bằng route public tuyệt đối và luôn có trailing slash:
Đọc thêm [Nền tảng](/fundamentals/) trước khi instrument ứng dụng.
<Cards>
<Card
title="Chuẩn bị môi trường"
href="/getting-started/environment/"
description="Kiểm tra toolchain trước khi thực hành."
/>
</Cards>Kiểm tra route bằng cách đối chiếu file trong content/docs/. Ví dụ,
/fundamentals/telemetry-pipeline/ chỉ hợp lệ khi
content/docs/fundamentals/telemetry-pipeline.mdx tồn tại. Không link tới
placeholder, file hoặc folder chưa có trong repository. Link ngoài dùng URL đầy
đủ và chỉ nên thêm khi nguồn đó thực sự cần thiết.
Components và code blocks
Components Fumadocs
Dùng component khi nó làm rõ cấu trúc, không dùng component chỉ để trang trí.
Các component mặc định như Callout, Cards và Card đã được cung cấp qua
src/components/mdx.tsx, nên các trang hiện tại không import chúng.
Với component không mặc định, dùng đúng import ở đầu file. Ví dụ trang có cây thư mục dùng:
import { File, Folder, Files } from 'fumadocs-ui/components/files';Các quy ước đang dùng:
<Callout type="info|warn|error|idea" title="...">cho ghi chú, cảnh báo, lỗi hoặc mẹo. Nêu hành động cụ thể sau cảnh báo.<Steps>và<Step>cho quy trình theo thứ tự. Mỗi<Step>thường chứa một heading###và một hành động có thể làm được.<Cards>và<Card>để nối sang các bài liên quan ở cuối trang.hrefphải là route có trailing slash.<Files>,<Folder>và<File>cho cây thư mục đã kiểm chứng.- Fenced block
mermaidđượcremarkMdxMermaidxử lý và componentMermaidtrongsrc/components/mdx.tsxrender ở phía client. Giữ diagram ở dạng text để dễ review và version control.
Code blocks
Chọn language tag phù hợp để Shiki tô màu và để người đọc biết shell hoặc ngôn ngữ đang dùng:
bashcho lệnh terminal trên Linux/macOS.powershellkhi cú pháp Windows khác đáng kể.ts,tsx,js,jsoncho source hoặc dữ liệu cấu hình thực sự có trong repository.yamlcho cấu hình khi bài học đã cung cấp file YAML tương ứng.textcho output, cây thư mục hoặc giá trị không có ngôn ngữ.
Ví dụ lệnh phải copy được và không chứa prompt $. Chú thích nguyên nhân hoặc
kết quả ở ngoài code block. Một block nên phục vụ một mục đích; tách lệnh cài,
lệnh chạy và lệnh kiểm tra thay vì gom một đoạn shell dài khó đọc.
Không trình bày một file cấu hình tưởng tượng như thể nó đã tồn tại. Nếu chỉ minh họa cú pháp, nói rõ đó là ví dụ tối giản và chỉ dùng tên binding, port hoặc path đã được giải thích trong bài.
Quy trình thêm hoặc sửa trang
Sửa một trang có sẵn
Đọc context trước khi sửa
Mở meta.json của category, trang liền kề và các route mà trang đang link tới.
Giữ title, độ sâu heading, thuật ngữ tiếng Việt và mức chi tiết nhất quán với
nhóm. Nếu trang là placeholder, thay nội dung placeholder thay vì tạo một file
trùng chủ đề.
Sửa nội dung MDX
Giữ frontmatter ở đầu file, không thêm H1 body, cập nhật mục lục thủ công sau
khi chốt heading. Khi dùng component, kiểm tra import và prop theo component
đang được đăng ký trong src/components/mdx.tsx.
Kiểm tra link và ví dụ
Đối chiếu từng link nội bộ với file MDX hoặc index.mdx tương ứng. Chạy ví dụ
ở mức có thể kiểm chứng. Nếu ví dụ phụ thuộc một Collector, backend, runtime
hoặc file Compose chưa có trong repository, nói rõ dependency đó thay vì viết
như thể nó đã được commit.
Thêm một trang mới
- Chọn category đã tồn tại trong
content/docs/. Dùng tên file chữ thường, kebab-case, có phần mở rộng.mdx. - Tạo frontmatter
titlevàdescription. Viết phần nội dung không có H1, rồi thêm## Mục lụcvới anchor của mọi##và###. - Thêm slug bỏ
.mdxvào đúng mảngpagestrongmeta.jsoncủa category. Đặt slug ở vị trí phản ánh thứ tự học. - Dùng route public có trailing slash khi link tới trang mới. Ví dụ,
new-page.mdxtronggetting-startedcó route/getting-started/new-page/. - Không tạo thư mục
examples/,configs/hay runtime project chỉ để chứa một đoạn minh họa nếu repository chưa có quyết định tổ chức cho chúng.
Chạy các kiểm tra
Các script này có trong package.json hiện tại:
npm run lint
npm run types:check
npm run build
npm run previewÝ nghĩa của từng lệnh:
| Lệnh | Mục đích |
|---|---|
npm run lint | Chạy ESLint cho source code. |
npm run types:check | Chạy fumadocs-mdx, Next typegen và TypeScript không phát sinh output. |
npm run build | Build Next.js static export vào dist/. |
npm run start | Phục vụ dist/ bằng serve; cần build trước, giống npm run preview. |
npm run preview | Phục vụ dist/ bằng serve; cần build trước. |
Trong quá trình phát triển, npm run dev giúp xem nội dung nhanh. Trước khi
mở pull request, chạy các kiểm tra phù hợp và ghi nhận lỗi nếu một kiểm tra
không thể chạy trong môi trường hiện tại. Không sửa generated file để làm cho
kiểm tra tạm thời qua.
Tệp được sinh tự động
Các path sau không phải nơi viết source tài liệu:
| Path | Nguồn sinh | Quy tắc |
|---|---|---|
.source/ | fumadocs-mdx, được gọi bởi postinstall và types:check | Không sửa hoặc commit thủ công. |
dist/ | next build, theo distDir trong next.config.mjs | Chỉ là static build output; không sửa để thay đổi docs. |
.next/ | Next.js trong development/build | Cache và output nội bộ; không sửa. |
.gitignore của repository đã bỏ qua .source, dist/ và .next/. Nếu
source collection lỗi, sửa MDX, meta.json, source.config.ts hoặc component
nguồn tương ứng rồi chạy lại lệnh sinh. Những file sinh tự động có thể thay đổi
sau mỗi lần cài hoặc build nên không dùng chúng làm nơi review nội dung.
Checklist review
Trước khi gửi thay đổi tài liệu, tự kiểm tra:
- File nằm đúng category dưới
content/docs/và tên file là kebab-case. - Frontmatter có
titlevàdescriptionrõ ràng. - Không có H1 viết bằng
#trong body. - Có
## Mục lụcngay sau phần mở đầu và mục lục chứa đủ mọi##/###. - Anchor trong mục lục khớp heading sau khi bỏ dấu câu.
- Jargon được giải thích ở lần xuất hiện đầu tiên.
- Link nội bộ trỏ tới route hoặc file thật, có trailing slash với route docs.
- Nếu thêm trang, slug đã được thêm đúng
meta.jsonvà đúng thứ tự sidebar. - Component có syntax/import đúng; fenced code block có language tag phù hợp.
- Không bịa file Compose, thư mục ví dụ, binding hoặc runtime chưa tồn tại.
- Không sửa
.source/,dist/hoặc.next/. - Đã chạy
npm run lintvànpm run types:check; nếu cần static export, chạy thêmnpm run buildrồinpm run preview.