# Documentation Page Documentation Page turns the markdown already sitting in your Github repository into a gorgeous documentation website, with little or no setup. Talk about dogfeeding 🤗. The page you are reading right now is generated by it. There is no build step and nothing is copied into your repo: we read your files on demand, render them, and serve a fast, searchable site. Push a change and it shows up (see the [refresh rate](/documentation/how-it-works#caching)). ## Getting started There is a good chance your documentation already works. Try it by searching your repository on the [homepage](https://documentation.page/), or go straight to: ``` https://documentation.page/github/// ``` For example: [documentation.page/github/sindresorhus/meow](https://documentation.page/github/sindresorhus/meow/). ## Organize your docs From the simplest to the most flexible, you can structure your documentation in three ways: - **A single `readme.md`.** Ideal for smaller projects: write everything in your readme and call it a day. [See example](https://documentation.page/github/sindresorhus/meow/). - **A `documentation/` folder** with multiple markdown files. Every `.md` inside is concatenated (alphabetically, top-level files first) into a single page. Prefix files with numbers to control the order. - **A configuration file** when you want control over the name, logo, menu, which files to include, a blog, and more. See [Configuration](/documentation/configuration). ``` documentation/ 1. Getting started.md 2. Configuration.md 3. Advanced.md ``` We follow your existing structure automatically, building the [navigation](/documentation/how-it-works#navigation) from your headings. Most of what we detect is described in [Conventions](/documentation/conventions), and everything you can override lives in [Configuration](/documentation/configuration). ## Custom branding Every public repository is available on Documentation Page for free, so anyone can read and learn from it. Upgrading to a paid plan lets you point your **own custom domain** at it, put your **brand** front and center (logo, menu, a custom landing page), and get a **faster refresh rate**. See the [pricing](https://documentation.page/#pricing) and the [custom domain](#custom-domain) below. ## Custom domain On a paid plan you can serve your docs from your own domain, like `docs.yourproject.com`, with your branding front and center. 1. Register your domain (anywhere you like) and subscribe to a paid [plan](https://documentation.page/#pricing). 2. [Contact me](https://francisco.io/) with your custom domain and your repo. 3. We reply with the `CNAME` record to add at your DNS provider. 4. Add a [`menu`](/documentation/configuration#menu) to your configuration so your site has top navigation, and optionally a [`home` or `landing`](/documentation/configuration#home-and-landing) page. Your documentation is then served at the root of your domain, with your generated docs available under `/documentation`. ## sitemap.xml and llms.txt On a custom domain we automatically serve two extra files at the root, so search engines and AI tools can discover your content. They are generated for you, kept up to date, and require no configuration. - **`/sitemap.xml`**: every page of your site (docs, blog posts and extra pages), for search engines. - **`/llms.txt`**: your full documentation as a single markdown file, for LLMs and AI assistants. Both are available only on custom domains. ## Leaving Documentation Page Documentation Page exists to help developers semi-automate their docs, not to lock them in. If you ever decide to move to, say, Github Pages, you can. There are [some disadvantages](/documentation/compare-with#github-pages), but they might not affect you. The easiest path is to keep a single markdown file with all your docs, then either run a small script that converts it to HTML locally, or use a Jekyll template that renders it to HTML on Github Pages. # Conventions This is the most powerful bit: we crawl your repository looking for a handful of useful files and use them to build the website. Whenever possible we recommend following these conventions first, and reaching for [configuration](/documentation/configuration) only when you need to override something. Everything below is detected automatically from a **public** repository, no config required. Each item links to its matching [configuration](/documentation/configuration) option, which always takes precedence over what we detect. | key | detected from | override | |-----------------|------------------------------------------------------|----------| | `name` | The Github repo `name`, cleaned up. | [name](/documentation/configuration#name) | | `title` | The same as `name` by default. | [title](/documentation/configuration#title) | | `description` | The Github repo `description`. | [description](/documentation/configuration#description) | | `logo` | A file named `favicon` or `logo`. | [logo](/documentation/configuration#logo) | | `social` | A file named `social`, or the Github social preview. | [social](/documentation/configuration#social) | | `documentation` | A `documentation/` folder, otherwise `readme.md`. | [documentation](/documentation/configuration#documentation) | | `blog` | A `blog/` folder. | [blog](/documentation/configuration#blog) | | `tutorials` | A `tutorials/` folder. | [tutorials](/documentation/configuration#tutorials) | | `menu` | Not detected, configuration only. | [menu](/documentation/configuration#menu) | ## name Your project's short identifier. It comes from the Github repository name, tidied up: emoji are stripped, dashes become spaces, and each word is capitalized, so the repo `my-cool-lib` becomes **My Cool Lib**. It's the shortest possible label for your project, with no tagline or icon, and appears in the browser-tab title (and, on paid plans, next to the logo in the navbar). Override it with the [`name`](/documentation/configuration#name) option. ## title A longer identifier that can carry your tagline. It defaults to the same value as `name`, but this is where the marketing goes: it's used as the main title in Google search results and as the headline on social share cards. Set the [`title`](/documentation/configuration#title) option to give search engines and link previews something richer than the bare project name. ## description A short paragraph summarizing what the project does and why it matters, taken straight from your repository's Github description. It appears in the Google search snippet and the social share-card description. Emoji are stripped and whitespace normalized. Override it with the [`description`](/documentation/configuration#description) option. ## logo We look for a file named `favicon` or `logo` with a `.svg`, `.png`, `.jpg`, `.jpeg` or `.ico` extension, preferring files closer to the repository root. The image becomes **both** the browser-tab favicon and (on paid plans) the logo shown next to your project name in the navbar. If none is found, we fall back to the Documentation Page icon. Point at a specific file or URL with the [`logo`](/documentation/configuration#logo) option. ## social The social image is used for social share cards, the preview that appears when your docs are linked on Twitter, Slack, Facebook, and so on (the Open Graph and Twitter image). We look for a file named `social` with a `.jpg`, `.png`, `.webp` or `.avif` extension; failing that we use your repository's Github social-preview image, and as a last resort an automatically generated card. Set the [`social`](/documentation/configuration#social) option to use a specific image. ## documentation If you don't set [`documentation`](/documentation/configuration#documentation) explicitly, we pick the source of your docs automatically: 1. A **`documentation/`** folder, if present. 2. Otherwise your **`readme.md`**. A folder is read recursively and every `.md` file inside it is concatenated into a single page, in order: alphabetically, with top-level files before nested ones. Because the order is alphabetical, prefixing files with numbers (`1. Intro.md`, `2. Usage.md`) is the easiest way to control the sequence. For full control over which files and folders are included, and to split your docs into multiple pages, use the [`documentation`](/documentation/configuration#documentation) option. ## blog If your repository has a top-level **`blog/`** folder, its markdown files are published as a blog automatically: the index at `/blog`, each post at `/blog/`, and a *Blog* link added to the navigation. Point at a different folder with the [`blog`](/documentation/configuration#blog) option, and see the [Blog](/documentation/blog) guide for the per-post front-matter (`title`, `description`, `date`, `social`) and how posts are ordered. ## tutorials If your repository has a top-level **`tutorials/`** folder, its markdown files are published as tutorials automatically: the index at `/tutorials`, each tutorial at `/tutorials/`, and a *Tutorials* link added to the navigation. Point at a different folder with the [`tutorials`](/documentation/configuration#tutorials) option, and see the [Tutorials](/documentation/tutorials) guide for the per-tutorial front-matter (`title`, `description`, `date`, `social`) and how tutorials are ordered. ## menu The top-right navigation menu is the one thing here that is **not** auto-detected. It's used on custom domains and must be set with the [`menu`](/documentation/configuration#menu) option. # Configuration When the [conventions](/documentation/conventions) aren't enough, add a small JSON configuration to take control. Every key is optional and overrides what we would otherwise detect automatically, so you only need the ones you care about. ## Where to put it We read the **first** of these that exists in your repository: - `documentation.page.json`: a file at the root of your project. - The `documentation.page` key inside your **`package.json`**. Both use exactly the same options, described below. A typical configuration looks like this: ```json { "name": "Statux", "title": "Statux • The easy React state management library", "description": "A straightforward way of dealing with your global app state", "logo": "https://example.com/mylogo.png", "menu": { "Donate": "https://www.paypal.me/franciscopresencia/19", "Github": "https://github.com/franciscop/statux" }, "documentation": ["readme.md", "src/methods", "examples"] } ``` ## name A very short name to identify the project: just the name, with no tagline or icon. It appears in the browser-tab title and, on paid plans, next to the logo in the navbar, so keep it short. Defaults to your [detected repo name](/documentation/conventions#name). ```json { "name": "Statux" } ``` ## title A longer identifier that can include your tagline. Unlike `name`, this is where the marketing goes: it's used as the main title in Google search results and as the headline on social share cards. Defaults to `name`. ```json { "title": "Statux • The easy React state management library" } ``` ## description A short paragraph summarizing what the project does and why it's useful. A sentence or two works best. It's used for the Google search-result description and the social share-card description. Defaults to your [Github repo description](/documentation/conventions#description). ```json { "description": "A straightforward way of dealing with your global app state" } ``` ## logo An absolute path or URL to your project's logo (`.svg` or `.png` recommended so it stays crisp at any size). It's used as **both** the browser-tab favicon and, on paid plans, the logo next to your project name in the navbar. Defaults to a [detected `favicon`/`logo` file](/documentation/conventions#logo), or the Documentation Page icon if there is none. ```json { "logo": "https://example.com/mylogo.png" } ``` ## social An absolute path or URL to the image used for social share cards, the preview shown when your docs are linked on Twitter, Slack, Facebook, etc. A wide image (around 1200×630) works best. Defaults to a [detected `social` file](/documentation/conventions#social), then your repo's Github social-preview image, then a generated card. ```json { "social": "https://example.com/social-card.png" } ``` ## menu The top-right navigation links, shown on **custom domains** (they don't appear on the free `documentation.page/github/...` pages). It's an object mapping each visible label to its URL, in order: ```json { "menu": { "Issues": "https://github.com/franciscop/react-test/issues", "Contribute": "https://github.com/franciscop/react-test/blob/master/Contributing.md", "Donate": "https://www.paypal.me/franciscopresencia/19", "Github": "https://github.com/franciscop/react-test" } } ``` Most links point to external URLs, or to your site's own sections (`/documentation`, `/blog`). ### Publishing an HTML page If a value is instead a path to a local **`.html` file** in your repository, that file is published as its own page and the menu link points to it. This is how you add a hand-written page (a changelog, a demo, a test runner) that isn't part of your markdown docs: ```json { "menu": { "Tests": "tests.html", "Github": "https://github.com/franciscop/umbrella" } } ``` - **The URL comes from the label**, lowercased and hyphenated: `"Tests"` is served at `/tests`, and `"Release Notes"` at `/release-notes`. The file name plays no part in the URL. - The page is included in your generated `/sitemap.xml`. - If the file doesn't exist in the repository, the menu link is left pointing at the raw value rather than breaking the build. Only `.html` values are published this way; a page is only created when it has a menu entry. #### Fragments and whole documents How the file is served depends on what it contains: - **A fragment** (no `` tag) is wrapped in your site's header and footer, exactly like [`home`](#home-and-landing). Write only the content and it matches the rest of your site, with the menu link highlighted while the reader is on it. Add a `

