diff --git a/.prettierignore b/.prettierignore
index 0bc25361..c2ee592e 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,3 +1,4 @@
share/jupyterhub/templates/
share/jupyterhub/static/js/admin-react.js
jupyterhub/singleuser/templates/
+docs/source/_templates/
diff --git a/docs/source/_templates/page.html b/docs/source/_templates/page.html
new file mode 100644
index 00000000..098c156a
--- /dev/null
+++ b/docs/source/_templates/page.html
@@ -0,0 +1,2 @@
+{%- set _meta = meta | default({}) %}
+{%- extends _meta.page_template | default('!page.html') %}
diff --git a/docs/source/_templates/redoc.html b/docs/source/_templates/redoc.html
new file mode 100644
index 00000000..2df21470
--- /dev/null
+++ b/docs/source/_templates/redoc.html
@@ -0,0 +1,34 @@
+{%- extends "!layout.html" %}
+
+{# not sure why, but theme CSS prevents scrolling within redoc content
+ # If this were fixed, we could keep the navbar and footer
+ #}
+{%- block css %}{%- endblock %}
+{%- block docs_navbar %}{%- endblock %}
+{%- block footer %}{% endblock %}
+{%- block body_tag %}
+
+{%- endblock %}
+
+{%- block extrahead %}
+{{ super() }}
+
+
+{%- endblock %}
+
+{%- block content %}
+
+
+{%- endblock %}
diff --git a/docs/source/conf.py b/docs/source/conf.py
index c4db7833..9215b14f 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -7,13 +7,17 @@ import datetime
import io
import os
import subprocess
+from pathlib import Path
+from urllib.request import urlretrieve
from docutils import nodes
from sphinx.directives.other import SphinxDirective
+from sphinx.util import logging
import jupyterhub
from jupyterhub.app import JupyterHub
+logger = logging.getLogger(__name__)
# -- Project information -----------------------------------------------------
# ref: https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
#
@@ -119,7 +123,24 @@ class HelpAllDirective(SphinxDirective):
return [par]
+templates_path = ["_templates"]
+
+
+def stage_redoc_js(app, exception):
+ """Download redoc.js to our static files"""
+ redoc_version = "2.1.3"
+ redoc_url = (
+ f"https://cdn.redoc.ly/redoc/v{redoc_version}/bundles/redoc.standalone.js"
+ )
+
+ dest = Path(app.builder.outdir) / "_static/redoc.js"
+ if not dest.exists():
+ logger.info(f"Downloading {redoc_url} -> {dest}")
+ urlretrieve(redoc_url, dest)
+
+
def setup(app):
+ app.connect("build-finished", stage_redoc_js)
app.add_css_file("custom.css")
app.add_directive("jupyterhub-generate-config", ConfigDirective)
app.add_directive("jupyterhub-help-all", HelpAllDirective)
diff --git a/docs/source/reference/rest-api.md b/docs/source/reference/rest-api.md
index 6a0f11bd..2dd79dd9 100644
--- a/docs/source/reference/rest-api.md
+++ b/docs/source/reference/rest-api.md
@@ -1,33 +1,14 @@
-
+---
+page_template: redoc.html
+# see: https://redocly.com/docs/redoc/config/ for options
+redoc_options:
+ hideHostname: true
+ hideLoading: true
+---
(jupyterhub-rest-API)=
# JupyterHub REST API
-Below is an interactive view of JupyterHub's OpenAPI specification.
-
-
-
-
-
-
-
-
-
-
-
+NOTE: The contents of this markdown file are not used,
+this page is entirely generated from `_templates/redoc.html` and `_static/rest-api.yml`