Appearance
Documentation System Guide
How to work with Vulcan's documentation.
Overview
Vulcan uses VitePress for documentation:
- Fast development with hot-reload
- Vue 3 powered components
- Markdown-centric with Vue enhancements
- Static site generation for GitHub Pages
Separate Dependencies (Vue 2/3 Isolation)
The documentation has its own package.json in docs/ — separate from the Rails app. This is intentional:
- Rails app: Vue 2.7.16 + Bootstrap 4 (in root
package.json) - Documentation: VitePress with Vue 3 (in
docs/package.json)
The root package.json scripts (yarn docs:dev, etc.) handle this transparently — they auto-install docs dependencies before running VitePress. You never need to cd docs manually.
Commands (from project root)
bash
yarn docs:dev # Start dev server at http://localhost:5173/vulcan/
yarn docs:build # Build static site to docs/.vitepress/dist/
yarn docs:preview # Preview the production build locallyDirectory Structure
Publishing is structural: srcDir points VitePress at the curated site root docs/site/, so everything under it is published and nothing outside it can be. There is no exclude list.
docs/
├── .vitepress/
│ ├── config.mjs # Sidebar, nav, VitePress settings (srcDir: 'site')
│ └── theme/ # Custom theme (Mermaid, styles)
├── package.json # Docs-specific dependencies (Vue 3)
├── yarn.lock # Dependency lock file
├── site/ # THE PUBLISHED SITE ROOT — every page lives here
│ ├── index.md # Homepage
│ ├── about.md # About page
│ ├── api/ # API documentation
│ ├── data/ # Generated data (openapi.json — gitignored)
│ ├── deployment/ # Deployment + upgrade guides
│ ├── development/ # Developer documentation (this file)
│ ├── disa-process/ # DISA STIG vendor process
│ ├── getting-started/ # Setup, config, env vars, troubleshooting
│ ├── public/ # Static assets (logos, favicons, attachments)
│ ├── release-notes/ # Per-version release notes
│ ├── security/ # Security controls + compliance
│ └── user-guide/ # End-user documentation
├── plans/ # Internal working docs — never published
├── decisions/ # Architecture decision records — never published
├── research/ # Research notes — never published
└── superpowers/ # Development artifacts — never publishedAdding Documentation
Creating New Pages
- Create a
.mdfile in the appropriate directory underdocs/site/— a page outside the site root is never built - Add frontmatter if needed:yaml
--- title: Page Title description: Page description --- - Write content using Markdown
Updating Navigation
Edit .vitepress/config.mjs to add pages to the sidebar (links are relative to the site root, so docs/site/development/setup.md is /development/setup):
javascript
{
text: "Development",
items: [
{ text: "Setup", link: "/development/setup" },
{ text: "Your New Page", link: "/development/your-page" },
],
},Both the top-level nav and the path-specific sidebar sections need to be updated — the config has two sidebar definitions (one for the main nav, one for path-specific).
Markdown Features
Standard Markdown plus VitePress extensions:
Custom Containers
markdown
::: tip
Helpful information
:::
::: warning
Important caveat
:::
::: danger
Critical warning
:::Mermaid Diagrams
markdown
```mermaid
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Do this]
B -->|No| D[Do that]
```Build Configuration
Unpublished Content
Curation has exactly one mechanism: srcDir: 'site' in .vitepress/config.mjs. Internal working documents (docs/plans/, docs/decisions/, docs/research/, docs/superpowers/) live outside the site root, so VitePress never processes them — there is no exclude list to maintain, and a new internal directory is unpublished by default. The guard spec spec/config/docs_site_curation_spec.rb proves every built page originates under the site root.
Build Verification
Always build before committing doc changes:
bash
yarn docs:buildIf the build fails, check for:
- Raw HTML in markdown that Vue interprets as template syntax
- Unclosed tags or duplicate attributes
If a new page does not appear in the build, check that it lives under docs/site/ — pages outside the site root are silently never built.
Deployment
Automatic (GitHub Actions)
Documentation deploys when changes are pushed to master or main in the docs/ directory. The .github/workflows/docs.yml workflow builds and deploys to GitHub Pages.
Manual
Trigger via GitHub Actions → "Deploy VitePress Documentation" → "Run workflow".
Content Guidelines
- Source verification — read the source code before documenting it
- Code examples — include practical, runnable examples from real Vulcan usage
- Cross-references — link to related pages (use relative links:
[setup](setup)) - No fabrication — don't document features that don't exist
- Keep current — when code changes, update the docs in the same commit
Commit Messages
bash
git commit -m "docs: add upgrade system developer guide"
git commit -m "docs: update env vars for port standardization"Troubleshooting
Port Already in Use
VitePress auto-increments:
➜ Local: http://localhost:5174/vulcan/Module Not Found
bash
yarn docs:build # Auto-installs deps before buildingIf that fails, manually reinstall:
bash
cd docs && rm -rf node_modules && yarn install && cd ..Internal Docs and the Build
Internal working docs contain raw markdown that Vue's template compiler would reject, but the build never sees them: they live outside docs/site/, and VitePress only processes the site root. New internal docs go anywhere outside docs/site/; new published pages go under it. Nothing to configure either way.