ExDoc Configuration
Quick Reference
Topic Reference
Markdown, cheatsheets (.cheatmd), livebooks (.livemd) references/extras-formats.md
Custom head/body tags, syntax highlighting, nesting, annotations references/advanced-config.md
Dependency Setup
Add ExDoc to mix.exs deps:
defp deps do [ {:ex_doc, "~> 0.34", only: :dev, runtime: false} ] end
Project Configuration
Configure your project/0 function in mix.exs :
def project do [ app: :weather_station, version: "0.1.0", elixir: "~> 1.17", start_permanent: Mix.env() == :prod, deps: deps(),
# ExDoc
name: "WeatherStation",
source_url: "https://github.com/acme/weather_station",
homepage_url: "https://acme.github.io/weather_station",
docs: docs()
] end
The docs/0 Function
Define a private docs/0 function to keep project config clean:
defp docs do [ main: "readme", logo: "priv/static/images/logo.png", output: "doc", formatters: ["html", "epub"], source_ref: "v#{@version}", extras: extras(), groups_for_modules: groups_for_modules(), groups_for_extras: groups_for_extras() ] end
Key Options
Option Default Description
main
"api-reference"
Landing page module name or extra filename (without extension)
logo
nil
Path to logo image displayed in sidebar
output
"doc"
Output directory for generated docs
formatters
["html"]
List of output formats ("html" , "epub" )
source_ref
"main"
Git ref used for "View Source" links
assets
nil
Map of source directory to target directory for static assets
deps
[]
Links to dependency documentation
Setting the Landing Page
The main option controls what users see first:
Use the README as the landing page (most common)
docs: [main: "readme"]
Use a specific module as the landing page
docs: [main: "WeatherStation"]
Use a custom guide
docs: [main: "getting-started"]
The value matches the extra filename without its extension, or a module name.
Extras
Extras are additional pages beyond the API reference. Add them as a list of file paths:
defp extras do [ "README.md", "CHANGELOG.md", "LICENSE.md", "guides/getting-started.md", "guides/configuration.md", "guides/deployment.md", "cheatsheets/query-syntax.cheatmd", "notebooks/data-pipeline.livemd" ] end
Controlling Extra Titles
By default, ExDoc uses the first h1 heading as the title. Override with a keyword tuple:
defp extras do [ {"README.md", [title: "Overview"]}, {"CHANGELOG.md", [title: "Changelog"]}, "guides/getting-started.md" ] end
Ordering
Extras appear in the sidebar in the order listed. Put the most important pages first:
defp extras do [ "README.md", "guides/getting-started.md", "guides/architecture.md", "guides/deployment.md", "CHANGELOG.md" ] end
Grouping
Grouping Modules
Organize modules into logical sections in the sidebar:
defp groups_for_modules do [ "Sensors": [ WeatherStation.Sensor, WeatherStation.Sensor.Temperature, WeatherStation.Sensor.Humidity, WeatherStation.Sensor.Pressure ], "Data Processing": [ WeatherStation.Pipeline, WeatherStation.Pipeline.Transform, WeatherStation.Pipeline.Aggregate ], "Storage": [ WeatherStation.Repo, WeatherStation.Schema.Reading, WeatherStation.Schema.Station ] ] end
Use regex to group by pattern:
defp groups_for_modules do [ "Sensors": [~r/Sensor/], "Schemas": [~r/Schema/], "Pipeline": [~r/Pipeline/] ] end
Modules not matching any group appear under a default "Modules" heading.
Grouping Functions
Group functions within a module using groups_for_docs :
defp docs do [ groups_for_docs: [ "Lifecycle": &(&1[:section] == :lifecycle), "Queries": &(&1[:section] == :queries), "Mutations": &(&1[:section] == :mutations) ] ] end
Tag functions in your module with @doc metadata:
@doc section: :lifecycle def start_link(opts), do: GenServer.start_link(MODULE, opts)
@doc section: :queries def get_reading(station_id), do: Repo.get(Reading, station_id)
Grouping Extras
Organize guides, cheatsheets, and notebooks in the sidebar:
defp groups_for_extras do [ "Guides": [ "guides/getting-started.md", "guides/configuration.md", "guides/deployment.md" ], "Cheatsheets": [ "cheatsheets/query-syntax.cheatmd", "cheatsheets/ecto-types.cheatmd" ], "Tutorials": [ "notebooks/data-pipeline.livemd", "notebooks/sensor-setup.livemd" ] ] end
Use glob patterns for convenience:
defp groups_for_extras do [ "Guides": ~r/guides/./, "Cheatsheets": ~r/cheatsheets/./, "Tutorials": ~r/notebooks/.*/ ] end
Dependency Doc Links
Link to documentation for your dependencies so ExDoc cross-references resolve:
defp docs do [ deps: [ ecto: "https://hexdocs.pm/ecto", phoenix: "https://hexdocs.pm/phoenix", plug: "https://hexdocs.pm/plug" ] ] end
This enables references like t:Ecto.Schema.t/0 to link directly to the dependency docs.
Generating Docs
Generate HTML docs
mix docs
Open in browser
open doc/index.html
Complete mix.exs Example
defmodule WeatherStation.MixProject do use Mix.Project
@version "1.3.0" @source_url "https://github.com/acme/weather_station"
def project do [ app: :weather_station, version: @version, elixir: "~> 1.17", start_permanent: Mix.env() == :prod, deps: deps(), name: "WeatherStation", source_url: @source_url, homepage_url: "https://acme.github.io/weather_station", docs: docs() ] end
defp docs do [ main: "readme", logo: "priv/static/images/logo.png", source_ref: "v#{@version}", formatters: ["html"], extras: extras(), groups_for_modules: groups_for_modules(), groups_for_extras: groups_for_extras(), deps: [ ecto: "https://hexdocs.pm/ecto", phoenix: "https://hexdocs.pm/phoenix" ] ] end
defp extras do [ "README.md", "CHANGELOG.md", "guides/getting-started.md", "guides/configuration.md", "guides/deployment.md", "cheatsheets/query-syntax.cheatmd", "notebooks/data-pipeline.livemd" ] end
defp groups_for_modules do [ "Sensors": [~r/Sensor/], "Data Processing": [~r/Pipeline/], "Storage": [~r/Schema|Repo/] ] end
defp groups_for_extras do [ "Guides": ~r/guides/./, "Cheatsheets": ~r/cheatsheets/./, "Tutorials": ~r/notebooks/.*/ ] end
defp deps do
[
{:phoenix, "> 1.7"},
{:ecto_sql, "> 3.12"},
{:ex_doc, "~> 0.34", only: :dev, runtime: false}
]
end
end
When to Load References
-
Setting up cheatsheets or livebooks as extras -> extras-formats.md
-
Injecting custom CSS/JS, configuring syntax highlighting, or tuning module nesting -> advanced-config.md