SplashPreloader is a JavaFX Preloader, registered by GuiBootstrap through javafx.preloader, so it only exists on the --ui path and shows as soon as the toolkit is up, before the Spring context is built. It displays the splash image with the application name, the build version read from META-INF/build-info.properties, a status line and a progress bar, and fades out once the main window is actually on screen. StartupProgressReporter, a BeanPostProcessor added to the context before it refreshes, turns the context's construction into real progress (beans initialised over bean definitions) and status lines following the measured phases: opening the library, loading components, preparing the interface. The template's placeholder custom.property is dropped from build-info. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011xpLSeYKKHX6o16jzYLgZv
Pholio
Pholio is a desktop application for managing large photo and video libraries, built for volume and speed.
- Libraries — point Pholio at one or more folders; it indexes every photo and video into its own embedded database, one per library, and keeps it in sync as files change.
- Gallery — a justified, date-grouped grid that stays fluid on tens of thousands of files, with a full-screen photo view and an info panel for the selected file.
- Metadata — reads EXIF, IPTC and XMP (RAW, HEIF and video included), edits capture date, location and rating, and writes them back to the file itself.
- Places — offline reverse geocoding from a bundled GeoNames dataset, plus optional online place search (LocationIQ).
- People — local face and animal detection and clustering (ONNX Runtime, nothing leaves the machine); naming a person makes their photos searchable.
- Search — free text, rating (
r:4+), people (p:Alice) and folder (path:Holidays/2024) filters, combined freely — see the in-app guide (the?next to the search bar) orsrc/main/resources/userguide. - Command line — the same binary runs headless:
pholio scan <dir>reports the media files a folder holds.
Built with Java 26, JavaFX (AtlantaFX, GemsFX, Ikonli), Spring Boot, H2, PicoCLI and metadata-extractor.
Build and run
Requirements: a JDK 26 that bundles JavaFX (e.g. Azul Zulu FX 26). Maven comes with the wrapper.
./mvnw verify # compile, test, build target/pholio.jar
java -jar target/pholio.jar --ui # desktop interface
java -jar target/pholio.jar scan ~/Pictures [-R] # headless scan; -R: do not recurse
java -jar target/pholio.jar -V # version
java -jar target/pholio.jar # usage, same as --help
Pholio runs headless by default: only --ui opens the window, so every launcher meant to show one (IDE run
configuration, installers) passes it. Any argument Pholio does not recognise is read as a command.
Development
JVM options (-D…)
| Option | Default | Effect |
|---|---|---|
--enable-native-access=javafx.graphics,ALL-UNNAMED |
— | Not a property, but recommended: silences the restricted-method warnings from JavaFX, JNA and the macOS process naming. |
-Dpholio.home=<dir> |
OS user dirs | Puts configuration, data (libraries) and cache under one root — keeps a test run out of your real profile. |
-Dpholio.skipTheme=true |
false |
Starts without the AtlantaFX theme, on JavaFX's default styling (to tell a theme issue from a layout one). |
-Dpholio.modalBackend=dialogPane |
stage |
Shows dialogs in GemsFX's embedded DialogPane instead of a separate window. |
-Djavafx.enablePreview=true |
set by the app | Required for the JavaFX HeaderBar preview API; GuiBootstrap sets it unless you pass a value. |
-Dprism.dirtyopts=false |
set by the app | Works around a stale-paint bug in Prism; GuiBootstrap sets it unless you pass a value. |
Application settings (--pholio.…= arguments)
Spring Boot settings from application.yaml, overridable on the command line (they bypass PicoCLI, so they
never read as a command):
| Setting | Default | Effect |
|---|---|---|
--pholio.dev-tools.enabled= |
true |
F12 opens the DevToolsFX scene-graph inspector. |
--pholio.library.routing.enabled= |
true |
Routes the database to the library picked in the header; false pins spring.datasource.url. |
--pholio.pools.cpu= |
0 |
Threads for decoding work (thumbnails, hashes); 0 = cores − 1. |
--pholio.pools.scheduler= |
2 |
Scheduler threads. |
--pholio.window.default-width= / default-height= |
1440 / 900 |
First-run window size. |
--logging.level.org.icroco.pholio= |
DEBUG |
Log level of Pholio's own code. |
What makes the jar big
target/pholio.jar is ~223 MB, 89 libraries. Almost all of it is recognition: the application's own code is
under 1 MB.
| Size (in the jar) | Entry | Why |
|---|---|---|
| 130.5 MB | onnxruntime-1.21.1.jar |
ONNX Runtime with native libraries for 5 platforms (~590 MB unpacked, win-x64 alone 351 MB). The installers keep only their own platform's — see below. |
| 34.2 MB | models/recognition/face_recognition_sface_2021dec.onnx |
Face embedding model (SFace). |
| 10.2 MB | geodata/cities1000.txt.gz |
GeoNames seed for offline reverse geocoding, imported into H2 on first run. |
| 4.4 MB | byte-buddy |
Runtime agent behind @FxThread. |
| 3.2 MB | models/recognition/yolox_nano.onnx |
Animal detection model. |
| 3.0 MB | gemsfx |
UI controls. |
| 2.6 MB | h2 |
Embedded database. |
| ≤ 2 MB each | Spring, Jackson, JNA, AtlantaFX themes, … | The remaining ~30 MB. |
Deliberately left out of the jar (pom.xml): Lombok and Jilt (compile-time only), the OpenJFX jars (every
target runtime already has JavaFX as modules), and the JUnit/AssertJ that devtoolsfx wrongly declares at
compile scope.
The native installers go further (distrib/packaging/common.sh): only the target platform's ONNX Runtime
natives (130 MB → ~24 MB for macOS arm64) and a jlink'ed runtime (~64 MB) — the macOS arm64 .dmg is ~157 MB.
To re-measure: unzip -v target/pholio.jar | sort -k3 -n -r | head -20 (third column: compressed size).
Credits
src/main/resources/userguide/credits.md is the single list of credits — shipped libraries with their
licenses, recognition models, map and place data. The application shows it from the ? in Settings
(CreditsView), and each release copies it to distrib/CREDITS.md. Add a library or data source there when
you add one to the application.
Useful scripts
python3 tools/icons/make-macos-icon.py— regenerates the macOS icon,icon.pngandpholio.icnsfromsrc/main/resources/images/spo-1024x1024.png.python3 tools/demo/fetch-commons-photos.py <dir> [--quality] [--places Paris Kyoto …] [--per-place N]— downloads a demo library for screenshots from Wikimedia Commons: freely licensed JPEG originals whose own EXIF has a capture date and GPS, one folder per city, with aCREDITS.md(CC BY / BY-SA require the credit wherever the photos are shown).--qualitykeeps only Commons' Quality/Featured pictures — nicer, fewer, slower.--helpfor every option.
Release
./mvnw -Prelease validate
Needs a clean working tree (or -Drelease.allowDirty=true) and a logged-in GitHub CLI (gh auth login).
In order, it:
- bumps the version to
YYYY.M.N— same month as the current version:N + 1, otherwise build 0 of the current month; - runs a fresh
./mvnw verify; - writes
distrib/release_note/release-note-<version>.mdfrom the Conventional Commits since the previous release (grouped by type, then scope); - creates GitHub release
v<version>in Imag-In/Pholio with the jar, its SHA-256 and the release note; - commits
pom.xmland tagsv<version>locally; - commits the release note in
distrib/and pushes it.
The source repository itself is never pushed to GitHub: Imag-In/Pholio only receives release assets and
the distrib/ worktree (an orphan branch), and a local pre-push hook enforces it. See AGENTS.md for the
details, and keep commit messages in the Conventional Commits format so they reach the release note.