Add ability to send notifications to selected servers instead of all.
- New ActiveServersHandler at GET /api/notifications/active-servers
- BroadcastNotificationHandler accepts optional recipients array
- UI with "Send to all" checkbox and server selection list
- Select All/Deselect All buttons, dynamic button text
- Backward compatible - sends to all if recipients not specified
- Add JUPYTERHUB_LOGO_FILE config for custom logo (served at /hub/logo)
- Fix CustomAuthorizationAreaHandler with @needs_scope decorator
- Import orm inside get() method to fix NameError
- Simplify page.html logo block (always use base_url/logo)
- Fix Add Users button to use stock btn-light colors (size only)
- Disable hover on expanded card tables via box-shadow override
- Add padding:0 to expanded user detail td cells
- Make collapse buttons more compact (0.2rem 0.3rem)
- Add left padding to username labels
- Add groups page styling (list items, card footer)
- Add notifications page styling (form, textarea, results table)
- Unify button font sizes to 0.8rem across all pages
- Set collapsed user card padding to 0
- Add subtle hover effect on admin user rows (0.015 alpha)
- Style Add Users form panel with dark mode support
- Style authorization and token pages consistently
Removed obsolete 01_nvidia-smi.sh (GPU detection handled in jupyterhub_config.py).
Renamed 02_ensure_groups.py to 01_ensure_groups.py for sequential ordering.
Changed from containrrr/watchtower:latest to nickfedor/watchtower:latest.
New image is actively maintained and compatible with latest Docker versions.
Version bump: 3.2.11 -> 3.3.1
Updated version metadata:
- VERSION_COMMENT reflects key features of v3.2.11
- Added RELEASE_TAG: RELEASE_3.2.11
- Added RELEASE_DATE: 2025-11-09
This marks the official release of version 3.2.11 with configuration-agnostic
volume management, notification broadcast, and privileged access control.
Implemented comprehensive notification broadcast functionality allowing
administrators to send notifications to all active user JupyterLab servers
simultaneously through a dedicated admin panel.
Core Features:
- Admin-only notification panel accessible at /hub/notifications
- Concurrent delivery to all active servers using asyncio with 5s timeout
- Temporary API token generation (5-minute expiry) for authentication
- Support for 6 notification types: default, info, success, warning, error, in-progress
- 140-character message limit with live character counter
- Auto-close toggle and dismiss button in notifications
- Dynamic endpoint URL construction using spawner.server.base_url
- Comprehensive error handling with user-friendly messages
- One-line logging per server with message preview and outcome
Technical Implementation:
- Created BroadcastNotificationHandler in custom_handlers.py
- Created NotificationsPageHandler for admin UI rendering
- Added notifications.html template with Bootstrap 5 form
- Registered handlers in jupyterhub_config.py extra_handlers
- Sends to /jupyterlab-notifications-extension/ingest endpoint
- Payload includes type, message, autoClose, and actions array
- Navigation link added to home.html for admin access
Integration:
- Requires jupyterlab_notifications_extension installed on JupyterLab servers
- Uses correct payload format (type field, not variant)
- Includes Dismiss action button for manual notification closure
Documentation:
- Updated .claude/CLAUDE.md with complete feature documentation
- Updated README.md Features section with notification broadcast details
- Updated .claude/JOURNAL.md with implementation summary
- Removed obsolete FEATURE_PLAN.md
Version: 3.2.0 (bumped from 3.1.2)
Implemented built-in protected group system enabling admins to grant trusted users read-write Docker socket access within their JupyterLab containers. Groups are managed through admin panel and cannot be permanently deleted.
- Add pull_policy: build to jupyterhub service
- Forces Docker Compose to use locally built image
- Prevents unnecessary pulls from Docker Hub after building
Now 'docker compose up' will use the local image built with 'make build'
- Change Docker build context from services/jupyterhub to project root
- Copy config/jupyterhub_config.py into image at /srv/jupyterhub/jupyterhub_config.py
- Users can still override with volume mount if needed
- Update all COPY paths in Dockerfile to reflect new build context
- Enables container to work out-of-the-box without external config file
Benefits:
- Image is self-contained and ready to run without dependencies
- Volume mount remains optional for custom configurations
- Default config includes GPU auto-detection and self-service features
- Add /srv/jupyterhub to sys.path before importing custom_handlers
- Separate shell scripts and Python files in Dockerfile COPY commands
- Resolves ModuleNotFoundError for custom_handlers module
- JupyterHub now starts successfully with custom API handlers
UI Enhancements:
- Add Font Awesome icons to all control buttons (stop, start, restart, manage volumes)
- Auto-refresh page after server stop with smooth UI transitions
- Hide/show appropriate buttons based on server state (Restart vs Manage Volumes)
- Re-inject icons removed by JupyterHub's DOM manipulation
Technical Implementation:
- MutationObserver watches for JupyterHub DOM changes after stop
- Immediate UI state correction before page refresh
- Comprehensive console logging for debugging
CI/CD:
- Add GitHub Actions workflow for Dockerfile validation with hadolint
- Triggers on push to main, version tags, and pull requests
- Uses hadolint to ensure Dockerfile best practices
Documentation enhancements:
- Add comprehensive Features section highlighting key capabilities
- Document GPU auto-detection, user self-service, isolated environments
- Include production-ready features (Traefik, TLS, Watchtower)
- Add Self-Service Volume Management subsection with visual examples
- Include three screenshots demonstrating UI features:
- Restart Server button (active state)
- Manage Volumes button (stopped state)
- Volume selection modal (checkbox interface)
- Position screenshots prominently after feature list
- Provide one-sentence descriptions for each screenshot
Technical updates:
- Increase Stop Server refresh delay to 3 seconds for stability
- Update version to 3.0.14
Screenshots stored in .resources/ directory for future reference
- Add console.log statements to track button clicks and API calls
- Log username, base URL, and button existence on page load
- Log success/error responses from API calls
- Help diagnose why restart server button does nothing
- Add .claude/CLAUDE.md with comprehensive architecture documentation
- Add .claude/JOURNAL.md for tracking substantive work
- Add FEATURE_PLAN.md for Reset Home Volume and Restart Server features
- Add project.env with version tracking (1.0.0_jh-4.x)
- Update Makefile with increment_version and tag targets
- Implement auto-versioning on build and dual-tag push workflow