Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Developer guide

This guide is for contributors who want to understand the codebase, make changes, or help maintain the project.

Architecture overview

How it works

  1. Templates: Jinja2 templates render the initial HTML structure for the profile selection form

  2. React App: JavaScript/React code handles the interactive UI, form state, and dynamic features

  3. Webpack: Bundles the frontend code and outputs it to static/

  4. HTTP Handlers: JupyterHub serves the static assets when the profile page loads

  5. KubeSpawner Integration: The setup_ui() function configures KubeSpawner to use these templates and handlers

Design philosophy

Keep this tool a fairly simple React app focused on profile selection. This won’t become a super-heavy, complex application.

Why react?

If this file gets over 200 lines of code long (not counting docs / comments), start using a framework

From the BinderHub JS Source Code

The file did get more than 200 lines long, and BinderHub learned this lesson the hard way. For this project:

Development setup

Setting up minikube

Currently, these instructions work with minikube but can be adapted to any local Kubernetes setup.

  1. Download, set up and start minikube

  2. Allow spawned JupyterHub server pods to talk to the JupyterHub instance on your local machine:

    # Linux
    sudo ip route add $(kubectl get node minikube -o jsonpath="{.spec.podCIDR}") via $(minikube ip)
    
    # macOS
    sudo route -n add -net $(kubectl get node minikube -o jsonpath="{.spec.podCIDR}") $(minikube ip)

    You can later undo this with:

    # Linux
    sudo ip route del $(kubectl get node minikube -o jsonpath="{.spec.podCIDR}")
    
    # macOS
    sudo route delete -net $(kubectl get node minikube -o jsonpath="{.spec.podCIDR}")

Setting up the development environment

  1. Clone the repository:

    git clone https://github.com/2i2c-org/jupyterhub-fancy-profiles.git
    cd jupyterhub-fancy-profiles
  2. Set up a virtual environment (using venv, conda, etc.)

  3. Install Python dependencies:

    pip install -r dev-requirements.txt
    pip install -e .

    This also builds the JS and CSS assets.

  4. Install configurable-http-proxy (required for JupyterHub):

    npm install configurable-http-proxy
  5. Add configurable-http-proxy to your $PATH:

    export PATH="$(pwd)/node_modules/.bin:${PATH}"
  6. Start JupyterHub and navigate to localhost:8000:

    jupyterhub

    You can login with any username and password.

  7. If working on JS/CSS, run this in another terminal to automatically watch and rebuild:

    npm run webpack:watch

Testing

Tests for the frontend use Jest and React Testing Library for rendering components and asserting DOM state.

Run all tests

npm test

Run specific test suite

To run tests in a specific file (e.g., ProfileForm.test.tsx):

npm test ProfileForm

Making a release

We use automation to publish releases to PyPI. Release early and often!

Creating the release

  1. Update your local checkout:

    git checkout main
    git stash  # if needed
    git pull upstream main  # or origin, as needed
  2. Create a new git tag:

    git tag -a v<version-number>

    In the tag message, at minimum write: Version <version-number>

    Ideally, include a brief changelog of notable changes.

  3. Push your tag to GitHub:

    git push origin --tags
  4. Done! A new release will automatically be published to PyPI.

Generating release notes

After making the release:

  1. Install github-activity:

    pip install github-activity
  2. Generate release notes using the previous and current release tags:

    github-activity 2i2c-org/jupyterhub-fancy-profiles -s <last-release-tag> -u <this-release-tag>

    For example, for v0.5.0:

    github-activity 2i2c-org/jupyterhub-fancy-profiles -s v0.4.0 -u v0.5.0
  3. Copy the output and rearrange/categorize as needed. github-activity will automatically group PRs based on tags (e.g., enhancement, bug) or prefixes (e.g., [ENH], [BUG]).

  4. Create a GitHub release, use the tag as the title, and paste in the generated release notes.

  5. Click Publish Release.