Spaces:
Running
Running
| title: img2threejs | |
| emoji: 🧊 | |
| colorFrom: indigo | |
| colorTo: gray | |
| sdk: docker | |
| app_port: 7860 | |
| pinned: false | |
| license: mit | |
| short_description: Image to procedural Three.js with community gallery | |
| tags: | |
| - threejs | |
| - image-to-3d | |
| - procedural-generation | |
| - code-generation | |
| - llm | |
| startup_duration_timeout: 30m | |
| # img2threejs — image to procedural Three.js | |
| Upload one object reference image. A vision-capable LLM authors an | |
| `ObjectSculptSpec`; deterministic validators enforce the upstream structural | |
| and strict-quality rules; and the vendored generator emits a TypeScript | |
| `THREE.Group` factory. The result renders in a sandboxed browser viewer and is | |
| downloadable as the original spec, TypeScript, an ESM bundle, and standalone | |
| HTML. Successful results are shared to the public community gallery by | |
| default; the clearly labelled upload-page toggle lets each user keep a result | |
| out of the gallery before generation begins. | |
| This Docker Space adapts [hoainho/img2threejs](https://github.com/hoainho/img2threejs) | |
| (MIT), synced to v1.3.0 commit | |
| `2c78038d315ec93086ef308c17ad2f1cd4cca683`. It is reconstruction-by-code, | |
| not photogrammetry, mesh extraction, or a downloaded asset pack. | |
| ## What the hosted workflow guarantees | |
| ```text | |
| image ──▶ byte/type/decompression guard + deterministic probe | |
| ──▶ vision LLM authors schema-2.1 ObjectSculptSpec | |
| ──▶ strict validator (errors return to the LLM, up to 3 repair rounds) | |
| ──▶ original spec saved locked and unreviewed | |
| ──▶ separate hosted-preview compile manifest (all supported parts) | |
| ──▶ vendored generator + esbuild ──▶ sandboxed viewer/downloads | |
| ──▶ optional persistent community publication (default on) | |
| ``` | |
| The hosted preview does **not** fabricate upstream review evidence. The | |
| downloaded `spec.json` retains an empty `reviewHistory` and its original locked | |
| pass order. A separate compile copy marks itself | |
| `hosted-unreviewed-preview` and combines the declared components into one | |
| preview pass. It contains no screenshot comparison, AI-vision score, reviewer, | |
| or `continue` decision. | |
| The result is an approximate, stylized procedural reconstruction from a single | |
| image. Hidden sides are inferred rather than observed or measured. Structural | |
| strict validation is not visual approval; production approval requires running | |
| the upstream pass-by-pass render, comparison, and review loop outside this | |
| hosted preview. Unsupported geometry families and parent cycles are rejected | |
| instead of being replaced by placeholder boxes. | |
| ## Community gallery and privacy | |
| The upload page starts with **Share this result to the community gallery** | |
| enabled. The disclosure beside it states that publication includes the | |
| uploaded reference image and generated artifacts. Turn it off before choosing | |
| Generate to keep the job out of the gallery; opted-out and failed jobs are | |
| never copied to gallery storage. Opted-out job URLs are unlisted rather than | |
| access-controlled and expire with temporary job storage. | |
| Published entries are written atomically to a private Hugging Face Bucket | |
| mounted at `/data` and are exposed only through the gallery API below. They | |
| survive app restarts, unlike the short-lived per-job files under `/tmp`. | |
| Gallery cards open the real generated bundle in the same sandboxed viewer and | |
| offer the same downloads. The viewer provides orbit, zoom, pan, wireframe, | |
| shadow, camera-reset, and screenshot controls. | |
| ## Required Space Secrets | |
| Conversion needs a vision-capable Anthropic Messages or OpenAI-compatible chat | |
| endpoint. Add these under **Settings → Secrets**: | |
| | Secret | Required | Example | Purpose | | |
| | --- | --- | --- | --- | | |
| | `LLM_API_KEY` | yes | provider API key | Credential; never logged or returned to the browser. | | |
| | `LLM_MODEL` | yes | `claude-sonnet-4-5`, `moonshotai/kimi-k3` | Provider model identifier; it must accept images. | | |
| | `LLM_BASE_URL` | no | `https://api.anthropic.com` | Provider base URL; defaults to Anthropic. | | |
| | `LLM_API_STYLE` | no | `auto`, `anthropic`, or `openai` | `auto` tries Messages then falls back on HTTP 404. | | |
| | `LLM_MAX_TOKENS` | no | `32768` | Response budget for reasoning plus the structured spec. | | |
| | `LLM_TIMEOUT_S` | no | `180` | Per-request timeout in seconds. | | |
| | `LLM_MAX_RETRIES` | no | `2` | Transient provider retries. | | |
| | `LLM_REFERER`, `LLM_TITLE` | no | provider-specific | Optional attribution headers. | | |
| Set the public Space variable `GALLERY_DIR=/data/gallery`. The production | |
| Space mounts `hf://buckets/Mike0021/img2threejs-gallery` at `/data`; another | |
| deployment should mount its own Bucket at the same path. | |
| Optional operational variables are `JOB_TIMEOUT_S` (default `1800`, covering | |
| queue time through the completed browser bundle) and | |
| `GALLERY_PUBLISH_TIMEOUT_S` (default `120`, bounding the isolated persistent | |
| Bucket copy). Long opaque stages report elapsed time every 25 seconds; the UI | |
| does not invent completion percentages. | |
| `ANTHROPIC_API_KEY`/`ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and | |
| `ANTHROPIC_MODEL` are accepted as server-side aliases. Without a key and model, | |
| the app still starts, `/health` reports `llm_configured: false`, and job creation | |
| returns `503 llm_not_configured`; no model or placeholder is emitted. | |
| ## HTTP API | |
| ```bash | |
| curl https://<space-host>/health | |
| curl -F "file=@object.png" https://<space-host>/api/jobs | |
| curl -N https://<space-host>/api/jobs/<job-id>/events | |
| curl https://<space-host>/api/jobs/<job-id>/artifacts/spec.json | |
| curl https://<space-host>/api/jobs/<job-id>/artifacts/factory.ts | |
| curl https://<space-host>/api/jobs/<job-id>/artifacts/model.bundle.js | |
| curl https://<space-host>/api/jobs/<job-id>/artifacts/standalone.html | |
| curl 'https://<space-host>/api/gallery?offset=0&limit=24' | |
| curl https://<space-host>/api/gallery/<gallery-id> | |
| curl https://<space-host>/api/gallery/<gallery-id>/artifacts/standalone.html | |
| ``` | |
| Uploads are limited to PNG, JPEG, WebP, GIF, or BMP, 10 MiB, and 40 MP by | |
| default. SVG is rejected. Images are orientation-normalized, metadata-stripped, | |
| and downscaled to at most 1024 px before processing. Defaults permit 10 jobs per | |
| hour per client, 2 active conversions, and 8 queued/running jobs total. In the | |
| multipart job request, `share` defaults to `true`; send `share=false` to opt | |
| out. | |
| ## Run and test locally | |
| Python 3.12 and Node 22 are the tested versions. | |
| ```bash | |
| python3 -m pip install -r requirements.txt | |
| npm ci | |
| pytest -q | |
| python3 forge/tests/test_pipeline.py | |
| LLM_API_KEY=... LLM_MODEL=... LLM_BASE_URL=... python3 -m app.main | |
| # http://127.0.0.1:7860 | |
| ``` | |
| Build and verify the same target architecture used by Hugging Face: | |
| ```bash | |
| docker build --platform=linux/amd64 -t img2threejs . | |
| docker run --rm -p 7860:7860 \ | |
| -e LLM_API_KEY -e LLM_MODEL -e LLM_BASE_URL img2threejs | |
| scripts/verify_docker.sh | |
| ``` | |
| The Docker build regenerates a fixture factory through the real strict gate | |
| and hosted-preview compiler, bundles it with esbuild, and executes the bundle | |
| headlessly in Node. The final runtime image contains only runtime dependencies, | |
| `app/`, the required `forge/` source, and the license—not tests, scripts, | |
| rollouts, virtual environments, caches, or the upstream comparison clone. | |
| ## Deploy and verify | |
| The helper uses the currently authenticated local `hf` CLI account; an | |
| `HF_TOKEN` environment variable is not required. `--dry-run` performs no Hub | |
| mutation and prints the exact deterministic upload allowlist. | |
| ```bash | |
| hf auth whoami | |
| hf buckets create Mike0021/img2threejs-gallery --private --exist-ok | |
| hf spaces volumes set Mike0021/img2threejs \ | |
| --volume hf://buckets/Mike0021/img2threejs-gallery:/data | |
| hf spaces variables add Mike0021/img2threejs --env GALLERY_DIR=/data/gallery | |
| python3 scripts/deploy_space.py --dry-run | |
| python3 scripts/deploy_space.py # sets present LLM_* aliases as Secrets | |
| # or: python3 scripts/deploy_space.py --no-secrets | |
| hf spaces logs Mike0021/img2threejs --build --follow | |
| hf spaces logs Mike0021/img2threejs --follow | |
| python3 scripts/verify_space.py # wait/info/logs + GET-only probes | |
| python3 scripts/verify_space.py \ | |
| --e2e tests/fixtures/mug_photo.png # real SSE job + artifact/node smoke | |
| ``` | |
| The deploy helper stages only its allowlist and issues one sanitized | |
| `hf upload`. Secret values are passed in a temporary mode-0600 secrets file; | |
| only secret names are printed. The live verifier never submits a job unless an | |
| explicit `--e2e IMAGE` is supplied. | |
| ## Repository layout | |
| | Path | Purpose | | |
| | --- | --- | | |
| | `app/` | FastAPI service, LLM client, pipeline adapter, SPA, and sandboxed viewer | | |
| | `forge/` | Vendored upstream v1.3 pipeline with targeted runtime generator/safety fixes | | |
| | `grimoire/`, `SKILL.md` | Upstream rubrics and complete agent workflow | | |
| | `UPSTREAM_REVISION` | Exact upstream version and commit provenance | | |
| | `tests/` | Unit, HTTP, pipeline, manifest, and render smoke tests | | |
| | `scripts/` | Fixture builder, Node smoke, Docker verifier, deployer, live verifier | | |
| | `docs/SECURITY.md` | Threat model, controls, and accepted limitations | | |
| The targeted `forge/` changes preserve declared component dimensions without | |
| scaling child pivots, avoid misinterpreting non-axis attachments, detect parent | |
| cycles, and retain explicit hosted-preview honesty labels. The Space supports | |
| the v1.3 advanced primitive set instead of replacing unknown geometry with | |
| boxes. The adapter is therefore intentionally not a byte-for-byte upstream | |
| tree. | |
| ## License and attribution | |
| MIT — © 2026 hoainho (upstream) and this Space's contributors. See | |
| `LICENSE`. three.js is MIT © the three.js authors. | |