Documentation Guide
This guide defines how documentation is organized and managed in this project.
Last Updated: 2026-01-25
Directory Structure
docs/
├── DOCS_GUIDE.md # This file
├── guides/ # Development guides and standards
│ ├── INDEX.md
│ └── features/ # Feature-specific documentation
├── issues/ # Active issues and errors
│ └── resolved/ # Resolved issues
└── plans/ # Implementation plans
├── INDEX.md # Main plans index
├── backlog/ # Planned but not yet active
│ └── INDEX.md
├── archive/ # Completed plans
├── reports/ # Admin-facing completion reports
│ └── INDEX.md
└── templates/ # Plan and report templates
├── PLAN_TEMPLATE.md
├── PLAN_TEMPLATE_SIMPLE.md
└── COMPLETION_REPORT_TEMPLATE.md
Plans
Lifecycle
Plans follow this workflow:
Backlog → Active → Archive
↘ Report (for admin users)
| Stage | Location | Purpose |
|---|---|---|
| Backlog | docs/plans/backlog/ | Defined plans waiting to be prioritized |
| Active | docs/plans/ | Currently being worked on |
| Archive | docs/plans/archive/ | Development complete |
| Report | docs/plans/reports/ | Admin-facing completion summary |
Templates
Use templates from docs/plans/templates/:
| Template | Use Case |
|---|---|
PLAN_TEMPLATE.md | Complex, multi-phase features |
PLAN_TEMPLATE_SIMPLE.md | Simple fixes and improvements |
COMPLETION_REPORT_TEMPLATE.md | Admin-facing summary after completion |
Naming Convention
Plans are numbered sequentially: NNN-descriptive-name.md
Examples:
001-client-portal-plan.md212-audit-system-improvements.md212a-scoring-response-types.md(sub-plan)
Numbering
Run the script to get the next available plan number:
php scripts/util/get-next-plan-number.php
This scans docs/plans/, docs/plans/archive/, and docs/plans/backlog/ and returns the next number.
Workflow
Starting a new plan:
- Choose appropriate template from
docs/plans/templates/ - Run
php scripts/util/get-next-plan-number.phpto get next number - Save to
docs/plans/backlog/if not starting immediately, ordocs/plans/if active
Activating a backlog plan:
- Move file from
docs/plans/backlog/todocs/plans/ - Update status to "In Progress"
- Update INDEX files in both directories
Completing a plan:
- Move file from
docs/plans/todocs/plans/archive/ - Update status to "Complete"
- Create completion report in
docs/plans/reports/(for significant features) - Update feature guide in
docs/guides/features/ - Commit changes
Completion Reports
Purpose
Completion reports are written for admin users, not developers. They explain:
- What's new and how to access it
- Step-by-step usage instructions
- Changes to existing workflows
- Known limitations
Location
docs/plans/reports/YYYY-MM-DD-feature-name.md
When to Create
Create a completion report for:
- New features visible to admin users
- Significant changes to existing functionality
- New settings or configuration options
Skip for:
- Internal refactoring
- Bug fixes
- Developer-only changes
Issues
Location
- Active issues:
docs/issues/ - Resolved issues:
docs/issues/resolved/
Naming Convention
Use descriptive kebab-case names: descriptive-issue-name.md
Examples:
login-redirect-loop.mdinvoice-total-calculation-error.md
Lifecycle
- Create issue in
docs/issues/when error/problem is encountered - Update issue as investigation and fixes progress
- When resolved, move to
docs/issues/resolved/
Issue Template
# Issue Title
## Description
Brief description of the issue.
## Steps to Reproduce
1. Step one
2. Step two
## Expected Behavior
What should happen.
## Actual Behavior
What actually happens.
## Investigation Notes
Notes added during investigation.
## Resolution
How the issue was resolved (filled in when moving to resolved/).
Guides
Location
- Development guides:
docs/guides/ - Feature guides:
docs/guides/features/
Updating Guides
ALWAYS update the appropriate feature guide after implementing or modifying any feature:
- Find existing guide in
docs/guides/features/ - If none exists, create one following existing format
- Update
docs/guides/features/INDEX.md - Update
docs/guides/INDEX.mdif adding new guide
Product Documentation (Plan 348 §5.4)
docs/product/** is the customer-facing documentation surface —
not internal engineering notes. These markdown files are rendered
publicly on the marketing site (Plan 348 §5.2) at routes like
/product, /plans, /plans/basic, /addons/online-store,
/managed-services, and /product/faq, and will also feed the
portal help center (Plan 348 Phase 6).
Directory structure
docs/product/
├── README.md # Contributor entry point
├── overview.md # /product landing (What is ScopeForged Websites?)
├── faq.md # /product/faq
├── plans/
│ ├── comparison.md # /plans (three-plan compare table)
│ ├── basic.md # /plans/basic
│ ├── plus.md # /plans/plus
│ └── unlimited.md # /plans/unlimited
├── addons/
│ ├── online-store.md # /addons/online-store
│ ├── ai-chatbot.md # /addons/ai-chatbot
│ ├── scheduling-bookings.md # /addons/scheduling-bookings
│ └── custom-integration.md # /addons/custom-integration
├── managed-services/
│ └── overview.md # /managed-services
├── how-tos/ # Portal /help/how-tos/{slug} (Phase 6)
│ └── *.md
├── internal/ # Ops runbooks — NOT publicly rendered
│ └── *.md
└── legal/ # Legal copy source — separate rendering
└── *.md
Voice
- Second-person, plain English. "You can change plans any time" not "customers may modify their subscription".
- Concrete prices and concrete feature names. "$29/mo" not "affordable pricing"; "Contact forms in your inbox" not "lead capture capabilities".
- No dev jargon. Say "sign in with your email" not "authenticate via the auth provider".
Rendering pipeline
Each doc is rendered by {@see \App\Services\Marketing\ProductDocsService}:
- Optional YAML frontmatter (
title,description) is extracted. Falls back to the first# H1for title, first paragraph for description. - Markdown → HTML via CommonMark with
html_input=strip— a raw<script>in a markdown source is refused at parse time. - HTML → sanitized HTML via HTMLPurifier with an explicit allowlist (headings, paragraphs, lists, tables, code, images, links).
- Cross-doc
.mdlinks rewrite to the mapped public URLs via {@see \App\Services\Markdown\RelativeLinkRewriter}. Unmapped links degrade to plain text so a broken hyperlink can't ship. - Cached under
docs:product:v1:{sha1(file_content)}— content- addressed, so a content edit reads a new key without explicit invalidation.
Authoring workflow
- Anyone can PR a doc change.
- Content-only PRs (typos, wording, examples, table adjustments): require 1 approval from the product owner. Engineering review not required.
- Structural changes (new sections, route additions, template changes): require product-owner + engineering approval.
- When a plan changes a product definition — e.g. reprices an
addon, retires a feature — update the corresponding
docs/product/**file in the same PR. The wizard/paywall UI and the docs are one product surface with two rendering pipelines; they should not drift.
Adding a new doc
Three files touch the contract:
- Create the markdown file under
docs/product/**/. - Add a route in
routes/marketing.phpbinding the URL slug toProductDocsController::show($request, 'your/path.md'). - Add the same path → URL mapping to
App\Services\Marketing\ProductDocsService::PATH_TO_URL_MAPso cross-doc links can rewrite to it.
The ProductDocsRoutingTest walks every mapped route on every CI
run — a missing doc or a broken frontmatter block trips the test
before it can trip production.
Deploy pre-warm
php artisan docs:product:prewarm (wired into
scripts/deploy/deploy.cjs when Phase 5.1 finishes deploying)
walks every mapped path, renders it into cache, and writes
storage/app/docs-manifest.json listing every current content
hash. Optional nightly docs:product:gc evicts stale cache keys.
General Guidelines
- Keep documentation concise and actionable
- Update docs as part of every task
- Commit documentation changes with related code changes
- Use markdown formatting consistently
- Always update INDEX files when adding/moving documents
Related Documentation
- Documentation Standards - Writing guidelines
- Plans Index - All plans
- Backlog Index - Planned features
- Guides Index - Development guides