No description
Archives - ZIP, 7Z, RAR and TAR/.tar.gz uploads are indexed in the background into archive_entries (7-Zip compiled to WASM in a worker thread; node-tar for tar). macOS/Windows clutter and paths that could escape the extraction folder are skipped. - Models inside archives are extracted once per archive to hash and geometry-fingerprint them, so duplicates are found inside packs too. Pictures, PDFs and readmes are listed but never matched. - New routes list an archive's entries and serve/convert a single entry, extracted on first use and cached under extracted/. Viewer - Model detail lists what's inside each archive with view/download links; opening an entry adds a viewer tab. - New 3D formats: FBX (with sibling textures), OBJ with its MTL and textures, STEP/STP via occt-import-js, and Rhino 3DM via rhino3dm — the WASM readers are served from node_modules, loaded on first use. - Pictures, PDFs and text files (jpg/png/gif/webp/bmp/svg, pdf, txt/md) can be uploaded and preview in the viewer; a model without an embedded 3MF preview uses its first picture as the card thumbnail. - Inline file responses send nosniff, and SVGs are sandboxed. - GLB conversions write to a temp file and rename, so a half-written preview is never served; a later tab can't be overdrawn by a slow load. - Better 3MF card image: the project thumbnail or plate 1 render, not a slicer pick map. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|---|---|---|
| .forgejo/workflows | ||
| db | ||
| lib | ||
| public | ||
| test | ||
| tools | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| server.js | ||
Printhive
A self-hosted web app for organizing your 3D-printing files (STL, 3MF, OBJ, STEP, GCODE, ZIP) into a searchable library — with in-browser 3D previews, collections, license/commercial-use tracking, and one-paste import from popular model sites.
Features
- Library of models, each owning one or more files; tags, collections, descriptions, print settings.
- Import from URL:
- Thingiverse — downloads files automatically via the official API (needs a free app token).
- Printables — downloads files automatically via its public GraphQL API (no auth needed for free models).
- MakerWorld — downloads files via FlareSolverr (solves Cloudflare) + your account token.
- cubee3d (Hive) and any other URL — imports title/description/preview image; you add the files manually.
- In-browser 3D viewer (Three.js) for STL/OBJ, and for 3MF via a server-side trimesh GLB conversion (handles Bambu/MakerWorld production-extension files the JS loader can't).
- Auto thumbnails rendered from the model; embedded 3MF thumbnails used when present.
- License & commercial-use tracking — captured per source, with a "sellable / non-commercial" indicator (a guide; verify before selling).
- Collections — group models (a model can be in many); rename/delete without losing models.
- Editing — rename/retag, edit print settings, override commercial-use, refresh metadata from source, re-download files, download all files as a zip.
- Notes — free-form notes per model, saved as you type.
- Search, filters & sorting — search across names, descriptions, notes, tags, file names and designers; filter by format, source and license; include or exclude tags (match any/all); sort and group by source or format. Press / to search.
- Duplicate finder — every file gets a SHA-256 content hash plus (for STL/OBJ/3MF) a geometry fingerprint, computed in the background. Models sharing files are grouped as exact copies or same shape (renamed, re-exported, converted — or mirrored, so check those), with a recommended copy to keep. Keeping one merges the others' tags, collections and notes into it and moves them to the trash; groups can be dismissed as "not duplicates".
- Trash — deleting moves a model to the trash; restore it, delete it forever, or empty the trash (only then are files removed from disk).
- Settings — API tokens / FlareSolverr URL stored in the database (with
.envfallback), secrets masked.
Tech stack
- Node.js + Express, vanilla-JS frontend (no build step), PostgreSQL.
- Three.js (viewer) via CDN import map.
- Python + trimesh sidecar for 3MF→GLB conversion, volume, and geometry fingerprints.
- Optional FlareSolverr for Cloudflare-protected sources.
Setup
- Postgres — create a database and point
DATABASE_URLat it. The schema is applied automatically on startup. - Python sidecar (for 3MF previews/volume and shape-based duplicate detection — without it, duplicates are still found by content hash):
python3 -m venv tools/venv tools/venv/bin/pip install trimesh numpy networkx lxml - Install deps and run:
npm install cp .env.example .env # set DATABASE_URL (+ optional tokens) npm start - Open http://localhost:3000
Run the unit tests with npm test.
Configuration
Settings live in the database (editable in the app's Settings menu) and fall back to environment variables:
| Setting | Env var | Purpose |
|---|---|---|
| Thingiverse API token | THINGIVERSE_TOKEN |
Thingiverse auto-download |
| FlareSolverr URL | FLARESOLVERR_URL |
Read Cloudflare-protected sites (MakerWorld) |
| MakerWorld auth token | MAKERWORLD_TOKEN |
MakerWorld downloads (bearer token from your session) |
| Printables auth token | PRINTABLES_TOKEN |
Optional; account-gated Printables files |
Notes
- Auto-download from MakerWorld/Printables relies on their private/session APIs and can break if they change; failed/partial imports can be recovered with "Download files from source".
- The commercial-use badge is a best-effort read of the license — always confirm on the source page before selling.