Prepare your Rust API docs for Github Pages
Ben Lovy

Ben Lovy @deciduously

About: Just this guy, you know?

Location:
Boston, MA, USA
Joined:
Mar 19, 2018

Prepare your Rust API docs for Github Pages

Publish Date: Nov 9 '21
41 5

Rust comes with a built-in documentation system, rustdoc. It's great, use it.

Github comes with a built-in web hosting service, Github Pages. It's great, use it.

To use Github Pages, you can either create a directory in your repository to host your deployed web content or a separate branch and then activate the feature in the "Pages" section of your repository settings:

settings screenshot

Great!

You get a directory located at <project>/target/doc when you run cargo doc to generate your Rust documentation. It contains the complete web content ready to publish. If you execute cargo doc --open, your default browser will open up and show you what it generated.

Unfortunately, this folder can't be copied strictly as-is. If you try, you'll get a 404. This is because Github Pages is looking for an index.html file in the root directory of wherever it's pointed. However, cargo doc created a subdirectory for your crate specifically, where index.html lives. Here's my example for a Rust package called build_wheel:



$ tree target/doc/
target/doc
├── ayu.css
├── brush.svg
├── build_wheel
│  ├── all.html
│  ├── fn.build_wheel.html
│  ├── index.html          <-- RIGHT HERE
│  ├── sidebar-items.js
│  ├── struct.Config.html
│  └── struct.Tag.html
├── clipboard.svg
/* ... etc, etc... */


Enter fullscreen mode Exit fullscreen mode

Uh-oh, it's nested. Github can't find it. You can't just make a symbolic link to an index.html in the root directory because all the relative links inside will break.

Luckily, the fix is easy. You simply need to create an index.html that reroutes where you want. This file only consists of one line:



<meta http-equiv="refresh" content="0; url=build_wheel">


Enter fullscreen mode Exit fullscreen mode

This file uses the http-equiv meta attribute to point immediately to the build_wheel subdirectory and load the index.html file found there. Just replace the directory name with the name of your package.

You can easily automate this in a simple script:



cargo doc --no-deps
rm -rf ./docs
echo "<meta http-equiv=\"refresh\" content=\"0; url=build_wheel\">" > target/doc/index.html
cp -r target/doc ./docs


Enter fullscreen mode Exit fullscreen mode

Feel free to get as fancy as you want for pulling the actual name. I've just hardcoded it ¯\(ツ)/¯.

When Github Pages tries to build your content, now it will find this root index page. Users will load this page and immediately refresh the page you intended to display, and all the internal links generated by rustdoc will work as expected.

Neat.

Cover photo by Kelly Sikkema on Unsplash

Comments 5 total

  • Tim McNamara
    Tim McNamaraNov 9, 2021

    This is quite cunning. I like it.

    • Stephan Sokolow
      Stephan SokolowNov 12, 2021

      It's also how I ensured no broken links when I was migrating the root ssokolow.com site to Jekyll.

      Just have a bunch of folders containing redirecting index.html files named after the old non-HTML routes from when I was using MoinMoin. (eg. ssokolow.com/ContactMe )

  • Denys Séguret
    Denys SéguretNov 10, 2021

    This is interesting but why not using docs.rs where all documentations are available as soon as you publish your crate ?

    • Ben Lovy
      Ben LovyNov 10, 2021

      I'm using this for a crate that's part of a build process specific to one project. It's not likely to end up published, but I still want to provide accessible documentation. You're definitely right for most public packages, just use the existing infrastructure!

  • Zoe
    ZoeMar 15, 2023

    I translated the script (and reordered it slightly) for a Windows bat file. Use as you please

    cargo doc --no-deps
    rmdir /s ./docs
    robocopy target/doc docs /s
    echo|set /p="<meta http-equiv="refresh" content="0; url=PROJECT_NAME/index.html">" > docs/index.html
    
    Enter fullscreen mode Exit fullscreen mode
Add comment