mesh-avatar-studio
Turn one illustration into an animated 2D mesh avatar with a coding agent and a local editor
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證AI chat-to-STL portal: describe an object, DeepSeek V4.1 Flash designs it, an exact Manifold geometry kernel builds a watertight 3D-printable STL plus a Blender script. Next.js 16, PostgreSQL, 3D viewer, gallery with likes and sharing, credit-based plans, Coolify-ready.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗
Describe an object in the chat, get back a watertight, printable STL plus a Blender Python script that rebuilds it with native primitives and booleans. Preview it in 3D, refine it in conversation, publish it to a gallery with likes and social sharing, and download it. Credit‑based plans: Free (10 credits), Starter (100/month), Pro (1000/month); a new model costs 5 credits, each edit 1 (Free = one model plus five edits, text only).
Inspired by Meshy AI and Tripo AI, built for Blender users and FDM printers.
https://3dblend.tertiaryinfotech.com — hosted on Hostinger via Coolify. Every push to main is deployed automatically through a GitHub webhook.
{op:"mesh"} in the agent's spec: a watertight base solid (via Manifold) the agent can cut, extend, scale or move; upload a 3DBlend Blender script and its embedded spec is restored for further editing.src/agent/) — DeepSeek V4.1 Flash emits a tiny JSON CSG language; a deterministic kernel builds it; printability checks feed errors back for automatic repair. Runs from the CLI too..3mf (units, indexed mesh, metadata) for Bambu Studio, PrusaSlicer and Cura, and .obj (millimetres, Z‑up, same frame as the STL) for Blender, Fusion and game engines; both derived from the stored STL and cached..blender.py per model that recreates the design with bmesh primitives, EXACT booleans, arrays and mirrors, in millimetres, sitting on the build plate.M400 U1), PrusaSlicer (M600/M601) and Cura/Marlin (M0/M600), plus material‑pairing tips.src/lib/site.ts.remixOfId) and a "Title by Author" snapshot that every later version inherits; shown on the share page, in the studio, on gallery cards and inside the 3MF metadata (CC BY 4.0).defaultVisibility / canMakePrivate in src/lib/plans.ts)./admin (users flagged isAdmin): overview KPIs, all users with search and pagination (plan, credit top‑ups, grant/revoke admin), every subscription and invoice (sync, cancel, PDF), gallery moderation (feature, hide, delete), and an Integrations tab: DeepSeek API, HitPay keys, SMTP, each with a test button, plus editable transactional email templates (welcome, subscription activated, invoice with PDF, cancellation). Settings saved there override the environment and secrets are encrypted at rest.┌────────────┐ SSE ┌──────────────────────┐ OpenAI-compatible ┌───────────────────┐
│ Next.js │ ◄──────► │ /api/chat (harness) │ ──────────────────────► │ DeepSeek V4.1 │
│ App Router│ │ validate → build → │ ◄────── JSON spec ───── │ Flash │
│ R3F viewer│ │ check → repair loop │ └───────────────────┘
└─────┬──────┘ └──────────┬───────────┘
│ Prisma │ Manifold (WASM) → binary STL + Blender .py
▼ ▼
┌────────────┐ ┌──────────────────────┐
│ PostgreSQL │ │ STORAGE_DIR volume │
└────────────┘ └──────────────────────┘
user idea (+ image / PDF, printer, nozzle, material)
│
▼
LLM ─► { message, spec } ─► zod validation ─► Manifold build ─► DFM checks ─► OK? ──► optimise pass ─► STL / 3MF / .py
▲ │ │ │ (kept only if the
└──────── repair prompt with the exact errors ◄─────┴──────────────┘ print score improves)
(max 4 attempts)
The model never touches geometry directly. It writes a declarative spec in a ~20‑op CSG DSL (cube, cylinder, sphere, cone, torus, roundedBox, extrude, revolve, union, difference, intersection, hull, translate, rotate, scale, mirror, repeat, radial, ref/parts). The harness owns every side effect, which keeps generation deterministic, cheap (one LLM call per attempt, ~3 s), replayable, and safe to expose publicly.
Key files:
| File | Purpose |
|---|---|
src/agent/spec.ts | DSL schema (zod) and semantic validation (refs, cycles, size limits) |
src/agent/kernel.ts | Manifold builder → positions/indices, volume, bbox, genus, shells |
src/agent/checks.ts | DFM analysis: fit, overhangs, bridges, thin walls, layer height, material tips |
src/agent/thickness.ts | Local wall‑thickness map via BVH ray casting (three-mesh-bvh) |
src/lib/printers.ts | Printer / nozzle / material presets |
src/components/PrintSetup.tsx | Printer / nozzle / material selector (persisted per browser) |
src/app/api/messages/[id]/image | Serves a message's reference image (owner only) |
src/agent/stl.ts | Binary STL writer + parser |
src/agent/threemf.ts | 3MF (zip + XML) writer |
src/agent/obj.ts | Wavefront OBJ writer |
src/components/ModelStage.tsx | Viewer wrapper with the 3D ⇄ Render toggle, finish/colour picker and PNG export |
src/lib/colour-swap.ts / src/components/TwoColourGuide.tsx | Swap‑height suggestions and the per‑slicer two‑colour guide |
src/agent/blender.ts | Spec → self‑contained bpy script |
src/agent/llm.ts | DeepSeek client (OpenAI SDK, non‑thinking mode, JSON output; TruncatedOutputError on token‑cap hits) |
src/agent/harness.ts | The generate → validate → build → check → repair → optimise loop (text + image input) |
src/lib/editor.ts / src/components/ShapeEditor.tsx | Manual shape editor model and the 3D edit‑mode UI (TransformControls gizmos) |
src/lib/security.ts | Turnstile verification, honeypot, in‑memory rate limiter |
src/lib/verification.ts | Email verification tokens and sending |
src/lib/settings.ts |
Why non‑thinking mode? DeepSeek V4.x in thinking mode spends its entire token budget reasoning about geometry and returns empty content for anything non‑trivial. The harness supplies the verification loop instead, and direct mode answers in ~3 s. Set
DEEPSEEK_THINKING=1to opt back in.
Runaway replies. Flash occasionally loops, re‑emitting the same few nodes until it hits the output cap. Spec calls are capped at 8k tokens (real specs are ~2k); a cut‑off reply counts as one attempt and the harness retries with a "be compact — use
repeat/radial/parts" nudge instead of failing the request. Only if every attempt runs away does the request fail (and the credit is refunded).
git clone https://github.com/alfredang/3dblend.git && cd 3dblend
npm install
cp .env.example .env # fill DEEPSEEK_API_KEY, DATABASE_URL, AUTH_SECRET
docker run -d --name 3dblend-pg -e POSTGRES_USER=blend -e POSTGRES_PASSWORD=blend -e POSTGRES_DB=blend -p 5544:5432 postgres:16-alpine
npm run db:push # create tables
npm run db:seed # demo users + 6 featured models (optional; also happens on first page view)
npm run dev # http://localhost:3000
Demo login: [email protected] / demo1234 (Pro plan, 1000 credits). With SEED_ADMIN_PASSWORD / SEED_TEST_PASSWORD set, [email protected] and [email protected] are also available (passwords from the env).
Move models between instances (for example local → production); the target rebuilds each model from its spec and skips ones it already has:
TARGET_URL=https://3dblend.tertiaryinfotech.com ADMIN_PASSWORD=... npm run push-models
Try the harness without the web app:
npm run agent -- "a desk phone stand for a 75mm wide phone, angled 65 degrees, with a cable slot"
# → out/phone-stand.stl, out/phone-stand.blender.py, out/phone-stand.spec.json
| Variable | Required | Notes |
|---|---|---|
DEEPSEEK_API_KEY | ✅ | DeepSeek API key |
DEEPSEEK_BASE_URL | default https://api.deepseek.com | |
DEEPSEEK_MODEL | default deepseek-flash (= DeepSeek‑V4.1‑Flash) | |
DATABASE_URL | ✅ | PostgreSQL connection string |
AUTH_SECRET | ✅ | openssl rand -base64 32 |
NEXT_PUBLIC_APP_URL / NEXTAUTH_URL | ✅ | public URL (share links, HitPay redirect and webhook URLs, email links) |
STORAGE_DIR | where STL / .py files live (/data/storage in Docker, mount a volume) | |
HITPAY_API_KEY, HITPAY_SALT, HITPAY_WEBHOOK_SALT, HITPAY_SANDBOX, HITPAY_CURRENCY | enable paid upgrades via HitPay recurring billing (sandbox with HITPAY_SANDBOX=1); without a key the UI shows “Coming soon” | |
CRON_SECRET | protects GET /api/cron/reset-credits (monthly top‑ups) | |
SEED_ON_BOOT | 0 disables auto‑seeding of sample models | |
TURNSTILE_SITE_KEY, TURNSTILE_SECRET_KEY, REQUIRE_EMAIL_VERIFICATION | sign‑up bot protection and verification toggle (also editable in Admin → Integrations) | |
SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASS, SMTP_FROM_NAME, SMTP_FROM_EMAIL, SMTP_REPLY_TO | transactional email; all of these (and the AI / HitPay keys) can instead be set in Admin → Integrations | |
SEED_ADMIN_PASSWORD, SEED_TEST_PASSWORD | when set, [email protected] (admin, Pro) and [email protected] (Free) are created/updated on boot |
The production instance was created through the Coolify API; the same steps work from the UI:
https://github.com/alfredang/3dblend, branch main, build pack Docker Compose, compose file /docker-compose.yml. Coolify builds the multi‑stage Dockerfile (Next.js standalone output) and brings up the bundled PostgreSQL 16 service with persistent pgdata and storage volumes.POSTGRES_PASSWORD, DEEPSEEK_API_KEY, AUTH_SECRET, NEXT_PUBLIC_APP_URL, CRON_SECRET). Coolify pre‑creates the keys from the compose file.web service: https://3dblend.tertiaryinfotech.com:3000 (the :3000 tells the Traefik proxy which container port to route to; the service is not published on the host). Coolify provisions TLS.https://<coolify-host>/webhooks/source/github/events/manual, content type application/json, secret = the application's Manual webhook secret (Coolify → app → Webhooks), event push. With Auto Deploy enabled, every push to main redeploys. Manual trigger: POST /api/v1/deploy?uuid=<app-uuid> with a Coolify API token.prisma db push so the schema is always in sync; sample models are seeded on the first page view.curl -fsS -H "x-cron-secret: $CRON_SECRET" https://3dblend.tertiaryinfotech.com/api/cron/reset-creditsSMTP_* variables); use the test buttons there to verify DeepSeek, HitPay and SMTP after deploying.Local run of the same stack: docker compose -f docker-compose.yml -f docker-compose.local.yml up --build (the override publishes port 3000).
Health check: GET /api/health.
| Route | Method | Description |
|---|---|---|
/api/register | POST | create account (10 free credits); Turnstile + honeypot + rate limit; sends the verification email |
/api/auth/verify, /api/auth/resend | GET / POST | consume a verification link / resend it |
/api/auth/* | Auth.js credentials provider | |
/api/projects | GET / POST | list / create chat projects |
/api/chat | POST (SSE) | run the agent for a project with { message, setup, attachment? }; events status, message, model, credits, error |
/api/messages/:id/image, /api/messages/:id/attachment | GET | reference image / original upload for a chat message (owner only) |
/api/models/:id/stl | GET | binary STL (?download=1 counts a download) |
/api/models/:id/3mf | GET | 3MF package (?download=1 counts a download) |
/api/models/:id/blender | GET | Blender Python script |
/api/models/:id/like | POST | toggle thumbs‑up |
/api/models/:id/publish | POST | toggle gallery visibility, edit title/description |
/api/models/:id/remix | POST | copy a public model into a new project of yours |
/api/models/:id/edit | POST | manual shape edit: merge { shapes[] } into the spec, rebuild, save as a new version |
/api/billing/checkout | POST | create a HitPay recurring billing for STARTER / PRO, returns the hosted checkout URL |
/api/billing/return | GET | HitPay redirect target; re-verifies the subscription with HitPay's API |
User (plan, credits, isAdmin) → Subscription (HitPay recurring billing, status lifecycle) → Invoice (numbered, one per charge); User → Project → Message (role, content, optional modelId, optional reference imagePath / attachmentPath / extracted attachmentText) and Model (spec JSON, stats JSON, stlPath, blenderPath, isPublic, featured, counters) with Like (user × model) and CreditTransaction (audit log).
Next.js 16 (App Router, standalone output) · React 19 · TypeScript · Tailwind CSS 4 · Prisma 6 + PostgreSQL 16 · Auth.js v5 · OpenAI SDK → DeepSeek V4.1 Flash (text + vision) · manifold‑3d (WASM) · three.js / @react‑three/fiber / drei · three‑mesh‑bvh · pdfjs‑dist + @napi‑rs/canvas · pdf‑lib · fflate · HitPay · Docker / Coolify.
.blender.py exporter targets Blender 3.6+.MIT © Alfred Ang. Gallery models are shared by their authors under CC BY 4.0 unless stated otherwise.
| DB‑backed integration settings with env fallback and AES‑GCM‑encrypted secrets |
src/lib/email.ts | SMTP sending (nodemailer) and editable {{variable}} templates |
src/lib/attachments.ts | Attachments: images, PDF text + first‑page render, STL/3MF import, Blender‑script spec recovery |
src/agent/meshio.ts | STL (ASCII/binary) and 3MF parsers, spec extraction from exported Blender scripts |
src/agent/prompts.ts | System prompt with the DSL reference and FDM design rules |
scripts/push-models.ts | Sync local models to another instance through the admin import API |
scripts/agent-cli.ts | npm run agent -- "a hex pencil cup" → out/*.stl, *.blender.py, *.spec.json |
/api/billing/webhook| POST |
HitPay callbacks (event webhooks with Hitpay-Signature, or legacy hmac form callbacks) |
/api/billing/cancel, /api/billing/sync | POST | cancel at HitPay / re-check status |
/api/invoices/:id/pdf | GET | invoice PDF (owner or admin) |
/api/admin/users, /api/admin/models, /api/admin/subscriptions | PATCH/DELETE | admin actions |
/api/admin/models/import | POST | admin bulk import: rebuild models from specs (used by npm run push-models) |
/api/admin/settings, /api/admin/settings/test, /api/admin/email-templates, /api/admin/email-templates/test | GET/PUT/POST | integrations and email templates |
/api/cron/reset-credits | GET | monthly credit top‑up (secret header) |
/api/health | GET | DB connectivity |