Share ExDoc output
mix docs is one of the better documentation experiences in any ecosystem —
module docs, @doc examples that are also tests, guides, a search box that
works. It writes the whole thing to doc/ and then the ecosystem assumes the
next step is publishing to Hex.
For an internal umbrella app, a client project, or a release candidate, that assumption is wrong in both directions: you do not want it public, and it is not a package.
Build it
MIX_ENV=docs mix docs
doc/
├── index.html
├── MyApp.Accounts.html # one page per module
├── readme.html changelog.html
├── dist/ # js, css, the search index
└── assets/
Open index.html from the filesystem and the pages render but the search box
does not: ExDoc fetches its index over XHR, which a browser blocks from a
file:// origin. It is the same
origin problem that breaks most
generated docs when they are zipped and emailed.
Drop the folder in
Drag doc/ (or a zip of it) into Comma:
index.htmlbecomes the report body — the page carrying the comment layer.- Module pages, guides,
dist/andassets/upload alongside it, and relative references are rewritten to the uploaded copies, so search works and the sidebar navigates. - Scripts run inside a sandboxed iframe (
allow-scripts, noallow-same-origin).
Access per report: private, your team, anyone signed in at your domain, or anyone with the link — see sharing & access control.
From CI
MIX_ENV=docs mix docs
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html doc/index.html \
--arg t "MyApp — $(mix run -e 'IO.puts Mix.Project.config()[:version]')" \
'{title: $t, html: $html}')"
Supporting pages go up through POST /api/v1/reports/$REPORT_ID/assets as
base64 — one call per file, worth scripting once. See the
API reference and publishing from CI.
An umbrella is the case that needs this most
An umbrella project generates docs per app, and the thing nobody has is a
single readable view of the boundary between them — which context owns which
schema, and which public function another app is allowed to call. Publishing
each app's doc/ as its own report gives you that as a set of links, and
comments anchored on a specific @doc are where the boundary argument actually
belongs. See commenting on HTML.
Limits
- Entry HTML: 5 MB. Assets: 25 MB per file, 250 MB and 500 files total.
A large app with many modules can approach 500 pages —
:filter_modulesor splitting per umbrella app keeps it under. - Scripts run, sandboxed — no same-origin access.
- 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.