A browser slideshow for locally stored pictures.
- Shuffled order, every image shown once per cycle, then reshuffles and loops forever.
- Configurable duration — on-screen control and
?duration=URL param. - Fullscreen button (or press
f). - Optional EXIF "date taken" overlay (toggle in the bar, or
?exif=1).
No dependencies. Requires Node 18+.
Serves a folder from disk and reads EXIF dates server-side:
node server.js /path/to/photos
# custom port:
node server.js /path/to/photos --port 9000
# branding logo overlay (auto-loads, no re-picking):
node server.js /path/to/photos --logo /path/to/logo.pngOpen the printed URL (default http://localhost:8080). Subfolders are scanned recursively.
Start the server with no folder (or open the page however you serve it), then click 📁 Pick folder and choose a directory. Files are read in-browser and EXIF dates are parsed client-side.
node server.js # then click "Pick folder" in the pageslideshow.html is fully self-contained (inline CSS, JS, and EXIF parser).
Double-click it — or open via file:// — and click 📁 Pick folder. No server,
no install. Same controls and date options as the served version; file-picker only.
| Action | Control | Key |
|---|---|---|
| Next / Previous | ⏭ / ⏮ | → / ← |
| Play / Pause | ⏸ / ▶ | space |
| Fullscreen | ⛶ | f |
| Duration (sec) | number field | — |
| Show date taken | checkbox | — |
When the date-taken overlay is on, the bar exposes:
- Format —
DD.MM.YYYY,DD/MM/YYYY,MM/DD/YYYY,YYYY-MM-DD,D. MMMM YYYY,MMMM D, YYYY,DD MMM YYYY. Tokens:YYYY/YY,MMMM/MMM/MM/M,DD/D. - Position — Bottom center / Bottom left / Bottom right.
- Font — System / Serif / Sans / Mono.
- Size — in
rem. - 📅 icon — show or omit the calendar symbol.
Two independent, optional toggles control how photos whose aspect ratio differs from the screen are handled. Decided per image:
- Fill landscape — zoom to cover the screen (center-crop, never stretched), but only for landscape photos that won't be enlarged past 100%. Portrait and too-small photos are never cropped/upscaled.
- Blur background — for any photo still showing bars (portraits, landscapes that weren't filled, small photos), fill the bars with a scaled, blurred copy of the photo instead of black. No cropping.
If both are on, Fill wins for qualifying landscapes (they cover the screen, so there are no bars to blur); everything else gets the blurred background. With both off, photos show black bars. Re-evaluated on each image and on window resize.
URL params: ?fill=1, ?blur=1 (combine freely).
Your control choices (duration, overlays, Fill/Blur, date format/font/size/position,
logo position/size/opacity) are saved to the browser's localStorage and restored next
time. A URL parameter overrides the saved value for that run. Note: some browsers
disable localStorage on file://, so persistence is most reliable in server mode (or
any http(s):// origin).
Click 🖼 Logo to overlay a PNG (or any image) on every slide — handy for branding.
Adjust Corner (top/bottom × left/right), Logo size (% of screen width), and
Logo opacity (blend a B/W logo as a subtle watermark). In server mode, pass
--logo /path/to/logo.png so it loads automatically without re-picking each run.
URL params: ?logocorner=top-left, ?logosize=8, ?logoopacity=100.
?duration=8— seconds per slide.?exif=1— start with the date-taken overlay on.?name=1— start with the file-name overlay on (handy for spotting photos missing EXIF).?fill=1— zoom landscape photos to fill the screen (see below).?blur=1— fill bars with a blurred copy of the photo (see below).?datefmt=DD.MM.YYYY— date format (any token pattern; custom values accepted).?datefont=serif— overlay font family (e.g.serif,monospace, or a full stack).?datesize=2— overlay font size inrem.?dateicon=0— omit the 📅 calendar symbol.?datepos=bottom-right— overlay position (bottom-center,bottom-left,bottom-right).
Example: http://localhost:8080/?duration=8&exif=1&datefmt=DD.MM.YYYY&datesize=2&dateicon=0
The date taken is read from JPEG EXIF (DateTimeOriginal, falling back to
CreateDate, then DateTime). Non-JPEG formats and JPEGs without that tag show
"date unknown". The parser is dependency-free (public/exif.js) and shared by both
the server and the browser.