2026-09-27 11:25:20 -03:00
2026-10-26 17:32:24 -03:00
2026-09-27 11:32:58 -03:00
2026-10-26 17:32:24 -03:00
2026-09-27 11:18:26 -03:00
2026-09-27 11:25:20 -03:00

Image Library

A single-page, backend-free landing page that lists every image in img/, lets you full-text search by filename, and copies an image's URL to your clipboard when you click it. Built to be dropped onto an nginx server as plain static files.

index.html              the page
assets/styles.css       styling (auto light/dark)
assets/app.js           search, rendering, clipboard logic
generate-manifest.py    scans img/ -> images.json, then commits
pushAll                 regenerate + commit + push, in one command
images.json             generated manifest the page fetches
img/                    put your images here

Why a manifest?

A browser cannot list a directory on its own, and "no backend" rules out an API that would do it. So the file list is produced by a tiny build step: generate-manifest.py walks img/ and writes images.json. The page fetches that file at runtime. Everything the server does is serve static files.

Quick start

# 1. Add images (subfolders are fine)
cp ~/pictures/*.png img/

# 2. Build the manifest (and commit it)
./generate-manifest.py

# 3. Preview locally
python3 -m http.server 8080
#    -> open http://localhost:8080

Re-run step 2 whenever you add, rename, or delete images.

Publishing with pushAll

pushAll does the whole publish flow in one command: regenerate the manifest, commit the changes, and push to the remote.

./pushAll

To run it as pushAll from anywhere, either add this folder to your PATH, or create a git alias once:

git config alias.pushAll '!./pushAll'
# then:
git pushAll

generate-manifest.py options

./generate-manifest.py                 # generate + commit
./generate-manifest.py --no-commit     # generate only
./generate-manifest.py -m "Add logos"  # custom commit message

Features

  • Search — case-insensitive, multi-word with AND semantics. Every word must appear somewhere in the filename; prefix and word-boundary matches rank first. Matches are highlighted. Press / to focus the search box, Esc to clear.
  • Click to copy — clicking a card copies the image's absolute URL (e.g. https://your-host/img/logo.png). A toast confirms it.
  • Lazy loading — thumbnails load as you scroll, so large libraries stay fast.
  • No dependencies — vanilla JS/CSS, no framework, no build tooling.

Deploying on nginx

Copy the whole project (including the generated images.json) into a web root and point a server block at it. See nginx.conf.example.

# build the manifest locally, then upload everything
./generate-manifest.py --no-commit
rsync -av --delete ./ user@server:/var/www/image-library/

If you'd rather generate the manifest on the server, install Python 3 there and run the script after uploading images. Python is only needed for that step — nginx never runs it.

Clipboard over plain HTTP

navigator.clipboard only works in a secure context (HTTPS, or localhost). The app detects this and falls back to a legacy copy method, which works on plain HTTP in most browsers. For guaranteed behavior on a LAN host, serve over HTTPS (e.g. a self-signed cert or a reverse proxy) — or just use http://localhost while testing.

Alternative: nginx autoindex

If you don't want a build step at all, you can enable nginx's directory listing and have the page parse it, but that requires autoindex on, produces fragile HTML scraping, and loses the manifest metadata. The manifest approach is recommended.

S
Description
No description provided
Readme
4.6 MiB
0 Stars 1 Watchers 0 Forks
Languages
JavaScript 43.2%
CSS 27.4%
Python 21.3%
HTML 8.1%