Extras Formats
ExDoc supports three formats for extra pages: Markdown, Cheatsheets, and Livebooks.
Markdown (.md)
Standard Markdown files for long-form documentation. Use for conceptual guides, architecture overviews, getting started guides, and changelogs.
Structure
# Getting Started with WeatherStation
## Prerequisites
- Elixir 1.17+
- PostgreSQL 15+
## Installation
Add `weather_station` to your dependencies:
{:weather_station, "~> 1.3"}
## Configuration
Configure your sensor endpoints in `config/config.exs`:
config :weather_station,
sensors: ["temp_01", "humidity_01"],
poll_interval: :timer.seconds(30)
Tips
- Use the first
h1heading as the page title (ExDoc picks it up automatically) - Fenced code blocks with language tags get syntax highlighting
- Relative links between extras work:
[Configuration](configuration.md) - Link to modules with backticks:
`WeatherStation.Sensor` - Link to functions:
`WeatherStation.Sensor.read/1`
Cheatsheets (.cheatmd)
Quick-reference cards rendered in a visual card layout. Use for syntax summaries, common patterns, and lookup tables.
Basic Structure
A cheatsheet uses specific heading levels to create the card layout:
h1(#) -- Page titleh2(##) -- Section heading (rendered as a card group)h3(###) -- Individual card within a section- Content under each
h3becomes the card body
Example Cheatsheet
# Ecto Query Syntax
## Basic Queries
### Select all records
```elixir
Repo.all(User)
Filter with where
from u in User,
where: u.active == true,
select: u
Limit and offset
from u in User,
limit: 10,
offset: 20
Associations
Preload associations
Repo.all(User) |> Repo.preload(:posts)
# Or in the query
from u in User, preload: [:posts]
Join and select
from u in User,
join: p in assoc(u, :posts),
where: p.published == true,
select: {u.name, p.title}
### Card Layout Rules
- Each `h2` section becomes a visually distinct group with a header
- Each `h3` under an `h2` becomes a card in that group
- Code blocks inside cards are rendered as styled examples
- Keep card content concise -- cheatsheets are for quick scanning
- Plain text under `h2` (before any `h3`) appears as an intro for that section
- Content before the first `h2` appears as a page introduction
- Cheatsheets support only a limited subset of Markdown -- headings, plain text, fenced code blocks, and inline attributes
### Layout Attributes
ExDoc provides inline attributes on `h2` and `h3` headers to control card layout:
**Column layouts (on `h2` sections):**
- `{: .col-2}` -- Two equal columns
- `{: .col-3}` -- Three equal columns
- `{: .col-2-left}` -- Two columns, left column wider
**List layouts (on `h3` cards):**
- `{: .list-4}` -- Four-column list
- `{: .list-6}` -- Six-column list
**Width control (on `h2` sections):**
- `{: .width-50}` -- Half-width section
```markdown
## API
{: .col-2}
### Functions
{: .list-6}
* `foo/1`
* `bar/2`
* `baz/3`
When to Use Cheatsheets
- API quick reference (common function calls)
- Syntax summaries (Ecto queries, Phoenix routes)
- Configuration option lookup tables
- Migration from another library (side-by-side comparisons)
Livebooks (.livemd)
Interactive Livebook notebooks that render as rich documentation pages. Use for tutorials, data exploration walkthroughs, and interactive examples.
How They Render in ExDoc
ExDoc renders .livemd files as static documentation pages with:
- Code cells displayed as syntax-highlighted code blocks
- Markdown cells rendered normally
- A "Run in Livebook" badge linking to the raw
.livemdfile so readers can open it interactively - Mermaid diagrams rendered if present
- Output cells are not included -- only source and markdown cells render
Example Livebook Structure
# Data Pipeline Tutorial
## Setup
```elixir
Mix.install([
{:weather_station, "~> 1.3"},
{:kino, "~> 0.14"}
])
Connecting to Sensors
First, start the sensor supervisor:
{:ok, pid} = WeatherStation.Sensor.Supervisor.start_link(
sensors: ["temp_01", "humidity_01"]
)
Reading Data
Poll the sensors and inspect the results:
readings = WeatherStation.Sensor.read_all()
Kino.DataTable.new(readings)
### Best Practices for Livebooks in ExDoc
- Include `Mix.install/1` in the first code cell so readers can run the notebook standalone
- Write Livebooks that make sense both as static docs and interactive sessions
- Use Markdown cells to explain what each code cell does
- Keep notebooks focused on a single workflow or concept
- Place livebooks in a dedicated directory (e.g., `notebooks/` or `livebooks/`)
## Organizing Extras
### Directory Conventions
```text
project/
README.md
CHANGELOG.md
guides/
getting-started.md
configuration.md
deployment.md
architecture.md
cheatsheets/
query-syntax.cheatmd
router-helpers.cheatmd
notebooks/
data-pipeline.livemd
sensor-setup.livemd
Ordering in Sidebar
Extras appear in the order they are listed in the extras option. Group related pages together:
defp extras do
[
"README.md",
"guides/getting-started.md",
"guides/configuration.md",
"guides/architecture.md",
"guides/deployment.md",
"cheatsheets/query-syntax.cheatmd",
"cheatsheets/router-helpers.cheatmd",
"notebooks/data-pipeline.livemd",
"CHANGELOG.md"
]
end
Naming Conventions
- Use kebab-case for filenames:
getting-started.md, notGetting Started.md - The first
h1heading becomes the sidebar title (override with the keyword tuple form) - Keep filenames short -- they become part of the URL in hosted docs
- Prefix with numbers if you need explicit ordering without
groups_for_extras:01-getting-started.md
Grouping with groups_for_extras
Combine ordering with grouping for the best sidebar organization:
defp groups_for_extras do
[
"Introduction": [
"README.md"
],
"Guides": [
"guides/getting-started.md",
"guides/configuration.md",
"guides/architecture.md",
"guides/deployment.md"
],
"Cheatsheets": [
"cheatsheets/query-syntax.cheatmd",
"cheatsheets/router-helpers.cheatmd"
],
"Tutorials": [
"notebooks/data-pipeline.livemd",
"notebooks/sensor-setup.livemd"
]
]
end
Extras not matching any group appear in a default section at the bottom of the sidebar.