A web app that generates 3D models from natural language (and reference images) and renders them in-browser with three.js. The backend runs Blender headless in a CPU Docker container and exports GLB files. It works like a code agent: each session keeps a conversation history and follow-up messages refine the model.
- Procedural strategy (no API key needed, always works): a deterministic parser
turns your prompts into a JSON spec; Blender builds that spec with
bpyand exports GLB. - Code-agent strategy ("codex"/LLM): an OpenAI-compatible LLM writes Blender Python from your conversation; the backend runs it headless and exports GLB. If the generated code errors, the error is fed back to the LLM for up to 2 retries (SceneCraft / LL3M "code-as-representation" pattern).
Architecture and exact interfaces are documented in DESIGN.md.
A prebuilt image is published to GHCR from CI:
docker pull ghcr.io/sloth-os/blender:latest
docker run -p 8080:8000 -v "$PWD/data:/app/data" ghcr.io/sloth-os/blender:latestOr build and run the full stack locally:
docker compose up --buildThen open http://localhost:8080.
To enable the code-agent (LLM) strategy, set these before building/running:
export LLM_BASE_URL=https://api.openai.com/v1
export LLM_API_KEY=sk-...
export LLM_MODEL=gpt-4o-mini
docker compose up --buildWithout these, the app runs in procedural mode (no key required).
You need Blender installed and on your PATH (or set BLENDER_PATH).
# Backend
cd backend
pip install -r requirements.txt
cd ..
export BLENDER_PATH=$(which blender)
uvicorn backend.app.main:app --reload --port 8000The backend also serves the frontend at http://localhost:8000 (FastAPI mounts
frontend/ at /). For separate hot-reloading of the frontend you can run:
cd frontend
python3 -m http.server 8080and open http://localhost:8080 (it will call the API on localhost:8000).
| Method | Path | Description |
|---|---|---|
| POST | /api/sessions |
Create a new session |
| GET | /api/sessions/{id} |
Get session + message history |
| POST | /api/sessions/{id}/generate |
Generate/refine a model (prompt + images) |
| GET | /api/files/{id}/{file} |
Download a generated GLB |
| GET | /api/health |
Health + Blender/LLM status |
POST /api/sessions/{id}/generate is multipart/form-data:
prompt (str), strategy (auto|procedural|code), images (files, optional).
Returns { session_id, turn, glb_url, code, rationale, strategy_used, error }.
- "a red cube"
- "make it bigger and add a small blue torus"
- "3 green cones"
- "a yellow sphere at 0 0 2 and a purple cylinder"
Follow-ups refine the model in the same session.