Quick Answer: An AI pose reference gallery is a browsable library of posed figure images that artists use as reference. The anhao/ai-pose-gallery-zh project is a zero-dependency static site: one index.html reads JSON, serves local thumbnails and full-size PNGs, and deploys to Cloudflare Pages through a build script. Deploy a filtered dist/ folder rather than the repo root, and check image rights before you reuse anything.

Most pose libraries online are a search box sitting in front of someone else's server. The anhao/ai-pose-gallery-zh repository takes a different route. It's a Chinese localization of a Japanese original, and it ships 1,439 records, 2,878 image files, and 659.5 MB of assets as plain files. Here's how it's organized, why a static approach suits it, and where the deployment usually goes wrong.

What the repository actually ships

Two JSON files matter most. data/pose.json keeps the original Japanese records untouched, and data/pose-zh.json is what the front end actually reads. Each record has an id such as full_sexy_P001_front, a system (体系), a category (分类), a pose name, an angle, and paths to a thumbnail and an original. A pre-joined search field (检索) lets the browser run fuzzy matching without a backend.

The README contradicts itself here. The header says 288 pose groups, but the field table describes the numbering as covering 80 groups. Those are different counts, and until you count the records yourself, don't quote either one. Gaps like this are exactly what an outdated or careless article gets wrong.

The layout is simple:

  • thumbs/: 1,439 JPG files at 300×400, about 22 MB in total
  • img/: 1,439 PNG files at 900×1200, about 637 MB in total
  • scripts/download.py: a 48-thread downloader with resume and retry
  • scripts/verify.py: checks existence, file size, and image headers across all 2,878 files
  • scripts/build.sh: copies only the publishable files into dist/

Each record maps to some subset of five camera angles: front, oblique, side, overhead, and low-angle. That structure is what makes the multi-angle thumbnail switching in the UI possible.

Why a static site beats a backend for this data

The data is read-only, and there are no user accounts. Every search is a filter over an array the browser already has. At 1,439 rows, a database adds cost and failure points without improving search. That's the counterintuitive part: the "proper" architecture is the wrong one here.

ApproachWhat it does wellHard limitFit for this data
Static site on Cloudflare PagesServes edge-cached files; custom _headers for cache policy25 MiB per file, 20,000 files per deploymentStrong fit
Node or Python app with a databaseServer-side search, accounts, analyticsA server to patch and a database to back upOverkill for read-only data
GitHub PagesFree and native to the repoNo custom response headersWorkable, but weaker cache control
Object storage with CDN (Cloudflare R2)Keeps large binaries out of Git historySeparate upload step and extra configurationStrong fit if the image set grows

One practical catch: the page loads data with fetch, so double-clicking index.html fails under CORS. For local testing, run python3 -m http.server 8000 and open http://127.0.0.1:8000. Skipping this step makes a working site look broken, and it's the first thing a new contributor hits.

The deploy mistake that breaks the build

Here's where most first deployments fail. If you point Cloudflare Pages at the repo root, the platform scans everything in it, including .git, which the README says runs to hundreds of megabytes. Any single file over the 25 MiB limit fails the build. The repo's largest file is 917 KB, so the image files aren't the problem. The culprit is the scope of the upload.

The fix is to publish only what the site needs. scripts/build.sh copies index.html, _headers, data/, thumbs/, and img/ into dist/. Then:

  1. In the Cloudflare Dashboard, go to Workers & Pages, choose Create, then Pages, then Connect to Git.
  2. Select the repository and set the production branch to main.
  3. Set the framework preset to None, the build command to bash scripts/build.sh, and the build output directory to dist.
  4. Save and deploy. The README estimates 2 to 5 minutes for the first build.

If you prefer the command line, run bash scripts/build.sh and then npx wrangler pages deploy dist --project-name ai-pose-gallery-zh using the Wrangler CLI. The repo also includes a .assetsignore file as a fallback for root deployments. Treat it as a safety net, not a substitute for a clean output directory.

Caching large images without breaking updates

The _headers file sets a one-year cache on img/ and thumbs/, which means browsers and the CDN rarely go back to origin for pictures. That's a real performance win for a gallery that loads dozens of thumbnails per screen.

It also creates a trade-off most guides skip. If you replace img/P001_front.png with a corrected file under the same name, returning visitors can keep the old version for up to a year. The fix is to version filenames when you change an image, such as P001_front_v2.png, or to add a version query string. Renaming is cleaner, because it gives you a new URL and a fresh cache entry.

Before every deploy, run python3 scripts/verify.py. It checks all 2,878 files for existence, size, and valid image headers. Catching a truncated download locally is much cheaper than discovering it from a broken thumbnail in production.

The SEO setup most galleries skip

This project does several things well. It has a single H1, descriptive alt text that includes the pose name and angle, lazy-loaded images, a robots.txt that points to a sitemap, and JSON-LD structured data using the WebSite and ImageGallery types.

The most important detail is the canonical tag. The site is reachable at both a custom domain and a pages.dev address. Without a canonical tag pointing to one domain, search engines can split ranking signals between the two copies. Google's Search Central documentation describes canonicals as a way to consolidate duplicate URLs, and that matters more here than the keyword-heavy title, which is only one tag.

If you fork the project for your own domain, you need to update the address in five places: the canonical, the og:* and twitter:* tags, the JSON-LD block, robots.txt, and sitemap.xml. Miss one and you'll reintroduce the duplicate-domain problem.

The licensing and content risks you can't skip

This section matters more than any performance tweak. The README states that the gallery includes adult-oriented pose references, and that some category names use sexual terminology. It says the content is for artistic reference, motion study, and front-end learning only, and that minors should not access it. Treat those statements as the minimum. Before you host a public copy, check your jurisdiction's rules on age-restricted content and how your hosting provider's terms apply.

Copyright is the bigger problem. The MIT license covers the scripts and index.html, but the README explicitly says it doesn't cover the images or the original data in img/, thumbs/, and data/. The images belong to the original artist, ギア. The maintainer describes the repository as an archive that asks for no rights, and offers to remove material on request.

That doesn't make the images free to reuse. Whether a given use is fair use or permitted depends on jurisdiction and purpose, and I'm not giving legal advice here. The safer path is to replace the images with your own or get written permission before you publish a mirror. If you're only studying the code, the front-end patterns are worth learning from.

Frequently Asked Questions

An AI pose reference gallery is a searchable collection of posed human figure images that artists, 3D animators, and photographers use for composition and anatomy reference. Most are browsed by pose category and camera angle. Some, like anhao/ai-pose-gallery-zh, are static sites you can host yourself, which lets you control caching, SEO, and access rules.

Connect the repository to Cloudflare Pages, set the framework preset to None, and use a build command that copies only the public files into an output folder. For this project, the command is bash scripts/build.sh and the output directory is dist. Every push to the production branch then triggers a new deployment automatically.

Why does my Cloudflare Pages build fail on a large repo?

The most common cause is deploying the repository root, which pulls in .git and any other non-site files. Cloudflare limits each file to 25 MiB and each deployment to 20,000 files. Build into a clean output directory that contains only the site assets, and the failure usually disappears.

Not automatically. An MIT license on the code doesn't extend to the images. The repository states that the artwork belongs to its original creator. Get written permission or use your own images before publishing copies, and check local rules on age-restricted content if the source includes adult-oriented material.

Clone the repository, run python3 scripts/verify.py, and deploy a test build from dist/ before you touch anything else. If the build fails, check the output directory first, because that's where most failures start. Share this with anyone who's stuck on a Cloudflare Pages build for a static site, since the fix is usually a single setting.