Naming conventions
Naming is the load-bearing convention in a repository that will hold hundreds of documents. Ordering, navigation, cross-references and asset resolution are all derived from names, so a name is not cosmetic — it is configuration.
Everything on this page is enforced by pnpm content:structure.
Modules (top-level directories)
docs/<NN>-<kebab-case-topic>/
NNis a two-digit ordering prefix, assigned in tens for the core path (00,01,02, …) and reserved as follows:
| Range | Purpose |
|---|---|
00–11 | The linear curriculum, in reading order |
90–94 | Reference material |
95–98 | Glossary |
99 | Appendix |
- The prefix is never reused within a range. Renumbering is safe — prefixes do not appear in URLs — but it still churns the diff, so leave gaps rather than renumbering.
- The rest of the directory name does appear in the URL
(
03-branching-and-mergingpublishes at/branching-and-merging). Renaming one is a URL change and needs an entry insrc/data/redirects.ts.
Documents
<NN>-<kebab-case-title>.md
- Two-digit ordering prefix, unique within its directory. Increment in ones.
- Leave gaps when you expect insertions:
10,20,30inside a busy section is legitimate and saves renumbering later. - The prefix never appears in the URL. Docusaurus strips
NN-from every path segment, so03-branching-and-merging/04-merge-conflicts.mdpublishes at/branching-and-merging/merge-conflicts. Renumbering a file therefore does not change its URL — which is the entire point of the prefix scheme, and the reason renumbering is cheap. - Never write a link that includes a prefix.
pnpm content:linksrejects it. index.mdis the only permitted unprefixed name.- No underscores. Docusaurus excludes
_-prefixed paths from the build, so an underscore silently deletes your page.
Document ids
The id field equals the filename with the ordering prefix removed:
| File | id |
|---|---|
03-branching-and-merging/04-merge-conflicts.md | merge-conflicts |
08-internals/index.md | index |
This is checked. It means a cross-reference can be written from the filename without opening the file.
Sub-directories
Only two sub-directory names are permitted inside a module:
| Directory | Contents |
|---|---|
exercises/ | Short, standalone practice tasks |
labs/ | Multi-step scenarios of 30–90 minutes |
Maximum nesting is three levels below docs/. Anything deeper is unreachable in
the sidebar and indicates that a module needs splitting.
Anchors
Docusaurus generates heading anchors from the heading text, which means renaming a heading silently breaks every deep link to it. For any heading you expect to be linked from elsewhere, pin the anchor explicitly:
## Recovering from a hard reset {#recover-hard-reset}
Explicit anchor ids are kebab-case, short, and never renamed.
Assets
static/img/<module-directory>/<document-slug>/<descriptive-name>.<ext>
For example:
static/img/05-history-and-rewriting/interactive-rebase/todo-list-editor.png
static/img/05-history-and-rewriting/interactive-rebase/todo-list-editor@2x.png
- Lower-case kebab-case, no spaces, no dates, no version numbers in the name.
@2xis the only permitted suffix, for high-density raster variants.- Shared assets that genuinely belong to no single document live in
static/assets/diagrams/. - Full rules, including formats and size budgets, are in the assets guide.
Branches
<type>/<issue-number>-<short-description>
| Type | For |
|---|---|
content/ | New or edited lessons, exercises, cheat sheets |
fix/ | Corrections to existing content or tooling |
feat/ | Site features and components |
chore/ | Dependencies, configuration, housekeeping |
docs/ | Repository documentation outside docs/ |
Example: content/142-interactive-rebase-basics.
Commits
Conventional Commits, with the type and
scope vocabulary defined in commitlint.config.js and enforced on every commit
by a Git hook:
content(history): add interactive rebase lesson
Covers todo-list editing, squash, fixup and reword. Verified against
Git 2.47.1 on a clean repository.
Closes #142
- Type is one of
content,feat,fix,docs,style,refactor,perf,test,build,ci,chore,revert,i18n,a11y,assets. - Scope is the module short name (
history,branching,internals, …) or a tooling area (components,scripts,config). - Subject is imperative, lower case, no trailing period, under 100 characters.
contentcommits are excluded from the software changelog by design; the curriculum's own changes are announced inupdates/.
Components
- Directory and component both
PascalCase:src/components/GitGraph/index.tsx. - Styles always at
styles.module.cssbeside the component. - Props interfaces named
<ComponentName>Propsand exported. - Every component is re-exported from
src/components/index.tsand registered insrc/theme/MDXComponents.tsx. Missing either one means it works in some files and not others, which is worse than not existing.
CSS custom properties
Project tokens are prefixed --gm- and defined only in src/css/custom.css.
Infima's own --ifm- variables may be overridden there but never invented.
Components reference tokens; they never hard-code a colour.