Sayr

Writing Documentation

How to contribute to Sayr's 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.

Quick Start: Edit on GitHub

Every documentation page has an Open menu below its title. Choose Open in GitHub to jump to the source file, then:

  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.

How the Docs Work

Sayr's documentation is built with Fumadocs and lives in the landing app (apps/landing), which runs on TanStack Start. It turns the Markdown files in apps/landing/content/docs/ into the docs site.

Key Features

  • Markdown/MDX — Write in standard Markdown, with MDX for pages that need components such as callouts
  • Navigation from the file tree — The sidebar is generated from the folders and each folder's meta.json, which also controls page order
  • Code highlighting — Syntax highlighting built in, via Shiki
  • Copy as Markdown — Every page can be copied or opened as raw Markdown, and /docs/llms.txt / /docs/llms-full.txt expose the whole docs set to LLMs
  • Edit links — Open in GitHub on every page
  • Generated API reference — The endpoint pages under api/reference/ are generated from Sayr's OpenAPI spec, so don't edit them by hand

File Structure

Documentation lives in the landing app:

apps/landing/
├── content/
│   └── docs/                       # All documentation pages
│       ├── meta.json               # Top-level sidebar order
│       ├── index.mdx               # Homepage (/docs)
│       ├── quick-start.md
│       ├── cli/                    # The sayr CLI: overview, feature pages, config reference
│       ├── tasks/                  # Every folder has its own meta.json
│       │   ├── meta.json           #   (title, icon, page order)
│       │   ├── tasks.md
│       │   ├── subtasks.md
│       │   ├── task-relations.md
│       │   └── templates.mdx
│       ├── organize/               # labels, categories, views, releases
│       ├── visibility/             # overview, public-pages
│       ├── account/                # my-tasks, notifications, settings, security
│       ├── organizations/          # overview, preferences, members, billing
│       ├── ai/
│       ├── integrations/
│       ├── self-hosting/
│       ├── api/                    # Separate "API" tab
│       │   ├── overview.md
│       │   ├── sdk.mdx
│       │   └── reference/          # Generated from OpenAPI — don't edit
│       ├── knowledge-base/         # Separate "Knowledge Base" tab
│       └── contributing/           # Separate "Contributing" tab
│           ├── local-development.mdx
│           ├── architecture.md
│           └── guidelines/
└── src/
    └── lib/
        ├── source.ts               # Docs loader + folder icon registry
        └── layout.shared.tsx       # Sidebar tabs (Documentation, API, ...)

URL Mapping

Files map to URLs as follows (paths are relative to content/docs/):

File PathURL
index.mdx/docs
quick-start.md/docs/quick-start
api/overview.md/docs/api/overview
visibility/overview.md/docs/visibility/overview
knowledge-base/index.md/docs/knowledge-base

URLs mirror folder and file names exactly, including case, so keep names lowercase with hyphens. Most folders have no index page, so a bare folder URL (one that stops at the folder name) doesn't resolve — link to a specific page instead.

Creating a New Page

1. Choose the Right Location

Content TypeLocationExample
Task managementtasks/Tasks, subtasks, relations, templates
Organize & workfloworganize/Labels, categories, views, releases
Visibility & public pagesvisibility/Visibility controls, public board
Account featuresaccount/My tasks, notifications, settings, security
Organization settingsorganizations/Members & teams, preferences, billing
Integrationsintegrations/GitHub, and future integrations
API guidesapi/Overview, SDK (endpoint pages are generated)
Self-hostingself-hosting/Deployment guides
FAQ & troubleshootingknowledge-base/Common questions
Contributingcontributing/Developer documentation

Creating a New Section

If your content doesn't fit into an existing category, create a new folder under content/docs/ with a meta.json (see Ordering pages and folders), and add the folder to the root meta.json so it appears in the sidebar. Mention this in your PR and we'll help with the configuration if you're not sure how.

