Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
name: Deploy GitHub Pages

# Publishes the MkDocs site plus the browser QuantUI Viewer (Voici + Pyodide,
# M-VIEWER) at <site>/viewer/app/; <site>/viewer/ is its docs page
# (docs/viewer.md). The viewer is built from the checked-out commit: on a
# release that is the release tag, so the hosted viewer matches the
# installers attached to that release.

on:
push:
branches: [main]
Expand All @@ -8,7 +14,10 @@ on:
- "mkdocs.yml"
- "requirements-docs.txt"
- "CHANGELOG.md"
- "packaging/viewer/**"
- ".github/workflows/pages.yml"
release:
types: [published]
workflow_dispatch:

permissions:
Expand Down Expand Up @@ -41,6 +50,21 @@ jobs:
- name: Build documentation
run: mkdocs build --strict

# Own venv: the viewer build pulls in QuantUI, PySCF and Voici, which
# must not mix with the docs toolchain above.
- name: Build the browser viewer into site/viewer/app/
run: |
python -m venv "$RUNNER_TEMP/viewer-env"
source "$RUNNER_TEMP/viewer-env/bin/activate"
python -m pip install --upgrade pip build
python -m build --wheel --outdir "$RUNNER_TEMP/dist"
pip install ".[pyscf,ase]"
python packaging/viewer/browser/make_samples.py "$RUNNER_TEMP/samples"
packaging/viewer/browser/build.sh "$RUNNER_TEMP"/dist/quantui-*.whl \
"$RUNNER_TEMP/samples" site/viewer/app
test -f site/viewer/app/voici/render/viewer.html
test -f site/viewer/index.html # the docs page survived

- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v5
with:
Expand Down
164 changes: 164 additions & 0 deletions .github/workflows/viewer-builds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
name: Viewer builds

# Lightweight QuantUI Viewer (History + Analysis only, no quantum engine) in
# its two delivery forms — see packaging/viewer/README.md:
#
# installer conda-constructor installers (Windows .exe, macOS .pkg, Linux
# .sh), UNSIGNED, each silently installed and smoke-tested.
# browser static Voici + Pyodide site (runs entirely in the browser).
#
# Runs only when the viewer packaging changes, on demand, or when a GitHub
# Release is published — never on the normal PR path, so it cannot slow or
# break regular CI. On a release, the three installers are attached to it
# (the browser build is published by pages.yml instead).

on:
push:
paths:
- "packaging/viewer/**"
- ".github/workflows/viewer-builds.yml"
release:
types: [published]
workflow_dispatch: {}

permissions:
contents: read

jobs:
wheel:
name: Build QuantUI wheel
runs-on: ubuntu-latest
outputs:
version: ${{ steps.ver.outputs.version }}
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.11"
- run: python -m pip install --upgrade pip build
- run: python -m build --wheel
- id: ver
run: |
v=$(ls dist/quantui-*.whl | sed -E 's/.*quantui-([^-]+)-.*/\1/')
echo "version=$v" >> "$GITHUB_OUTPUT"
- uses: actions/upload-artifact@v7
with:
name: wheel
path: dist/*.whl
if-no-files-found: error

installer:
name: Installer (${{ matrix.os }})
needs: wheel
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-14]
defaults:
run:
shell: bash -el {0}
env:
QUANTUI_VERSION: ${{ needs.wheel.outputs.version }}
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
with:
name: wheel
path: packaging/viewer/installer
- uses: conda-incubator/setup-miniconda@v3
with:
miniforge-version: latest
activate-environment: build
python-version: "3.11"
- name: Install constructor
run: conda install -y -c conda-forge constructor
- name: Build installer
run: |
cp LICENSE packaging/viewer/installer/
constructor packaging/viewer/installer --output-dir out
ls -la out

- name: Smoke test (Linux)
if: runner.os == 'Linux'
run: |
bash out/*.sh -b -p "$RUNNER_TEMP/qv"
"$RUNNER_TEMP/qv/bin/quantui" view --help
"$RUNNER_TEMP/qv/bin/python" -c "from quantui.app import QuantUIApp; QuantUIApp(viewer=True); print('viewer ok')"
test -f "$HOME/.local/share/applications/quantui-viewer.desktop"
- name: Smoke test (macOS)
if: runner.os == 'macOS'
run: |
installer -pkg out/*.pkg -target CurrentUserHomeDirectory
q=$(find "$HOME" -maxdepth 4 -path "*/bin/quantui" -type f | head -1)
echo "installed at: $q"
"$q" view --help
"$(dirname "$q")/python" -c "from quantui.app import QuantUIApp; QuantUIApp(viewer=True); print('viewer ok')"
test -x "$HOME/Applications/QuantUI Viewer.app/Contents/MacOS/QuantUI Viewer"
- name: Smoke test (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$exe = (Get-ChildItem out\*.exe)[0].FullName
Start-Process -Wait -FilePath $exe -ArgumentList '/S', '/InstallationType=JustMe', '/D=C:\qv'
& C:\qv\Scripts\quantui.exe view --help
& C:\qv\python.exe -c "from quantui.app import QuantUIApp; QuantUIApp(viewer=True); print('viewer ok')"
if ($LASTEXITCODE -ne 0) { exit 1 }
Get-Content C:\qv\post_install.log -ErrorAction SilentlyContinue
if (-not (Test-Path ([Environment]::GetFolderPath('Programs') + '\QuantUI Viewer.lnk'))) { throw 'Start-menu shortcut missing' }

- uses: actions/upload-artifact@v7
with:
name: installer-${{ runner.os }}
path: out/QuantUI-Viewer-*
if-no-files-found: error

browser:
name: Browser build (Voici + Pyodide)
# On a release pages.yml builds and publishes it; no need to twice.
if: github.event_name != 'release'
needs: wheel
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.11"
- uses: actions/download-artifact@v8
with:
name: wheel
path: dist
- name: Generate demo results (needs PySCF)
run: |
python -m pip install --upgrade pip
pip install -e ".[pyscf,ase]"
python packaging/viewer/browser/make_samples.py samples
- name: Build static site
run: packaging/viewer/browser/build.sh dist/quantui-*.whl samples site
- uses: actions/upload-artifact@v7
with:
name: browser-site
path: site
if-no-files-found: error

attach:
name: Attach installers to the release
if: github.event_name == 'release'
needs: installer
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v8
with:
pattern: installer-*
path: installers
merge-multiple: true
- name: Upload to ${{ github.event.release.tag_name }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.event.release.tag_name }}
run: |
ls -la installers
gh release upload "$TAG" installers/QuantUI-Viewer-* \
--repo "$GITHUB_REPOSITORY" --clobber
6 changes: 4 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ repos:
exclude: "notebooks/" # notebooks manage their own line endings
- id: check-yaml
# mkdocs.yml uses Material's !!python/name: tags for emoji config;
# the stock YAML parser rejects those without --unsafe.
exclude: ^mkdocs\.yml$
# the stock YAML parser rejects those without --unsafe. construct.yaml
# is a conda-constructor template (jinja + per-OS "# [win]" selector
# lines that repeat keys), not plain YAML.
exclude: ^(mkdocs\.yml|packaging/viewer/installer/construct\.yaml)$
- id: check-json
exclude: "notebooks/" # notebook JSON is managed by Jupyter
- id: check-merge-conflict
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht

