Customize the HTML export of Pluto notebooks

The static-export-template makes it easy to set up a repository of Pluto notebooks that automatically get deployed to GitHub pages. This happens via the export_directory function of PlutoSliderServer.

Is there any way to inject some .js and .css files into the exported .html file? In my case, I would like to insert

<link href="https://juliaquantumcontrol.github.io/QuantumControl.jl/dev/assets/topbar/topbar.css" rel="stylesheet" type="text/css"/>
<script src="https://juliaquantumcontrol.github.io/QuantumControl.jl/dev/assets/topbar/topbar.js"></script>

just before the </head> closing tag, in order to inject the same top-navigation bar that I use across the JuliaQuantumControl org. I suppose I could post-process all the generated .html files in my ExportPluto.yaml file, but isn’t there a more straightforward / built-in way of doing this?

The Pluto documentation itself looks like it’s a bunch of Pluto notebooks, and it similarly has an extra navigational bar on the the left. So does the original Computational Thinking website. For neither one, I’ve been able to find the workflow that produces the HTML from the original notebook files. Maybe @fonsp can provide some details on how this was set up?

Note that I only want to (minimally) customize the HTML generated during the export, not the general Pluto UI when running the notebook locally with Pluto.run(). So it doesn’t seem like @aplavin’s PlutoStyles would be suitable for this, and I don’t think I want to be adding content in the individual notebooks to load additional JS/CSS code. I’d definitely want to keep the “Edit or run this notebook” button (I’ve already tested that it combines nicely with my top-navbar), so PlutoStaticHTML does not seem like the correct solution, either.

Any hints?

1 Like

Is there any way to inject some .js and .css files into the exported .html file?

I’ll take the lack of a response as a “No” on that.

Manually injecting the extra code in CI turned out to be quite straightforward, though:

- name: Inject top navigation bar and metadata
  run: |
    INSERT_CODE_HEAD='<link href="https://juliaquantumcontrol.github.io/QuantumControl.jl/dev/assets/topbar/topbar.css" rel="stylesheet" type="text/css"/><script src="https://juliaquantumcontrol.github.io/QuantumControl.jl/dev/assets/topbar/topbar.js"></script>'
    INSERT_META_DESCRIPTION='<meta name="description" content="Tutorials for the JuliaQuantumControl Organization."/>'
    # The specific text of the above meta tag is required for topbar.js to properly recognized that a page belongs in the "Tutorials" tab
    for file in *.html; do
      # Use sed with /i to insert the code before the specified location
      sed -i "/<\/head>/i $INSERT_CODE_HEAD" "$file"
      sed -i "/<meta property='og:type' content='article'>/i $INSERT_META_DESCRIPTION" "$file"
    done

That gives me the topbar menu I need for the JuliaQuantumControl organization for the Tutorials tab.

Small nitpick: the font of the menu items in the other tabs, e.g., “QuantumControl.jl”, is very slightly thicker than the same items in Tutorials. I have not been able to figure out what in the CSS is missing to ensure that the menu bar looks exactly the same when combined with Documenter’s CSS and Pluto’s CSS. Are there any frontend specialists here that can figure that one out?

Hey @goerz ! Thanks for your question!

Your approach is fine, go for it! It will keep working in future Pluto/PSS versions.

PlutoSliderServer does not have configuration for this right now. It would be easy to add if you want to make a PR (with tests and docs, search for header_html in our source code).

The plutojl.org website and https://computationalthinking.mit.edu/ both use PlutoPages.jl, a static site generator (based on eleventy) with more advanced export options compared to PlutoSliderServer. Their source code is open source if you want to take a look. But I think this would overcomplicate your setup.


About the font issue, be sure to use the Chrome/Firefox dev tools (web inspector) if you haven’t yet. The issue is that you set the style font-family: "Lato Medium", -apple-system, ... for the nav, but the “Lato Medium” font only gets loaded by Documenter.jl pages. Your two options:

  • (recommended) change to font-family: system-ui, sans-serif; or this one if you want emoji. This will look the same on all pages because it only uses system fonts.
  • add an import for the “Lato Medium” font manually, using Google Fonts.

:cherry_blossom:

3 Likes