Skip to content

Writing Documentation

Contributing to Sayr’s documentation is one of the easiest ways to help the project. You can edit docs directly on GitHub without cloning the repository or setting up a local environment.

Every documentation page has an “Edit page” link at the bottom. Click it to:

  1. Fork the repository (if you haven’t already)
  2. Edit the file directly in GitHub’s web editor
  3. Submit a pull request with your changes

That’s it! No local setup required.

Sayr’s documentation is built with Starlight, a documentation theme for Astro. It transforms Markdown files into a beautiful documentation site.

  • Markdown/MDX — Write in standard Markdown with optional MDX for React components
  • Automatic navigation — Sidebar generated from file structure
  • Code highlighting — Syntax highlighting with Expressive Code
  • Last updated dates — Automatically tracked via Git history
  • Edit links — Direct links to edit any page on GitHub

Documentation lives in the marketing app:

apps/marketing/
├── src/
│ ├── content/
│ │ └── docs/
│ │ └── docs/ # All documentation pages
│ │ ├── index.md # Homepage (/docs)
│ │ ├── quick-start.md
│ │ ├── api/
│ │ │ ├── overview.md
│ │ │ ├── ws.mdx
│ │ │ └── reference.mdx
│ │ ├── guides/
│ │ │ └── visibility.md
│ │ ├── self-hosting/
│ │ │ └── railway.md
│ │ └── contributing/
│ │ ├── local-development.mdx
│ │ ├── architecture.md
│ │ └── ...
│ └── assets/
│ └── logo.svg
└── astro.config.mjs # Sidebar and site config

Files map to URLs as follows:

File PathURL
docs/index.md/docs
docs/quick-start.md/docs/quick-start
docs/api/overview.md/docs/api/overview
docs/guides/visibility.md/docs/guides/visibility
Content TypeLocationExample
User guidesdocs/guides/Feature tutorials, how-tos
API documentationdocs/api/Endpoints, WebSocket events
Self-hostingdocs/self-hosting/Deployment guides
Contributingdocs/contributing/Developer documentation

Create a new .md or .mdx file with frontmatter:

---
title: Your Page Title
description: A brief description for SEO and previews
---
Your content here...

Every documentation page starts with YAML frontmatter:

---
title: Page Title # Required - shown in sidebar and page header
description: Brief description # Required - used for SEO meta tags
sidebar:
order: 1 # Optional - controls sidebar position
label: Custom Label # Optional - override sidebar text
badge: New # Optional - add a badge (New, Beta, etc.)
hidden: false # Optional - hide from sidebar
---
  • Be direct — Get to the point quickly
  • Be practical — Focus on what users need to do
  • Be inclusive — Avoid jargon; explain technical terms
  • Use “you” — Address the reader directly
  1. Start with the goal — What will readers accomplish?
  2. Show, don’t just tell — Include code examples
  3. Use headings liberally — Make content scannable
  4. Keep paragraphs short — 2-4 sentences max
ElementConvention
File pathsBackticks: `apps/marketing/`
CommandsCode blocks with bash language
UI elementsBold: Click Save
Keyboard shortcutsCmd/Ctrl + S
Variables/placeholders{placeholder} or <placeholder>

Always specify the language for syntax highlighting:

```typescript
const example = "highlighted code";
```

For terminal commands:

```bash
pnpm dev
```

Starlight supports callout boxes for important information:

:::note
Helpful additional information.
:::
:::tip
Suggestions for best practices.
:::
:::caution
Important warnings about potential issues.
:::
:::danger
Critical warnings about destructive actions.
:::

These render as styled boxes:

Use tables for structured information:

| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
| Data | Data | Data |

These render as styled tables:

Column 1Column 2Column 3
DataDataData
  • Internal links: Use relative paths starting with /docs/

    See the [Architecture Overview](/docs/contributing/architecture)
  • External links: Use full URLs

    Learn more at [Starlight docs](https://starlight.astro.build/)

For pages that need React components, use .mdx extension:

---
title: Interactive Page
---
import { MyComponent } from '../../components/MyComponent';
Regular markdown content...
<MyComponent prop="value" />
More markdown...

The sidebar uses starlight-sidebar-topics to create separate navigation topics. Configuration is in apps/marketing/astro.config.mjs:

starlightSidebarTopics([
{
label: "Documentation",
link: "/docs/",
icon: "open-book",
id: "docs",
items: [
{
label: "Getting Started",
items: [
{ label: "Introduction", slug: "docs" },
{ label: "Quick Start", slug: "docs/quick-start" },
],
},
{
label: "Guides",
autogenerate: { directory: "/docs/guides" },
},
// ...
],
},
{
label: "Contributing",
link: "/docs/contributing/local-development/",
icon: "github",
id: "contributing",
items: [
// Contributing navigation items...
],
},
]),
  • Manual items: Explicitly listed pages with { label, slug }
  • Autogenerate: Automatically includes all pages in a directory
  • Topics: Separate top-level navigation tabs (Documentation, Contributing)

To preview documentation changes locally:

Terminal window
# From repository root
pnpm -F marketing dev
# Opens at http://localhost:3002
  • Frontmatter includes title and description
  • Content follows the writing style guide
  • Code blocks have language specified
  • Links use correct paths (internal: /docs/..., external: full URL)
  • Images have alt text (if any)
  • Page renders correctly in local preview (if testing locally)

Every documentation page displays metadata that’s automatically populated from Git history.

The author is the person who created the file (made the first commit). Their GitHub avatar and linked username appear below the page title.

Contributors are anyone who has committed changes to the file after the initial creation. They appear as a row of avatars, linking to their GitHub profiles.

The last updated date reflects when the file was last modified, based on the most recent Git commit that touched the file.

The metadata is populated through a build-time pre-computation system that extracts Git history during the build process.

Build Time Process:

  1. An Astro integration (apps/marketing/src/integrations/precompute-contributors.ts) runs during pnpm run build
  2. It scans all documentation files in src/content/docs/
  3. For each file, it executes git log --follow to retrieve the complete commit history
  4. Author data is extracted from the oldest commit (file creation)
  5. Contributor data is aggregated from all subsequent commits
  6. For each contributor with a GitHub username, profile data (avatar URL, profile link) is fetched from GitHub’s API
  7. All metadata (including GitHub avatars) is written to src/data/contributors.json
  8. This JSON file is committed to the repository and copied to dist/server/data/ and dist/client/data/ during builds

Runtime Process:

  1. Route middleware (apps/marketing/src/routeData/contributors.ts) loads the pre-computed JSON at server startup
  2. For each page request, it looks up the file path in the cached contributor data
  3. Metadata is attached to the route context with all GitHub data already included
  4. The PageTitle component renders the author, contributors, and last updated information using pre-fetched avatars

Email-to-GitHub Mapping:

The system extracts GitHub usernames using two methods:

  1. GitHub noreply emails: Automatically parsed from formats like [email protected] or [email protected]
  2. Manual mapping: Custom emails (like [email protected]) are mapped to GitHub usernames in the integration’s EMAIL_TO_GITHUB configuration

Once a GitHub username is identified, the build process fetches the user’s avatar URL and profile link from GitHub’s API. This data is stored in contributors.json, eliminating the need for any runtime API calls.