written by Eric J. Ma on 2020-01-18 | tags:
For my PyData Ann Arbor Meetup talk, I decided to use
reveal-md and a Markdown file to generate my slides. Here, I'd like to write about how I used
reveal-md and Travis CI to continually publish my slides as I updated them, thus making them accessible to everybody on the web.
reveal-md is nothing more than a live web server for that converts Markdown files into
reveal.js slides that can be hosted via a web server, static site, or PDF.
I much prefer to use Markdown to write my slides, as doing so comes with one big benefit: I am focused on the content that I want to deliver, and not the less important details that are easy to screw up (animations, positioning, etc.). Constraining what's accessible to me forces me to be extremely clear and succinct on what I'm trying to communicate. And if I really desired anything fancier, I could weave in some HTML with no issue.
Let’s walk through the steps needed to make this a reality for you!
On GitHub, create a new repository that has a nice and informative name. (For now, we’ll just refer to that repository as
my-talk for convenience.)
To get setup, you need to make sure that
reveal-md is on your
PATH. I choose to use
conda environments to manage my packages, so I have a slightly convoluted way of doing this, by using
conda to install
nodejs (which installs the
npm node package manager), followed by using the node package manager to install
reveal-md. We first start by preparing an
environment.yml specification file that
conda can use to build your environment:
name: my_talk channels: - conda-forge dependencies: - python=3.8 - nodejs
Now, we can execute the installation commands.
# Installation commands # Create environment conda env create -f environment.yml # Activate environment conda activate my_talk # Install reveal-md npm install -g reveal-md
To learn more about
conda hacks that can improve your efficiency, I have a blog post that you can reference.
Before we go onto the automation, it’s important that you get a feel for the workflow so you know what’s being automated.
Let’s write a simple Markdown file that has two slides:
--- title: My Fancy Talk! --- # My Fancy Talk Speaker Name Date --- ## Hello!
Save it as
slides.md. The filename isn’t special, it’s just convenient to remember.
To see more of what
reveal.js can do, check out the RevealJS GitHub repository!
To serve it up, run the following command at your terminal:
reveal-md slides.md # replace with the filename of your slides
Your browser should now pop open, and your slides will be there!
reveal.js made simple, thanks to
Now, you can continue editing your slides, keeping in mind the following pointers.
--- (three of them) denotes horizontal slide transition, while
---- (four of them) denotes vertical slide transitions. Use this to organize your content.
Secondly, to progressively reveal pointers on a slide, you need to add the following HTML comment right after the element. For example, to show bullet points progressively:
- Bullet Point 1 <!-- .element class="fragment" --> - Bullet Point 2 <!-- .element class="fragment" -->
If you need fancier things, you can weave in HTML at your own convenience. For example, I embedded an HTML table to organize
imcmc logos that I had previously compiled.
You’ll now want to create a
.travis.yml, which commands Travis to do things. It’s generally nothing more than a collection of bash commands that are executed in order. An example Travis configuration file from my data science testing talk looks like this:
language: python python: # We don't actually use the Travis Python, but this keeps it organized. - "3.5" install: # We do this conditionally because it saves us some downloading if the # version is the same. - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; - bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH" - hash -r - conda config --set always_yes yes --set changeps1 no - conda update -q conda # Useful for debugging any issues with conda - conda info -a # Install Python and required packages. - conda env create -f environment.yml - source activate testing-for-data-scientists # Install reveal-md - npm install -g reveal-md script: # Create the docs directory. This is where we will be publishing from # (see the "deploy" section below). - mkdir -p docs/ # Use reveal-md to generate static docs. - reveal-md slides.md --static docs --disable-auto-open --theme white - cp -r assets docs/. # Use reveal-md to generate PDF. - reveal-md slides.md --disable-auto-open --theme white --print slides.pdf - cp slides.pdf docs/. # This is an example to deploy to a branch through Travis. deploy: provider: pages skip-cleanup: true github-token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable keep-history: true # We read the master branch on: branch: master # Take the docs/ directory local-dir: docs # Publish to the gh-pages branch target-branch: gh-pages verbose: true
You’ll notice that the commands we want Travis to execute are basically the same as those we executed manually. The only difference now is that we command
reveal-md to build a static site under the directory
site/, which we then command Travis to push to GitHub pages.
deploy section, we are specifying to Travis that we want all of the content under the directory
site/ to be pushed to the
gh-pages branch of our repository. (We have not yet connected Travis to our repo; that will happen next, so sit tight!)
Notice also the
$GITHUB_TOKEN environment variable: we need to declare that as well. The
GITHUB_TOKEN is an authentication token that GitHub will recognize when Travis CI pushes the
site/ directory to
gh-pages. Because underneath the hood we are using
bash syntax in the YAML file, when we declare the
GITHUB_TOKEN, we do it without the
$ symbol, but when we need to grab it from the environment, we include the
$ symbol, just as in regular plain old
Under your repository settings, generate a deploy/"personal access" token. Exact docs are here, so in the spirit of "don’t repeat yourself" and "learn to read the docs", I will encourage you to read them.
Once you have generated a deploy key, copy them somewhere - you will need it later. (Tip: also make sure you don’t accidentally save it to disk!)
On Travis CI, connect your Travis CI account to GitHub, and then enable Travis to look for changes on the
my-talk repository. Generally, this is done by going to your user settings, and searching for "Legacy Services Integration", then toggling the checkbox to enable it on your
Once that is done, go into the Travis CI settings for the repository. Navigate to the "Environment Variables" section, and declare the
GITHUB_TOKEN there. Be sure to keep it hidden from the output!
To turn on GitHub pages, we are going to stick to a pretty sane and widely-used set of practices when interacting with GitHub repositories and static sites.
Firstly, on the GitHub repository for
my-talk, create a new branch (using the web interface or through the CLI) called
gh-pages. This time round, the name is definitely special, as GitHub recognizes this branch as a legitimate GitHub pages branch to serve content from.
Secondly, go to the repository settings (not your user settings), and ensure that GitHub pages is enabled for the repository. Usually, adding the
gh-pages branch will result in this option being automagically turned on.
git add slides.md environment.yml .travis.yml git commit -m "first commit" git push
Your slides, environment config, and Travis CI config files are now pushed to GitHub.
Travis is now going to be building your slides and pushing them to the
gh-pages branch. If all goes well, you will see the slides show up at the URL:
https://your_username.github.io/my-talk. (Naturally, replace
your_username with your GitHub username, and
my-talk with your repository name.
In case the build fails, you can inspect the output. Any errors are basically your standard bash
stderr, so if you know how to debug error messages, you should be able to debug issues with the build.
Going beyond serving up
reveal.js slides, Travis hooked up to GitHub pages can help you build static sites very easily.
If you use a static site generator (such as Lektor, Hugo, Pelican, Gatsby or Nikola), then you can create websites whose sources are fully under your control, 100% customizable, and fast to load. I do not blog on Medium because I desire full control over the display of my blog content, and I want to be able to take it anywhere I desire, without relying on a platform that might lock my content in. My personal website uses Lektor + Travis to push to GitHub pages; please feel free to look at the source and raid the repo for anything you’d like!
Addendum: I learned today from a fellow friend Nathan Matias that Netflix’s blog posts on Medium have been paywalled. Another reason for us to take back hosting of slides and blog content into our own hands!
Today I learned the @netflix tech blog posts are paywalled by Medium and I may have to take their post off my syllabus.— J. Nathan Matias (@natematias) January 17, 2020
Now I wonder if they paywalled posts which I intend to be freely available. Have any of you found that Medium was unexpectedly charging people for your work?
I send out a newsletter with tips and tools for data scientists. Come check it out at Substack.
If you would like to receive deeper, in-depth content as an early subscriber, come support me on Patreon!