尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A self-updating anime wallpaper archive. A scheduled job pulls from curated
sources daily, filters and re-encodes what it finds, extracts a colour
palette from each image, and commits the result. Cloudflare Pages serves the
repo as a static site — there is no server, no database, and no build step.
Images live in Cloudflare R2, not in git. The repository therefore holds
only code and a JSON manifest and stays a few megabytes no matter how long
the sync runs — which matters because deleting a file from git does not
reclaim its history, so an image-in-repo archive grows forever.檢視完整 README ↗A self-updating anime wallpaper archive. A scheduled job pulls from curated sources daily, filters and re-encodes what it finds, extracts a colour palette from each image, and commits the result. Cloudflare Pages serves the repo as a static site — there is no server, no database, and no build step.
GitHub Actions (daily cron)
└─ sync_danbooru.py fetch → filter → dedupe → WebP → palette
└─ prune.py drop oldest entries once a free-tier ceiling is hit
└─ build_site.py manifest + JSON-LD + sitemap + robots + llms.txt + OG card
└─ git push
└─ Cloudflare Pages redeploys automatically
| Path | What it is |
|---|---|
index.html | The whole site. Static gallery is injected at build time. |
assets/ | Stylesheet, runtime, favicon, generated OG card |
data/wallpapers.json | The index the frontend reads |
wallpapers/ | Processed WebP images — only in local mode; empty once storage is on R2 |
incoming/ | Local drop zone for your own uploads (git-ignored) |
scripts/ | The pipeline |
_headers, robots.txt, sitemap.xml, llms.txt | Generated — edit build_site.py, not these |
Images live in Cloudflare R2, not in git. The repository therefore holds only code and a JSON manifest and stays a few megabytes no matter how long the sync runs — which matters because deleting a file from git does not reclaim its history, so an image-in-repo archive grows forever.
Set these and the pipeline uses R2. Locally, leaving them unset falls back to
writing into wallpapers/ so the project still runs with no cloud account —
but the GitHub Actions workflow requires all five and fails its preflight
check without them, rather than silently publishing a manifest that points
at storage nothing was actually uploaded to:
R2_ACCOUNT_ID R2_ACCESS_KEY_ID R2_SECRET_ACCESS_KEY R2_BUCKET
R2_PUBLIC_BASE # public bucket URL, e.g. https://cdn.okeyamy.xyz
R2_PUBLIC_BASE also drives the img-src in the generated CSP, so the
image host can never fall out of sync with the security policy.
prune.py runs before every build and drops the oldest entries once either
ceiling is reached:
R2 bills nothing for egress, so traffic alone can never generate a charge.
Set in scripts/pipeline.py:
scripts/cropmatch.py: ORB feature matching with a geometric check). The
fingerprint index is one file in R2 (index/features.npz), not in git;
scripts/crop_index.py fills it from thumbnails before every synccull.py or prune.py is recorded in
data/removed.json and never re-fetched, from any sourcerating:general onlyDrop image files into incoming/ and run scripts/ingest_local.py. To credit
wherever an image actually came from, add a same-named .source sidecar:
incoming/nice.png
incoming/nice.png.source
https://twitter.com/artist/status/12345
artist_handle
Ganyu standing in the snow
Line 1 is the source link, line 2 is the artist/handle (optional), line 3 is a
title (optional). Both files are consumed on ingest — the sidecar is deleted
along with the source image once its contents are written into the item's
permalink/author/title fields.
The title is worth writing. It becomes the image's alt text and the name it is
indexed under, and an image with no title is deliberately left untitled rather
than named after its file — IMG-20260810-WA0002 describes nothing. Naming the
subject puts it on that character's page:
python scripts/ingest_local.py --title "Ganyu in the snow" --character Ganyu
Both flags apply to every image in the batch; a .source sidecar wins over
--title for the image it belongs to. scripts/build_site.py prints a count of
items it could not describe, so a missing title shows up at build time rather
than in a search result months later.
build_site.py writes one page per character into w/, served at
/w/<character>, for every character with at least MIN_HUB_ITEMS wallpapers
(2). Characters below the line still appear on the homepage and in the image
sitemap — they just don't get a page whose only content is a single image.
scripts/backfill_metadata.py is a one-off that repaired the titles and
character tags of items ingested before any of this existed. It has already
been run; it is kept because it is idempotent and documents what was wrong.
Static egress on Cloudflare Pages is unmetered, which matters because a wallpaper site's entire cost is bandwidth.
R2_* values as repository secrets.r2.dev domain or attach a
custom one such as cdn.okeyamy.xyz. That value is R2_PUBLIC_BASE./.wallpapers.okeyamy.xyz.robots.txt welcomes search and AI crawlers (that is the point — discovery)
while keeping generic bots out of the image directories. That is advisory
only, so the actual defence is at the edge — in the Cloudflare dashboard:
http.request.uri.path contains "/wallpapers/", e.g. 60 requests per minute
per IP, action BlockThat breaks the sequential crawl pattern used to clone a whole gallery without affecting anyone browsing normally.
Site code: MIT. The wallpapers are not covered — copyright remains with the original artists, and each item links back to its source post. Open an issue to request removal.