## [Unreleased]

### Added

- **Viewer mode (`quantui view [FOLDER]`)** — a lightweight QuantUI with only
the History and Analysis tabs, pointed at a results folder, needing no quantum
engine. `QuantUIApp(viewer=True, results_dir=...)` adds a results-folder bar
above the tabs; `quantui view` starts Voilà on a free `127.0.0.1` port and
opens the browser. Packaging for two delivery routes lives in
`packaging/viewer/` (unsigned conda-constructor desktop installers and a
Voici/Pyodide browser build), built by the new `viewer-builds` workflow.
- **QuantUI Viewer in the docs** — new *QuantUI Viewer* page
(`/viewer/`) with a link to the browser Viewer, which the Pages workflow now
builds and publishes at `/viewer/app/` on each release and docs change.
Publishing a release also attaches the three Viewer installers to it.

### Fixed

- History → "View Results" / "View Analysis" navigated by fixed tab index, so
with the Cluster Jobs tab visible they landed one tab early. They now look
the tab up by name.
- Background renders (vibrational animation, isosurface, export) and the
activity-light timer fall back to running inline when threads are
unavailable instead of leaving the panel stuck.

## [0.10.0] - 2026-10-03

### Added
Expand Down
57 changes: 57 additions & 0 deletions docs/viewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# QuantUI Viewer

The Viewer is a lightweight QuantUI for looking at results you already have.
It has only the **History** and **Analysis** tabs: energies, orbital diagrams,
IR / Raman / UV-Vis spectra, optimization trajectories, vibrational modes and
populations. It cannot run calculations.

There are two ways to use it. Neither needs git or a terminal.

## In your browser (nothing to install)

**[Open the QuantUI Viewer](https://the-schultz-lab.github.io/QuantUI/viewer/app/voici/render/viewer.html){ .md-button .md-button--primary }**

1. Wait for the page to load. The first visit downloads Python into the
browser and can take a minute; later visits are faster.
2. It opens on a small set of demo results (water). To look at your own,
zip your results folder (right-click it → *Compress* / *Send to →
Compressed (zipped) folder*) and click **Upload .zip**.
3. Pick a calculation in the **History** tab, then **→ View Analysis**.

Your files never leave your computer: the zip is unpacked inside the browser
tab and is gone when you close it. Use a recent Chrome, Edge, Firefox or
Safari.

## Desktop app (works offline)

Download the installer for your computer from the
[QuantUI releases page](https://github.com/The-Schultz-Lab/QuantUI/releases)
(under *Assets* of the latest release):

| Computer | File |
| --- | --- |
| Windows | `QuantUI-Viewer-<version>-Windows-x86_64.exe` |
| Mac (Apple silicon) | `QuantUI-Viewer-<version>-MacOSX-arm64.pkg` |
| Linux | `QuantUI-Viewer-<version>-Linux-x86_64.sh` |

The installers are **not code-signed**, so your computer warns you the first
time:

- **Windows:** "Windows protected your PC" → click **More info**, then
**Run anyway**. Choose *Just Me* when asked (no admin rights needed).
- **Mac:** the installer is blocked the first time you open it. Open
**System Settings → Privacy & Security**, scroll down to the message about
the QuantUI installer, click **Open Anyway** and enter your password.
- **Linux:** run `bash QuantUI-Viewer-*.sh` in a terminal.

Then start **QuantUI Viewer** from the Start menu / Desktop (Windows), the
Applications folder in your home folder (Mac), or your applications menu
(Linux). Your browser opens on the Viewer: type the path of your results
folder into **Results folder** and click **Open**. Click **Exit** when you are
done.

## Not available yet

- **Orbital isosurfaces, density and ESP surfaces** need PySCF to compute,
which the Viewer does not include. Use the full QuantUI for those.
- The browser Viewer shows molecules with py3Dmol only.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ nav:
- Getting Started:
- Installation: installation.md
- Platform Support: platforms.md
- QuantUI Viewer: viewer.md
- Tutorials: tutorials.md
- User Guide:
- Features: features.md
Expand Down
Loading
Loading