Your Project

A short tagline about what it does.

Read the docs
``` ## Full control For complete control over the whole page, including the ``, custom fonts and scripts, use [`landing`](/documentation/configuration#home-and-landing) instead of `home`. It is served exactly as-is at the root of your domain, with no navigation added. # Blog Documentation Page can publish a blog straight from markdown files in your repository: no separate site, no static-site generator, no deploys. Posts live next to your code, are versioned with it, and go live when you push. ## Enabling it A blog turns on automatically if your repo has a top-level **`blog/`** folder. You can also point at a different folder (or specific files) with the `blog` option in your [configuration](/documentation/configuration#blog): ```json { "blog": "blog" } ``` Once enabled, the blog index is served at **`/blog`**, each post at **`/blog/`** (the slug is the file name, lowercased and hyphenated, so `2. Dark mode.md` is served at `/blog/2-dark-mode`), and a *Blog* link appears in the navigation. ## Writing a post Each post is a markdown file. Optionally, start it with a metadata block (liquid/YAML front-matter) between `---` fences: ```markdown --- title: We shipped dark mode description: The most requested feature is finally here. date: 2026-07-12 social: /assets/dark-mode.png --- # We shipped dark mode It's been the most requested feature for months... ``` Every field is optional: leave one out and we pick a sensible default, described below. From whatever you provide, the full set of **social tags** (Open Graph and Twitter) is generated for you, so shared links look right everywhere. ## title The post's title, used in the heading, the browser tab and the social card. Defaults to the post's first heading, or a title built from the file name. ```md --- title: We shipped dark mode --- # Today's update ... ``` ## description A short summary, used for the social card and search engines. Defaults to your project's description. ```md --- description: The most requested feature is finally here. --- # Today's update ... ``` ## date The publication date, shown on the post. Defaults to the `YYYY-MM-DD` prefix of the file name, if it has one. ```md --- date: 2026-07-12 --- # Today's update ... ``` ## social A path (made absolute automatically) used for the social share card. Defaults to your project's social image. ```md --- social: /assets/dark-mode.png --- # Today's update ... ``` ## Ordering Posts are sorted by file name. If you prefix them with a `YYYY-MM-DD` date, the **newest** ones are shown first, so a blog reads the way you'd expect: ``` blog/ 2026-07-12-dark-mode.md 2026-05-02-v2-release.md 2026-01-10-hello-world.md ``` The file name is also the URL, so that post is served at `/blog/2026-07-12-dark-mode`. ## Naming each post To choose the URLs yourself, give `blog` an object instead of a folder. Each key is the slug and each value is the file, so you keep the dated file names while serving clean URLs, in exactly the order you list them: ```json { "blog": { "dark-mode": "blog/2026-07-12-dark-mode.md", "v2-release": "blog/2026-05-02-v2-release.md", "hello-world": "blog/2026-01-10-hello-world.md" } } ``` That post is now at `/blog/dark-mode`. This is also the way to rename a post without breaking its URL, or to publish only some of the files in a folder. # Tutorials Documentation Page can publish tutorials straight from markdown files in your repository: step-by-step guides that live next to your code, are versioned with it, and go live when you push. It works just like the [Blog](/documentation/blog), for learning-oriented content. ## Enabling it Tutorials turn on automatically if your repo has a top-level **`tutorials/`** folder. You can also point at a different folder (or specific files) with the `tutorials` option in your [configuration](/documentation/configuration#tutorials): ```json { "tutorials": "tutorials" } ``` Once enabled, the tutorials index is served at **`/tutorials`**, each tutorial at **`/tutorials/`** (the slug is the file name, lowercased and hyphenated, so `3. File uploads.md` is served at `/tutorials/3-file-uploads`), and a *Tutorials* link appears in the navigation. ## Writing a tutorial Each tutorial is a markdown file. Optionally, start it with a metadata block (liquid/YAML front-matter) between `---` fences: ```markdown --- title: Getting started description: Build and run your first app in a couple of minutes. date: 2026-07-12 social: /assets/getting-started.png --- # Getting started In this tutorial you will build your first app from scratch... ``` Every field is optional: leave one out and we pick a sensible default, described below. From whatever you provide, the full set of **social tags** (Open Graph and Twitter) is generated for you, so shared links look right everywhere. ## title The tutorial's title, used in the heading, the browser tab and the social card. Defaults to the tutorial's first heading, or a title built from the file name. ```md --- title: Getting started --- # Your first steps ... ``` ## description A short summary, used for the social card and search engines. Defaults to your project's description. ```md --- description: Build and run your first app in a couple of minutes. --- # Getting started ... ``` ## date The publication date, shown on the tutorial. Defaults to the `YYYY-MM-DD` prefix of the file name, if it has one. ```md --- date: 2026-07-12 --- # Getting started ... ``` ## social A path (made absolute automatically) used for the social share card. Defaults to your project's social image. ```md --- social: /assets/getting-started.png --- # Getting started ... ``` ## Ordering Tutorials are sorted by file name. Prefix them with a number to present them as a sequence, from the first steps through to the advanced topics: ``` tutorials/ 1-getting-started.md 2-routing.md 3-deploying.md ``` A `YYYY-MM-DD` date prefix works too, and shows the **newest** first (the same as the [Blog](/documentation/blog)). The file name is also the URL, so that first tutorial is served at `/tutorials/1-getting-started`. ## Naming each tutorial To choose the URLs yourself, give `tutorials` an object instead of a folder. Each key is the slug and each value is the file, so you keep the numbered file names while serving clean URLs, in exactly the order you list them: ```json { "tutorials": { "getting-started": "tutorials/1-getting-started.md", "routing": "tutorials/2-routing.md", "deploying": "tutorials/3-deploying.md" } } ``` That first tutorial is now at `/tutorials/getting-started`. This is also the way to rename a tutorial without breaking its URL, or to publish only some of the files in a folder. # How it works A quick tour of what happens between your repository and the website your readers see. ## Reading the repo Your repository must be **public** so we can read it (contact us if you need a private one). When someone opens your project, we call the Github API to fetch: - the repo metadata (name, description, homepage, default branch), - the full file tree of your default branch (`master` or `main`), - the specific markdown, config, logo and blog files we need. From those we detect everything described in [Conventions](/documentation/conventions), apply any [Configuration](/documentation/configuration), and render your markdown to HTML. ## Caching To stay fast, respect Github's rate limits, and serve many projects at once, we **cache** each project after building it. This means a change you push can take up to the plan's refresh window to appear: - **Free**: up to 24h. - **Paid**: faster refresh (down to near-immediate on higher tiers). See [pricing](https://documentation.page/#pricing). ## Navigation The sidebar navigation is generated from the headings of your rendered documentation. Your `##` and `###` headings become the sections and sub-sections, each linked by an anchor, so readers can jump around and share deep links. Multi-file docs are merged first, then parsed as one. ## Full-text search Every page and heading is indexed so readers can search your documentation from the sidebar (press `/` to focus the box). Results link straight to the matching section. # Compare with How Documentation Page differs from other ways of publishing docs. The short version: we generate a site from the markdown already in your repo, with no build step and nothing to maintain. ## Github Pages Github Pages is great, but it's a static-site host: you run a generator (often Jekyll) that builds HTML into your repository or a branch. That means a build step to maintain, generated files polluting your repo, and configuration to keep working over time. With Documentation Page there is nothing to build and nothing extra committed to your repo: you write markdown, we render it on demand. The trade-off is that your site is hosted by us rather than by Github; if you'd rather self-host, see [Leaving Documentation Page](/documentation#leaving-documentation-page). ## Static Sites Tools like docs frameworks and site generators are powerful, but they ask you to learn their system, adopt their file layout, and run their build. Documentation Page follows *your* structure instead: a single `readme.md`, a `documentation/` folder, or a small [configuration](/documentation/configuration) file when you want more control. ## A hand-built site You always get the most control by building the site yourself, at the cost of doing (and maintaining) all of it. Documentation Page aims for the sweet spot: a polished, searchable, mobile-friendly site for the price of writing markdown, with an [upgrade path](https://documentation.page/#pricing) for custom domains and branding when you need it. # Pricing Every public repository is documented on Documentation Page for **free**. Paid plans add your own custom domain, branding, faster refresh, and hands-on support. The plans are cumulative: each one includes everything below it. See the [live pricing](https://documentation.page/#pricing) for the current numbers. ## Open Source **Free**, for any public repository. - **Open Source project**: anyone can read and discover your documentation. - **Full navigation and search**: an auto-generated sidebar and full-text search across your docs. - **Basic Configuration**: the non-Pro options: name, title, description, pages and more. - **DIY Documentation**: our own docs to get you going; community help, no 1-on-1 support. - **24 hour refresh rate**: changes you push appear within a day. [Get started](https://documentation.page/), there's nothing to install. ## Private Projects **$5 / month** (or **$30 / year**). Everything in Open Source, plus: - **Custom Domain**: serve your docs from your own domain, like `docs.yourproject.com`. See the [custom domain](/documentation#custom-domain) section. - **White Label page**: your logo and name up front, with none of our branding. - **Full Configuration**: every option, including the ones tagged "Pro" (menu, `home`/`landing`, and more). - **Community Support**: get help from us directly through our community channels. - **10 min refresh rate**: changes appear within about ten minutes. ## Enterprise Project **$100 / month** (or **$1000 / year**). Everything in Private Projects, plus: - **Private Project**: publish docs from a private repository. - **Setup Help**: we help you get set up: repo, domain, branding and page structure. - **1h consulting / month**: a monthly hour of documentation consulting. - **Priority support**: your questions and issues jump to the front of the queue. - **Immediate refresh**: changes go live right away, with no waiting. To upgrade or ask about a plan, [contact me directly](https://francisco.io/). # Syntax Test This page is a **fully-fledged syntax check**: it exercises every markdown feature the renderer supports, gathered in one place so we can eyeball the output. If something renders wrong here, it renders wrong everywhere. ## Headings The title above is an `h1`; the remaining levels follow. ### Third-level heading #### Fourth-level heading ## Text formatting A paragraph with **bold**, *italic*, ***bold italic***, `inline code`, ~~strikethrough~~ and a [link](https://documentation.page/). This sentence runs a little longer so we can check the line height and how comfortably the text wraps once it reaches the edge of the column and continues onto the next line. ## Links Every flavour of link, to check colour, underline and hover states: - Inline link: [Documentation Page](https://documentation.page/) - Reference-style link: [reference link][ref] (defined once, reused) - Angle-bracket autolink: - Email autolink: - Bare URLs in text are *not* auto-linked, so wrap them: - Relative link to another page: [the Configuration page](/documentation/configuration) - Link to a heading on another page: [jump to `name`](/documentation/configuration#name) - Link wrapping `inline code`: [`package.json`](/documentation/configuration) - Link wrapping **bold text**: [**important link**](https://documentation.page/) - A [link that is long enough to wrap across more than one line so we can confirm the underline follows the text correctly as it breaks onto a second line](https://documentation.page/) mid-sentence. A linked image (click through): [![A small logo](/favicon.svg)](https://documentation.page/) [ref]: https://documentation.page/ ## Lists Unordered, with nesting: - First item - Second item - Nested one - Nested two - Third item Ordered: 1. Step one 2. Step two 3. Step three ## Code Inline `const answer = 42`, then fenced blocks in a few languages: ```js // JavaScript const greet = (name) => `Hello, ${name}!`; console.log(greet("world")); ``` ```tsx // TSX type Props = { name: string }; export const Hello = ({ name }: Props) =>

