When creating an OpenSource library and hosting it on hex.pm, you should provide documentation. Mix comes with mix hex.publish docs to help make that easy. However, what if you want to use the same documentation tools for a non-published Phoenix project?

Updated Nov 2016 for information on using in an umbrella app and more.

ExDoc

ExDoc is a documentation generation tool for Elixir

ExDoc generates web documentation for any elixir project and that includes your phoenix applications.

ExDoc on GitHub

So use it already

Add it to your project but only for the dev environment.

def deps do
  [{:ex_doc, "~> 0.13", only: :dev}]
end

Install the package…

mix deps.get

Oddly, the new mix docs mix task may not show up yet in mix --help. It didn’t for me. Go ahead and run it anyway. Once you do, it will show up in the mix tasks.

$ mix docs
Docs successfully generated.
View them at "doc/index.html".

Now it shows up as expected.

$ mix --help
...
mix docs                 # Generate documentation for the project
...

What did it do?

It created a new doc folder at the project root and created lots of files.

display list of generated files

The important file is doc/index.html. Open that in your browser to access the generated docs.

Hide some of those modules

With a Phoenix app, you may end up with a lot of modules being documented that you don’t want to document and otherwise clutter up the information you are trying to convey.

Adding @moduledoc false will not only tell ExDoc you don’t want to provide documentation for the module, it will completely suppress it from the generated documentation.

defmodule DocDemo.Endpoint do
  @moduledoc false
end

The same holds true with @doc false for suppressing a function from the documentation.

After sprinkling around a little @moduledoc false here and there, it cleaned up well. Here’s a sample new Phoenix project’s ExDoc docs.

sample generated doc

Add your readme and other markdown files

ExDoc supports adding “extras” to your documentation project. This can include your readme and any other markdown files you create. Some suggestions to consider:

  • GettingStarted.md - file for onboarding new team members
  • guides/testing.md - guide for how to test the application (does it require chromedriver? hound? special setup?)
  • README.md - the project’s readme file that hopefully has useful information in it
  • CONTRIBUTING.md - information on how to contribute to the project

You customize the ExDoc settings in your mix.exs project file under the docs section. (At the bottom)

defmodule DocDemo.Mixfile do
  use Mix.Project

  def project do
    [app: :doc_demo,
     version: "0.0.1",
     elixir: "~> 1.2",
     elixirc_paths: elixirc_paths(Mix.env),
     compilers: [:phoenix, :gettext] ++ Mix.compilers,
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     aliases: aliases(),
     deps: deps(),
     docs: docs()
   ]
  end

  defp docs do
    [
      source_url: "https://github.com/YourAcct/project",
      extras: ["README.md", "markdown/custom_page.md"]
    ]
  end

end  

Extras

Notice the docs section added at the bottom adds the project’s readme file. The readme shows up in the “Pages” section of the generated documentation. You can list any set of other files you want included in the documentation here as well. In the example above I link to a “custom_page.md” file in the “markdown” folder.

Source URL

In the docs function, I show the source_url option. This feature understands Github and adds a “</>” link to the documentation for a function or module linking directly to that page in your Github Repo. Slick!

Note: If you link to code that isn’t on master yet (a branch or local development), then the generated link will 404.

In an Umbrella

ExDoc works well when in an umbrella app too. You can run mix docs at the umbrella project root and it runs it for each project. Note that it doesn’t create a single combined doc, but docs for each project in the umbrella.

In an umbrella, you need to update the source_url to link deeper to the specific app in the umbrella. Fortunately this is supported too!

defp docs do
  [
    source_url_pattern: "https://github.com/YourAcct/project/blob/master/apps/doc_demo/%{path}#L%{line}",
    extras: ["README.md", "markdown/custom_page.md"]
  ]
end

Writing documentation

In your documentation, when referencing a module or function, if you give it a fully qualified name in back ticks like List.delete_all/2, ExDocs will turn that into a link for you. Note to include a function’s arrity.

Some resources to start you off in best-practices for writing your docs.

Closing

ExDoc is a great tool for building good-looking, hassle-free documentation for your Elixir and Phoenix projects. It is up to you if you want the generated files to be committed to your git repository or ignored. Either way, it is a powerful tool to help your team share knowledge and project information.

See ExDoc on GitHub or mix help docs for more usage information.

What tips or tricks do you have for project documentation?