From 8ff2abf3aa93c38d4145102c35e56158df1f0ddf Mon Sep 17 00:00:00 2001
From: Filip Leonarski
Date: Sat, 24 Oct 2026 22:01:12 +0200
Subject: [PATCH] docs: a standalone front page with the three programs and the
downloads, the Sphinx tree one page below it
docs/landing/ is a self-contained page (HTML, CSS, a little JS, no framework): a hero, a card per
program, the download section with the archives of the newest release and the reader's own
platform marked, the licence in one paragraph, light and dark. The jfjoch_downloads extension
renders it into the HTML output root as index.html at the end of every Sphinx build, so it is
served wherever the documentation is - Read the Docs, the gitea-pages branch and the broker's
frontend bundle - and its download buttons are the same ones as on the Sphinx download pages,
built from the configured release and repointed at the newest published one by the shared script.
The Sphinx root page moves to documentation.html (root_doc), and the frontend's documentation
frame opens that page.
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
(cherry picked from commit 64cde61f0b941b3e8c99eaa9b74afeaa75aefc78)
---
docs/_ext/jfjoch_downloads.py | 27 +-
docs/conf.py | 4 +
docs/{index.rst => documentation.rst} | 11 +-
docs/landing/index.html | 149 +++++++++++
docs/landing/landing.css | 369 ++++++++++++++++++++++++++
docs/landing/landing.js | 60 +++++
frontend/src/App.tsx | 2 +-
7 files changed, 615 insertions(+), 7 deletions(-)
rename docs/{index.rst => documentation.rst} (92%)
create mode 100644 docs/landing/index.html
create mode 100644 docs/landing/landing.css
create mode 100644 docs/landing/landing.js
diff --git a/docs/_ext/jfjoch_downloads.py b/docs/_ext/jfjoch_downloads.py
index 0fe07e327..f93438361 100644
--- a/docs/_ext/jfjoch_downloads.py
+++ b/docs/_ext/jfjoch_downloads.py
@@ -12,11 +12,18 @@ script matches against the release's asset list, written loosely enough to survi
bump.
"""
+import pathlib
+import shutil
+
from docutils import nodes
from docutils.parsers.rst import Directive
RELEASES = "https://gitea.psi.ch/mx/jungfraujoch/releases"
+# docs/landing/: the front page, rendered from its template into the output root as index.html at
+# the end of the build (write_landing below), with the same download blocks as the Sphinx pages.
+LANDING_FILES = ("landing.css", "landing.js")
+
# program -> [(platform, requirements, [(label, asset name with {v}, regex for the live lookup)])]
# The first button of a platform is the recommended one and is drawn filled.
PROGRAMS = {
@@ -69,7 +76,8 @@ def render(program, version):
' · all releases
' % (version, RELEASES, version, RELEASES),
'
']
for platform, requirements, archives in PROGRAMS[program]:
- out.append('
%s
' % platform)
+ out.append('
%s
'
+ % (platform.lower(), platform))
for i, (label, pattern, regex) in enumerate(archives):
name = pattern.format(v=version)
cls = "jfj-dl__btn" if i == 0 else "jfj-dl__btn jfj-dl__btn--secondary"
@@ -93,6 +101,23 @@ class JfjochDownloads(Directive):
return [nodes.raw("", render(program, version), format="html")]
+def write_landing(app, exception):
+ """Render docs/landing/index.html into the HTML output root, next to the Sphinx pages."""
+ if exception is not None or app.builder.name != "html":
+ return
+ src = pathlib.Path(app.confdir) / "landing"
+ out = pathlib.Path(app.outdir)
+ version = app.config.release
+ html = (src / "index.html").read_text(encoding="utf-8")
+ html = (html.replace("{{release}}", version)
+ .replace("{{downloads:rugnux}}", render("rugnux", version))
+ .replace("{{downloads:viewer}}", render("viewer", version)))
+ (out / "index.html").write_text(html, encoding="utf-8")
+ for name in LANDING_FILES:
+ shutil.copy(src / name, out / name)
+
+
def setup(app):
app.add_directive("jfjoch-downloads", JfjochDownloads)
+ app.connect("build-finished", write_landing)
return {"parallel_read_safe": True, "parallel_write_safe": True}
diff --git a/docs/conf.py b/docs/conf.py
index 9284e684d..393d3a17b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -26,6 +26,10 @@ extensions = [
'jfjoch_downloads',
]
+# The site's front page is docs/landing/index.html, a standalone page the jfjoch_downloads
+# extension renders into the output root as index.html; the Sphinx tree starts one page below it.
+root_doc = 'documentation'
+
templates_path = ['_templates']
# docs/review/ is gitignored working material (review reports, work plans); Sphinx renders
# whatever is on disk, so without this a local review file would become a published page.
diff --git a/docs/index.rst b/docs/documentation.rst
similarity index 92%
rename from docs/index.rst
rename to docs/documentation.rst
index 9e177b386..0cdd8c704 100644
--- a/docs/index.rst
+++ b/docs/documentation.rst
@@ -1,11 +1,12 @@
-PSI Jungfraujoch
-================
+Documentation
+=============
.. raw:: html
-
Open-source software from the Paul Scherrer
- Institute for X-ray diffraction data, from the detector to the merged reflections. Three
- programs, each usable on its own.
+
The manuals and reference of Jungfraujoch and Rugnux, open-source software
+ from the Paul Scherrer Institute for X-ray diffraction data.
+ The front page has the overview and the downloads; this page is the
+ map of the documentation.
diff --git a/docs/landing/index.html b/docs/landing/index.html
new file mode 100644
index 000000000..31e9016f4
--- /dev/null
+++ b/docs/landing/index.html
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+Jungfraujoch and Rugnux: X-ray diffraction data, from the detector to the merged reflections
+
+
+
+
+
+
+
+
+ Jungfraujoch
+
+
+
+
+
+
+
+
+
+
Paul Scherrer Institute · open source
+
From the detector to the merged reflections.
+
Software for X-ray diffraction data: Rugnux processes a stored
+ dataset with one command, the Viewer shows what is in it, and
+ Jungfraujoch acquires it from the detector at full speed.
rugnux <diffraction image file>is the whole command: cell, space group and resolution come out of the data.
+
+
+
+
+
+
+
+
Data processing
+
Rugnux
+
Takes a macromolecular diffraction dataset, a rotation sweep or serial stills, from the
+ images to merged reflections: spot finding, indexing, integration, scaling and merging, with
+ the space group, cell and resolution decided from the data and a report that says on what
+ evidence. Writes .mtz, .cif and .hkl for the programs
+ that come next.
+
Linux · macOS · Windows · command line · fast on an NVIDIA GPU, works without one
Shows what is in a dataset: every image with its spots, predictions and resolution rings,
+ per-image statistics over the sweep, grid-scan maps, and the same processing pipeline as
+ Rugnux, run from a settings panel on the open file. Follows a live collection from a running
+ Jungfraujoch broker.
The acquisition and real-time analysis system for the PSI JUNGFRAU and EIGER detectors,
+ and for DECTRIS detectors through their control unit: an FPGA and GPU pipeline that takes
+ the detector's frames at full rate, analyses them on the fly, streams them to the NXmx HDF5
+ writer and serves a web interface and REST API to the beamline.
Pre-built, signed where the platform asks for it, nothing to install beside them.
+
+
+
+
+
Rugnux
+
One self-contained executable. Unpack the archive into a directory of its own and run
+ bin/rugnux; no CUDA toolkit, no Qt, no service. On a machine with an NVIDIA GPU
+ take the GPU build, which also runs without one. Details, packages and building from source.
+ {{downloads:rugnux}}
+
+
+
+
Jungfraujoch Viewer
+
A desktop application with the Qt runtime included: a portable archive on Linux, a
+ notarized disk image on macOS, an installer on Windows. Details and building from source.
+ {{downloads:viewer}}
+
+
+
+
Jungfraujoch, the acquisition system
+
Installed on the beamline's Linux servers from the RPM and APT
+ repositories (jfjoch, jfjoch-writer, jfjoch-driver-dkms,
+ jfjoch-viewer, rugnux), with the FPGA firmware and the writer's
+ packages attached to every release.
+ Deployment is the step-by-step guide; Release contents says what each package needs on the machine.
+
+
+
+
+
Free to use, in academia and industry
+
Rugnux, the viewer and the Jungfraujoch services are free software under the
+ GNU General Public License v3; the FPGA design is released under the
+ CERN Open Hardware Licence v2, strongly reciprocal. Both let
+ anyone use, study and modify the software and the hardware design at no charge, commercial use
+ included; what they ask is that a modified version which is passed on is shared under the same
+ terms. The released binaries bundle third-party components under GPL-compatible licences, and the
+ CUDA builds the NVIDIA CUDA runtime under NVIDIA's EULA: see the
+ third-party notices.