2. Create the File

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

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

Your content here...

3. Add It to the Sidebar Order

Add the file's name (without the extension) to the pages array in the folder's meta.json, at the position where it should appear. See the next section.

Frontmatter Reference

Every documentation page starts with YAML frontmatter:

---
title: Page Title              # Required - shown in the sidebar and page header
description: Brief description # Required - shown under the title, used for SEO meta tags
---

Page order and sidebar labels are not set in frontmatter. Starlight-style keys such as sidebar.order, sidebar.label, sidebar.badge and sidebar.hidden are silently ignored — use the folder's meta.json instead.

Ordering pages and folders

Each folder has a meta.json that names the folder and lists its pages in display order:

{
	"title": "Organize",
	"defaultOpen": false,
	"icon": "IconFolders",
	"pages": ["labels", "categories", "views", "releases", "..."]
}
FieldPurpose
titleFolder label in the sidebar
defaultOpenWhether the folder starts expanded (false for most sections)
iconA Tabler icon name registered in src/lib/source.ts
pagesPage order — file names without the extension, or sub-folder names
roottrue makes the folder its own sidebar tab (API, Knowledge Base, Contributing)

Always end pages with "...". It stands in for every page you haven't listed, so a new page still appears (alphabetically, after the listed ones) instead of silently disappearing from the sidebar. A name in pages that doesn't match a file or folder is ignored, so double-check the spelling.

The root content/docs/meta.json controls the top-level order. A new top-level folder must be added there or it won't show up in the sidebar.

Generated API pages

content/docs/api/reference/ and its meta.json files are generated from the OpenAPI spec with pnpm -F landing openapi:generate. Don't edit them by hand.

Writing Style Guide

Tone and Voice

  • 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

Structure

  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

Formatting Conventions

ElementConvention
File pathsBackticks, e.g. apps/landing/
CommandsCode blocks with bash language
UI elementsBold: Click Save
Keyboard shortcutsCmd/Ctrl + S
Variables/placeholders{placeholder} or <placeholder>

Code Blocks

Always specify the language for syntax highlighting:

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

For terminal commands:

```bash
pnpm dev
```

Callouts

Use the <Callout> component for important information. It needs no import, but the page must be an .mdx file:

<Callout type="info" title="Optional title">
Helpful additional information.
</Callout>

<Callout type="idea">
Suggestions for best practices.
</Callout>

<Callout type="warn">
Important warnings about potential issues.
</Callout>

<Callout type="error">
Critical warnings about destructive actions.
</Callout>

Available types are info, warn, error, success and idea. They render as styled boxes:

This is an info callout.

This is an idea callout.

This is a warning callout.

This is an error callout.

Starlight's :::note / :::tip / :::caution / :::danger syntax is not supported here — use <Callout> instead.

Tables

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 absolute paths starting with /docs/ that point at a real page

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

    Learn more at [Fumadocs](https://fumadocs.dev/)

Using MDX

Plain Markdown (.md) is simpler and preferred for most pages. Use the .mdx extension only when a page needs a component such as <Callout>: .md files are compiled as plain Markdown, so JSX in them renders as text.

---
title: Interactive Page
description: A page that uses a callout
---

Regular markdown content...

<Callout type="info" title="Heads up">
Components like this are available in every `.mdx` page without imports.
</Callout>

More markdown...

Local Preview

To preview documentation changes locally:

# From repository root
pnpm -F landing dev

# Opens at http://localhost:3002

Checklist Before Submitting

  • Frontmatter includes title and description
  • The page is listed in its folder's meta.json pages (and the list still ends with "...")
  • The page is added to the Browse by Topic table in content/docs/index.mdx
  • Content follows the writing style guide
  • Code blocks have language specified
  • Links use correct paths (internal: /docs/... pointing at a real page, external: full URL)
  • Images have alt text (if any)
  • Page renders correctly in local preview (if testing locally)

On this page