Of the three main blockers in terms of look feel that I’ve used as an excuse to not to start thinking about moving course materials over to JupyterLab/RetroLab, I’ve now got hacky extensions for styling notebooks, empinken style, and enable cell run status indicators. The next one is purely cosmetic – adding custom logos.
The proper way to do this (?!) is probably to use a custom theme. See https://github.com/g2nb/jupyterlab-theme/ for an example of adding custom logos to to a custom theme.
Whilst it doesn’t appear that there is straightforward “parameter configurable” way of doing this, and there is zero help on the various forums and issues trackers for anyone who does want to achieve this (because believe it or not, the setting does matter sometimes, and learners particularly, often benefit from thinking they’re in a “safe space” that is suggested by branded environments), I finally had a poke around for some hacky ways of doing this.
It does, of course, require all the pain of building an extension, but we don’t need much more than some simple CSS and some simple JS, so we can get away with using the the JupyterLab Javascript cookiecutter extension.
To open the cookiecutter files into a pre-existing directory, such as a one created by cloing a remote Gihub repo onto your desktop, run the command:
cookiecutter https://github.com/jupyterlab/extension-cookiecutter-js -fs
You can then set up the environment:
cd my_extension/
`
python -m pip install .
And do a test build:
jlpm run build && python3 -m build
You can then install the resulting package:
pip3 install ./dist/
my_extension
-0.1.0-py3-none-any.whl
To customise the logos, in the ./style/base.css
file, we can hide the default JupyterLab logo and add our own:
#jp-MainLogo {
background-image: url(./images/OU-logo-36x28.png);
background-repeat: no-repeat;
}
#jp-MainLogo > svg {
visibility: hidden;
}
#jp-RetroLogo {
background-image: url(./images/OU-logo-53x42.png);
background-repeat: no-repeat;
}
#jp-RetroLogo > svg {
visibility: hidden;
}
The images should be place in a new ./style/images/
folder.
To have a go at hacking the favicon (which works on a “full server, ish, but not in JupyterLite?), we need some simple Javascript in ./style/index.js
:
import './base.css';
// Via: https://discourse.jupyter.org/t/changing-favicon-with-notebook-extension/2721
let head = document.head || document.getElementsByTagName('head')[0];
let link = document.createElement('link')
let oldLink = document.getElementsByClassName('favicon');
link.rel = 'icon';
link.type = 'image/x-icon';
link.href = 'https://www.open.ac.uk/oudigital/v4/external/img/favicons/favicon.png';
if (oldLink) {
link.classList = oldLink[0].classList;
head.removeChild(oldLink[0]);
}
head.appendChild(link);
I’m not sure how to reference a local, statically packed favicon shipped with the extension, so for now I pull in a remote one.
Rebuild the extension, and reinstall it:
jlpm run build && python3 -m build && pip3 install --upgrade
./dist/
my_extension
-0.1.0-py3-none-any.whl
To make it easier to distribute, I remove the dist/
element from the .gitignore
file and push everything to a repo.
The following Github action acan be manually triggered to build a JupyterLite enviornment pushed to Github Pages (in your Github repo, you need to go to Settings > Pages
and select the gh-pages
branch as the target for the site.
I include the custom extension in the JupyerLite build via a requirements-jupyterlite.txt
file which includes the following:
./dist/my_extension-0.1.0-py3-none-any.whl
name: JupyterLite Build and Deploy
on:
release:
types: [published]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install the dependencies
run: |
python -m pip install -r requirements-jupyterlite.txt
- name: Build the JupyterLite site
run: |
cp README.md content
jupyter lite build --contents content
- name: Upload (dist)
uses: actions/upload-artifact@v2
with:
name: jupyterlite-demo-dist-${{ github.run_number }}
path: ./_output
deploy:
if: github.ref == 'refs/heads/main'
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2.3.1
- uses: actions/download-artifact@v2
with:
name: jupyterlite-demo-dist-${{ github.run_number }}
path: ./dist
- name: Deploy
uses: JamesIves/github-pages-deploy-action@4.1.3
with:
branch: gh-pages
folder: dist
A demo of the extension can then be tried purely withing the browser via JupyterLite.
Repo is here: https://github.com/innovationOUtside/jupyterlab_ou_brand_extension
Demo is here: http://innovationoutside.github.io/jupyterlab_ou_brand_extension/
Files changed compared to cookiecutter generated pages here: https://github.com/innovationOUtside/jupyterlab_ou_brand_extension/commit/688863cb79557920b1950a9a9b0331ccedcdac39