Hi {name}

; ``` ```json { "name": "documentation-page", "nested": { "list": [1, 2, 3], "flag": true } } ``` ``` A plain, unhighlighted code block. ``` Headings inside a code block must render literally, and must not affect the real document: ```md # Not a real heading ## Also not real ``` ## Math Inline math like $E = mc^2$ and $a^2 + b^2 = c^2$ flows within the text, subscripts and all: $x_1, x_2, \ldots, x_n$. Display math is centered on its own line: $$ \int_0^1 x^2 \, dx = \frac{1}{3} $$ $$ \sum_{n=1}^{\infty} \frac{1}{n^2} = \frac{\pi^2}{6} $$ ## Tables | Feature | Supported | Notes | |-------------|-----------|----------------------| | Headings | Yes | `h1`–`h4` | | Code blocks | Yes | Syntax highlighted | | Tables | Yes | `border-collapse` | ## Blockquotes > A single-line quote. > > A second paragraph, with **formatting** inside. ## Alerts > [!NOTE] > Useful information the reader should know. > [!TIP] > A helpful tip. > [!IMPORTANT] > Key information worth highlighting. > [!WARNING] > Something to be careful about. > [!CAUTION] > The negative consequences of an action. ## Details
Click to expand Hidden content, revealed on toggle, with `code`, and a short list: - one - two
## Horizontal rule Above the rule. --- Below the rule.