Update image manifest (1 images)

This commit is contained in:
oliver committed 2026-09-27 11:25:20 -03:00
1 parent d72e91d9c1
commit a28201bdf6
3 files changed
+45 -18

No files matched your search

+41 -14
View File
@@ -6,20 +6,21 @@ clipboard when you click it. Built to be dropped onto an nginx server as plain
static files. static files.
``` ```
index.html the page index.html the page
assets/styles.css styling (auto light/dark) assets/styles.css styling (auto light/dark)
assets/app.js search, rendering, clipboard logic assets/app.js search, rendering, clipboard logic
scripts/generate-manifest.mjs scans img/ -> images.json generate-manifest.py scans img/ -> images.json, then commits
images.json generated manifest the page fetches pushAll regenerate + commit + push, in one command
img/ put your images here images.json generated manifest the page fetches
img/ put your images here
``` ```
## Why a manifest? ## Why a manifest?
A browser cannot list a directory on its own, and "no backend" rules out an API 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: that would do it. So the file list is produced by a tiny build step:
`scripts/generate-manifest.mjs` walks `img/` and writes `images.json`. The page `generate-manifest.py` walks `img/` and writes `images.json`. The page fetches
fetches that file at runtime. Everything the server does is serve static files. that file at runtime. Everything the server does is serve static files.
## Quick start ## Quick start
@@ -27,8 +28,8 @@ fetches that file at runtime. Everything the server does is serve static files.
# 1. Add images (subfolders are fine) # 1. Add images (subfolders are fine)
cp ~/pictures/*.png img/ cp ~/pictures/*.png img/
# 2. Build the manifest # 2. Build the manifest (and commit it)
node scripts/generate-manifest.mjs ./generate-manifest.py
# 3. Preview locally # 3. Preview locally
python3 -m http.server 8080 python3 -m http.server 8080
@@ -37,6 +38,32 @@ python3 -m http.server 8080
Re-run step 2 whenever you add, rename, or delete images. 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.
```sh
./pushAll
```
To run it as `pushAll` from anywhere, either add this folder to your `PATH`, or
create a git alias once:
```sh
git config alias.pushAll '!./pushAll'
# then:
git pushAll
```
### `generate-manifest.py` options
```sh
./generate-manifest.py # generate + commit
./generate-manifest.py --no-commit # generate only
./generate-manifest.py -m "Add logos" # custom commit message
```
## Features ## Features
- **Search** — case-insensitive, multi-word with AND semantics. Every word must - **Search** — case-insensitive, multi-word with AND semantics. Every word must
@@ -54,13 +81,13 @@ and point a server block at it. See [`nginx.conf.example`](nginx.conf.example).
```sh ```sh
# build the manifest locally, then upload everything # build the manifest locally, then upload everything
node scripts/generate-manifest.mjs ./generate-manifest.py --no-commit
rsync -av --delete ./ user@server:/var/www/image-library/ rsync -av --delete ./ user@server:/var/www/image-library/
``` ```
If you'd rather generate the manifest on the server, install Node there and run If you'd rather generate the manifest on the server, install Python 3 there and
the script after uploading images. Node is only needed for that step — nginx run the script after uploading images. Python is only needed for that step —
never runs it. nginx never runs it.
### Clipboard over plain HTTP ### Clipboard over plain HTTP
+3 -3
View File
@@ -1,6 +1,6 @@
/* Image Library — single-page app, no backend. /* Image Library — single-page app, no backend.
* *
* Reads `images.json` (generated by scripts/generate-manifest.mjs), renders a * Reads `images.json` (generated by ./generate-manifest.py), renders a
* searchable grid, and copies an image's absolute URL to the clipboard on click. * searchable grid, and copies an image's absolute URL to the clipboard on click.
*/ */
(() => { (() => {
@@ -42,7 +42,7 @@
els.manifestInfo.textContent = ""; els.manifestInfo.textContent = "";
showEmpty( showEmpty(
"Could not load images.json", "Could not load images.json",
`Run <code>node scripts/generate-manifest.mjs</code> to build the manifest, then reload.` `Run <code>./generate-manifest.py</code> to build the manifest, then reload.`
); );
els.loading.hidden = true; els.loading.hidden = true;
return; return;
@@ -96,7 +96,7 @@
if (images.length === 0) { if (images.length === 0) {
showEmpty( showEmpty(
"No images yet", "No images yet",
`Drop files into <code>img/</code>, then run <code>node scripts/generate-manifest.mjs</code>.` `Drop files into <code>img/</code>, then run <code>./generate-manifest.py</code>.`
); );
updateCount(0, 0); updateCount(0, 0);
return; return;
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"generatedAt": "2026-09-27T14:23:41.878271Z", "generatedAt": "2026-09-27T14:25:20.447348Z",
"count": 1, "count": 1,
"images": [ "images": [
{ {