Documentation Linter Guide โ
Date: 2026-01-17
Status: โ
Active
Overview โ
The documentation linter automatically checks that all markdown (.md) files are:
- Organized - Located in allowed directories per documentation structure guidelines
- Non-duplicated - Exist in only one location (single source of truth principle)
This prevents rogue documentation files from being scattered throughout the repository and catches unintended copies that create maintenance problems.
See .github/copilot-instructions.md for documentation organization guidelines.
Quick Start โ
Run the linter โ
# Check documentation organization
npm run lint:docs
# Strict mode (fails if issues found)
npm run lint:docs:strict
# Integrated with main linter
npm run lintWhat It Checks โ
The documentation linter validates that all .md files satisfy two requirements:
1. Location Check โ
All files must be in allowed locations:
โ Root-level files (allowed) โ
README.md- Main project READMECHANGELOG.md- Root changelog (synced withdocs/CHANGELOG.md)
โ Directory patterns (allowed) โ
docs/**/*.md- Primary documentation location (all user-facing docs).github/**/*.md- GitHub-specific documentation (workflows, actions, etc.)discord-bot/**/*.md- Discord bot documentation (if added)functions/**/*.md- Firebase Cloud Functions documentation (if added)
Script documentation should live in docs/engineering/guides/SCRIPTS_GUIDE.md (not in scripts/README.md).
โ Not allowed โ
./*.md(except README.md and CHANGELOG.md)- Markdown files scattered in arbitrary directories
- Feature docs outside
docs/features/ - Engineering docs outside
docs/engineering/
2. Duplicate Files Check โ
All markdown files must be unique by filename - no file should exist in multiple locations with the same name. This enforces the "single source of truth" principle.
Examples of duplicates found:
README.mdin multiple directories โ Keep only in appropriate locationCHANGELOG.mdin both root anddocs/โ Consolidate to one locationIMPLEMENTATION_SUMMARY.mdin 3+ locations โ Consolidate and link to single source
When duplicates are found:
- Linter reports all locations where the file appears
- You must identify which is the authoritative version
- Delete duplicates and update cross-references
- Use links instead of copying content
Documentation Organization โ
When creating new documentation, follow these rules:
Feature Documentation โ
docs/features/{feature-name}/
โโโ QUICK_START.md # 5-minute quick start
โโโ {FEATURE_NAME}.md # Complete spec
โโโ IMPLEMENTATION.md # Developer guide (optional)
โโโ TESTING_GUIDE.md # QA procedures (optional)Examples: docs/features/wave/, docs/features/lantern-hub/, docs/features/profile/
Engineering Documentation โ
docs/engineering/{subdomain}/
โโโ {TOPIC}_{TYPE}.mdSubdomains:
architecture/- System design, tech stack, patterns, APIsdeployment/- Deployment guides, CI/CD, infrastructuresecurity/- Encryption, security architecture, incident responseguides/- Onboarding, troubleshooting, utility setuptesting/- Testing strategies, debugging guidesmobile/- Mobile-specific optimizations
Business & Governance โ
docs/business/
โโโ BUSINESS.md
โโโ PILOT_STRATEGY.md
โโโ COFOUNDER_FEEDBACK_POA.md
โโโ ...
docs/governance/
โโโ GOVERNANCE.md
โโโ GOVERNANCE_QUICK_REFERENCE.md
โโโ IMMUTABLE_RIGHTS.md
โโโ ...Handling Duplicates โ
When the linter detects duplicate filenames:
1. Identify the Source of Truth โ
The linter output shows all locations where a file appears:
๐ IMPLEMENTATION_SUMMARY.md
โข docs/archive/worklog-historical/IMPLEMENTATION_SUMMARY.md
โข docs/engineering/github/workflows/ai-triage/IMPLEMENTATION_SUMMARY.md
โข docs/engineering/github/workflows/discord/IMPLEMENTATION_SUMMARY.mdDetermine which is the canonical/authoritative version.
2. Update Cross-References โ
If other files link to duplicates, update them to point to the source:
Before:
[See implementation](../../engineering/github/workflows/discord/IMPLEMENTATION_SUMMARY.md)After:
[See implementation](../../engineering/github/workflows/IMPLEMENTATION_SUMMARY.md)3. Delete Duplicate Files โ
rm docs/archive/worklog-historical/IMPLEMENTATION_SUMMARY.md
rm docs/engineering/github/workflows/discord/IMPLEMENTATION_SUMMARY.md4. Common Duplicate Patterns & Solutions โ
README.md in multiple directories โ
- Keep: Module-level READMEs (e.g.,
discord-bot/README.md) - Remove: Duplicates in subdirectories
- Rule: One README per module, none in subdirectories; scripts are documented in
docs/engineering/guides/SCRIPTS_GUIDE.md
CHANGELOG.md (Root vs docs/) โ
- Keep:
docs/CHANGELOG.mdas primary - Sync/Remove: Root version should mirror docs/ or be removed
- Best Practice: Single source in
docs/CHANGELOG.md
IMPLEMENTATION_SUMMARY.md โ
- Issue: Multiple copies document same thing differently
- Solution: Keep in one location (e.g., per feature area)
- Link: From other locations, use relative links instead
QUICK_START.md & DEPLOYMENT.md โ
- Rule: One per feature/module in appropriate
docs/subdirectory - Link: Use cross-references between docs instead of copying
Configuration โ
The linter is configured using .docs-linter-config.js which controls all linting behavior.
Main Configuration File โ
File: .docs-linter-config.js
module.exports = {
// Root-level files that are allowed
rootFiles: ['README.md'],
// Directory patterns where markdown is allowed
allowedPaths: [
'docs/**/*.md',
'.github/**/*.md',
// ... more patterns
],
// Directories to completely ignore
excludePatterns: [
'node_modules/**/*.md',
'.git/**/*.md',
'dist/**/*.md',
// ... more patterns
],
// Files allowed to exist in multiple locations (duplicate exclusions)
duplicateExclusions: [
'README.md', // Per-module README files are expected
'CHANGELOG.md', // Per-directory changelogs are acceptable
'.gitignore',
'.prettierignore',
'.eslintignore',
],
// Error reporting modes
strictMode: false,
showSuggestions: true,
};Script Implementation โ
File: scripts/lint-docs.js
- Loads configuration from
.docs-linter-config.js - Applies exclusions when checking for duplicates
- Falls back to safe defaults if config is missing
- Provides helpful error messages with resolution steps
Modifying Configuration โ
To change allowed locations or duplicate exclusions:
Edit
.docs-linter-config.js- Add/remove paths from
allowedPaths - Add/remove filenames from
duplicateExclusions - Update exclusion patterns as needed
- Add/remove paths from
Test changes
bashnpm run lint:docsDocument in changelog
bashnpm run changelog:consolidate # or update docs/CHANGELOG.md
Exclusion Lists โ
Directory Exclusions โ
These directories are automatically ignored by the linter:
node_modules/**/*.md- Dependencies.git/**/*.md- Git historydist/**/*.md- Build artifactsbuild/**/*.md- Build output.next/**/*.md- Next.js artifacts.github/workflows/test-data/**/*.md- Test data
Duplicate Exclusions โ
These files are allowed to exist in multiple locations:
README.md- Per-module documentationCHANGELOG.md- Per-directory change logs.gitignore- Per-directory git ignore rules.prettierignore- Per-directory prettier config.eslintignore- Per-directory eslint config
Adding New Allowed Paths โ
If you need to allow markdown files in a new location (e.g., for a new module):
Edit
.docs-linter-config.js:javascriptallowedPaths: [ 'docs/**/*.md', '.github/**/*.md', 'new-module/**/*.md', // โ Add here ]Test the change
bashnpm run lint:docsDocument in changelog
markdown- Add support for new-module documentation in linter
Adding Duplicate Exclusions โ
If you have a file that should exist in multiple locations:
Edit
.docs-linter-config.js:javascriptduplicateExclusions: [ 'README.md', 'CHANGELOG.md', 'MY_FILE.md', // โ Add here ]Test the change
bashnpm run lint:docsDocument why this file legitimately has duplicates
Integration with Main Linter โ
The documentation linter is automatically included when you run:
npm run lintIt runs before ESLint and reports organization issues alongside code linting issues.
Exit codes:
0- All documentation is properly organized and has no duplicates1- Issues found (if using--strictflag)
Exit Codes & Modes โ
Warning Mode (default) โ
npm run lint:docs
# Always exits with 0, even if issues found
# Use this for informational checksStrict Mode โ
npm run lint:docs:strict
# Exits with 1 if issues found
# Use this in CI/CD pipelines to enforce complianceExample Output โ
โ Success โ
โ
All markdown files are in the correct locations!
โ
No duplicate markdown files found!โ Organization Issue โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๏ธ DOCUMENTATION ORGANIZATION ISSUE
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Found 1 markdown file(s) outside allowed locations:
โ API_GUIDE.md
๐ ALLOWED LOCATIONS:
Root-level:
โข README.md
โข CHANGELOG.md
Path patterns:
โข docs/**/*.md
โข .github/**/*.md
โข discord-bot/**/*.md
โข functions/**/*.md
๐ ORGANIZATION RULES:
โข All user-facing documentation โ docs/
โข Feature docs โ docs/features/{feature-name}/
โข Engineering docs โ docs/engineering/{subdomain}/
โข Business docs โ docs/business/
โข Governance docs โ docs/governance/
โข GitHub workflow docs โ .github/workflows/docs/
โข Script documentation โ docs/engineering/guides/SCRIPTS_GUIDE.md (no README in scripts/)
See docs/DOCS_INDEX.md and .github/copilot-instructions.md for details.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ Duplicate Files โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๏ธ DUPLICATE MARKDOWN FILES DETECTED
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Documentation should exist in only one location (single source of truth):
๐ README.md
โข .github/workflows/README.md
โข README.md
โข discord-bot/README.md
๐ IMPLEMENTATION_SUMMARY.md
โข docs/engineering/github/workflows/ai-triage/IMPLEMENTATION_SUMMARY.md
โข docs/engineering/github/workflows/discord/IMPLEMENTATION_SUMMARY.md
โข docs/features/frens/IMPLEMENTATION_SUMMARY.md
๐ฏ RESOLUTION:
1. Identify which copy is the "source of truth"
2. Move or delete the duplicate copies
3. Update links in other files to point to the single source
4. Consider using VitePress with proper linking instead of copying
๐ BEST PRACTICES:
โ Keep README.md files in module/package directories
โ Keep detailed docs in appropriate docs/ subdirectories
โ Link between docs using relative paths (no copying)
โ Use VitePress for cross-referencing between docs
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโFix Examples โ
Move documentation into docs/ โ
Before:
lantern_app/
โโโ API_GUIDE.md โ Not allowed
โโโ INTEGRATION.md โ Not allowed
โโโ docs/
โโโ (proper location)After:
lantern_app/
โโโ docs/
โโโ engineering/
โโโ API_GUIDE.md โ
Allowed
โโโ INTEGRATION.md โ
AllowedRelocate feature documentation โ
Before:
lantern_app/
โโโ WAVE_FEATURES.md โ Not allowedAfter:
lantern_app/
โโโ docs/
โโโ features/
โโโ wave/
โโโ WAVE_FEATURES.md โ
Allowed (rename to feature-appropriate name)Troubleshooting โ
"Documentation file X is not allowed" โ
Solution: Move the file to the appropriate docs/ subdirectory per the organization rules above.
"I need markdown files in a new location" โ
Solution: Update scripts/lint-docs.js with the new pattern and document it in docs/CHANGELOG.md.
Linter is too strict โ
Solution: Use warning mode for informational checks:
npm run lint:docs # Warning mode (doesn't fail)
npm run lint:docs:strict # Strict mode (fails on issues)Related Documentation โ
- Documentation Guidelines - Full documentation standards
- DOCS_INDEX.md - Complete documentation index
- CHANGELOG.md - Project changelog
- CONTRIBUTING.md - Contribution guidelines
See Also โ
- Changelog Workflow - How to maintain CHANGELOG.md
- Code Linting Guide - Main linting practices (if exists)