The single source of truth for all ScottyLabs documentation.
Replaces Notion, Discord pins, Google Drive docs, and scattered README files with a unified, searchable, automatically-updated documentation platform. Integrates with ScottyLabs governance to automatically pull documentation from projects marked with the docs flag.
Every ScottyLabs project, guide, process, and resource in one place:
- Project Documentation: Automatically aggregated from repos with
docs: truein governance - Org-Level Documentation: Central repository for organization-wide guides, processes, and resources
- API References: Interactive documentation for all APIs (OpenAPI/Scalar)
- Code Documentation: Auto-generated rustdoc for Rust projects
- Institutional Knowledge: Onboarding, meeting notes, decision records - everything previously scattered across Notion/Discord
- Governance integration: Projects marked with
docs: trueflag are automatically included - Multi-repo aggregation: Clone and merge documentation from all flagged projects
- Central org docs: Dedicated repository for ScottyLabs-wide documentation
- OpenAPI support: Interactive API documentation with Scalar
- Rustdoc integration: Automatic rustdoc generation and hosting
- Full-text search: Find anything across all projects (powered by Pagefind)
- CI/CD ready: Rebuilds automatically when any project updates docs
- Nix-powered: Reproducible builds and deployment via Nix flake
flowchart TB
governance[Governance YAML<br/>docs: true flag] --> discover[Project Discovery]
central[Central Docs Repo<br/>org-wide content] --> discover
discover --> manifest[projects.toml]
manifest --> build[Build Script]
repos[Project Repos] --> build
build --> starlight[Starlight Pages]
build --> scalar[Scalar API Docs]
build --> rustdoc[Rustdoc Sites]
starlight --> site[Unified Site<br/>Single Source of Truth]
scalar --> site
rustdoc --> site
site --> deploy[Garage S3]
notion[❌ Notion] -.replaced by.-> site
discord[❌ Discord] -.replaced by.-> site
gdrive[❌ Google Drive] -.replaced by.-> site
-
Central Org Docs (
scottylabs-docsrepo)- Onboarding guides
- Organization processes and policies
- Meeting notes and decision records
- Event planning guides
- Infrastructure documentation
-
Project Docs (from repos with
docs: truein governance)- Starlight - Markdown documentation that integrates into main navigation
- Rust - Runs
cargo doc, hosts at/{slug}/api/ - OpenAPI - Generates Scalar-rendered interactive API reference
The documentation hub automatically rebuilds when governance changes. See GOVERNANCE_INTEGRATION.md for setup instructions.
What triggers a rebuild:
- Changes to
data/in the governance repository - Direct pushes to this repository
- Manual workflow dispatch
Setup required in governance repository:
- Add access token secret:
DOCS_TRIGGER_TOKEN - Add workflow file:
.forgejo/workflows/trigger-docs-rebuild.yml(seegovernance-workflow-example.yml)
Once configured, any change to governance (adding/removing docs = true flags, updating descriptions, etc.) will automatically trigger a documentation rebuild and deployment.
# Clone the repository
git clone https://codeberg.org/scottylabs/documentation.git
cd documentation
# Install dependencies
bun install
# Enter development shell (Nix users)
nix developProjects are automatically discovered from the ScottyLabs governance repository. When a repository has docs = true in its governance entry (same pattern as kennel and sentry flags), it's included in the documentation hub.
To add your project's documentation:
-
In the governance repository (
data/directory), adddocs = trueto your repository entry:# data/my-team.toml [[team.projects]] name = "My Project" slug = "my-project" [[team.projects.repos]] name = "my-project-backend" description = "Backend for My Project" kennel = true docs = true # <-- Add this flag (same level as kennel/sentry)
-
Ensure your repository has a
docs/directory with markdown files -
The documentation hub will automatically pick it up on the next build
Optional configuration:
[[team.projects.repos]]
name = "my-api"
docs = true
docs_type = "openapi" # or "rust" or "starlight" (default)
docs_dir = "documentation" # custom docs directory
openapi_spec = "openapi.json" # for OpenAPI projects
export_command = "cargo run --bin export-openapi"Manual override: You can also manually add projects to projects.toml:
[[project]]
slug = "my-project"
name = "My Project"
repo = "https://codeberg.org/scottylabs/my-project"
type = "starlight"
docs_dir = "docs"
description = "Documentation for My Project"[[project]]
slug = "guides"
name = "User Guides"
repo = "https://codeberg.org/scottylabs/guides"
type = "starlight"
docs_dir = "docs"
description = "Comprehensive guides for all ScottyLabs services"[[project]]
slug = "common-lib"
name = "Common Library"
repo = "https://codeberg.org/scottylabs/common-lib"
type = "rust"
docs_dir = "docs"
description = "Shared Rust utilities and types"[[project]]
slug = "courses-api"
name = "Courses API"
repo = "https://codeberg.org/scottylabs/courses-backend"
type = "openapi"
docs_dir = "docs"
openapi_spec = "openapi.json"
export_command = "cargo run --bin export-openapi"
description = "Course scheduling and registration API"# Build documentation from all projects
bun run build
# Start development server
bun run dev
# Clean build artifacts
bun run scripts/build.ts cleanThe build process follows these steps:
- Parse manifest - Read
projects.tomlto get project list - Clone repos - Parallel
git cloneinto.repos/{slug}/ - Process by type:
- Starlight: Copy markdown to
src/content/docs/{slug}/ - Rust: Run
cargo doc, copy topublic/{slug}/api/ - OpenAPI: Export spec, generate Scalar page
- Starlight: Copy markdown to
- Generate nav - Build dynamic Starlight sidebar
- Build site - Run
astro build
documentation/
├── astro.config.mjs # Starlight configuration
├── package.json # Dependencies
├── projects.toml # Project manifest
├── flake.nix # Nix development environment
├── .forgejo/
│ └── workflows/
│ └── deploy.yml # CI/CD pipeline
├── scripts/
│ ├── build.ts # Main build orchestrator
│ ├── manifest.ts # TOML parsing
│ ├── clone-repos.ts # Git operations
│ ├── aggregate-docs.ts # Content aggregation
│ ├── scalar-integration.ts # OpenAPI handling
│ ├── rustdoc.ts # Rust documentation
│ └── generate-nav.ts # Navigation generation
├── src/
│ ├── content/
│ │ ├── config.ts # Content collections
│ │ └── docs/ # Documentation pages
│ ├── pages/
│ │ └── [slug]/
│ │ └── api.astro # Dynamic API pages
│ └── styles/
│ └── scalar-theme.css
└── .repos/ # Cloned repos (gitignored)
The documentation hub rebuilds automatically on:
- Direct commits to the documentation repository
- Governance changes via repository dispatch (when governance
data/changes) - Manual triggers via workflow dispatch
To enable automatic rebuilds when governance changes, add the trigger workflow to the governance repository. See GOVERNANCE_INTEGRATION.md for complete setup instructions.
Quick setup:
# In governance repository
mkdir -p .forgejo/workflows
cp /path/to/documentation/governance-workflow-example.yml \
.forgejo/workflows/trigger-docs-rebuild.yml
# Add secret DOCS_TRIGGER_TOKEN to governance repo
# (see GOVERNANCE_INTEGRATION.md for details)The included workflow automatically:
- Checks out the repository
- Installs dependencies with Bun
- Runs the build script
- Uploads artifacts
- Deploys to Garage S3 (on main branch)
Configure these in your Forgejo repository settings:
GARAGE_ENDPOINT- S3 endpoint URLGARAGE_ACCESS_KEY- S3 access keyGARAGE_SECRET_KEY- S3 secret key
The bucket name is configured in the workflow: scottylabs-docs
# Using Nix
nix run .#upload-garage
# Or directly with environment variables
export GARAGE_ENDPOINT="https://s3.example.com"
export GARAGE_ACCESS_KEY="your-access-key"
export GARAGE_SECRET_KEY="your-secret-key"
export GARAGE_BUCKET="scottylabs-docs"
nix run .#upload-garageFor projects contributing Starlight documentation:
your-project/
└── docs/
├── index.md # Landing page
├── getting-started.md
├── guides/
│ ├── installation.md
│ └── configuration.md
└── api/
└── reference.md
Standard Starlight frontmatter is supported:
---
title: Page Title
description: Page description for SEO
---
# Page Title
Content here...The build system automatically adds:
project: The project slugprojectType: The project type (starlight/rust/openapi)
For OpenAPI projects, ensure your export command:
- Runs without starting a server
- Writes to the path specified in
openapi_spec - Generates valid OpenAPI 3.0+ JSON
Example Rust implementation with utoipa:
// bin/export-openapi.rs
use utoipa::OpenApi;
use std::fs;
#[tokio::main]
async fn main() {
let doc = ApiDoc::openapi();
fs::write(
"openapi.json",
serde_json::to_string_pretty(&doc).unwrap()
).unwrap();
}Before:
- Notion: Onboarding guides, meeting notes, processes (hard to search, requires account)
- Discord: Pinned messages, FAQs (ephemeral, poor discoverability)
- Google Drive: Shared docs (siloed, inconsistent permissions)
- README files: Scattered across 30+ repos (no central search)
- Tribal knowledge: In people's heads or DMs
After:
- One URL:
docs.scottylabs.org - Full-text search: Find anything across all projects
- Always up-to-date: Rebuilds on every commit
- No account needed: Public, accessible, linkable
- Git-based: Version controlled, reviewable, forkable
Projects use a simple docs: true flag (same pattern as kennel: true):
- Automatic discovery: No manual manifest maintenance
- Consistent with existing workflows: Same governance system
- Self-service: Project maintainers control their own docs
- Audit trail: Changes tracked in governance repo
No mature multi-repo plugin exists for Starlight (unlike mkdocs-monorepo-plugin). A ~200 LOC build script provides:
- Full control over navigation structure
- Integration with governance system
- Better build caching
- Type-safe TypeScript implementation
- Equivalent UX to established plugins
Rustdoc generates a complete static site with its own theme, search, and navigation. Embedding would require:
- Fragile iframe hacks
- JSON-to-markdown conversion (lossy)
- Custom theming to match (high maintenance)
The sibling pattern (/{slug}/api/) is the industry standard (docs.rs, tokio.rs, axum.rs, etc.)
Compared to Swagger UI and Redoc:
- Better UX: Modern design, fast rendering
- More features: Try It, code generation, dark mode
- Better integration: First-party Astro component
- Active development: 14K+ stars, regular releases
Check that all required fields are present in projects.toml:
slug,name,repo,type,docs_dir,description
For OpenAPI projects, also ensure:
openapi_specis setexport_commandis provided (if spec isn't pre-generated)
Ensure:
- Project
typeis set to"rust" - Repository contains a valid Cargo workspace/package
cargo docruns successfully in the project
Check build logs for cargo errors.
The navigation is regenerated on each build. If changes aren't appearing:
- Clean build artifacts:
bun run scripts/build.ts clean - Rebuild:
bun run build - Check that markdown files have correct file extensions (
.mdor.mdx)
- Fork this repository
- Add your project to
projects.toml - Ensure your project has documentation in the specified
docs_dir - Test locally:
bun run build && bun run dev - Submit a pull request
Contributions to the documentation hub itself are welcome:
- Build script improvements
- Theme enhancements
- Additional project type support
- Documentation improvements
MIT License - see LICENSE file for details
For questions or issues:
- Open an issue on Codeberg
- Ask in the ScottyLabs Discord
- Email: tech@scottylabs.org