refactor: clean upload pipeline and restore draco delivery

This commit is contained in:
Tom Boullay
2026-04-29 16:29:32 +02:00
parent 097b8f6486
commit 498765db61
32 changed files with 769 additions and 215 deletions
+14 -20
View File
@@ -3,7 +3,7 @@
A secure web interface for uploading `model.gltf` with its associated `.bin` file and textures with two outputs:
- **Nextcloud Drive** — Archives the original files with automatic versioning (VF/V1/V2...), so artists always have a history of past versions
- **GitHub** — Delivers GLTF assets and compressed textures to the dev team's repository, ready for integration
- **GitHub** — Delivers Draco-compressed GLB assets by default, with an optional GLTF delivery mode for specific models
Built for La Fabrik Durable's internal use, but open-sourced for anyone looking for a similar solution. The app validates the upload locally, stages it server-side, then applies intelligent diffs to avoid unnecessary uploads and commits. The Drive upload serves as the source of truth and version history, while the GitHub upload delivers the prepared assets to developers
@@ -34,7 +34,7 @@ The app runs on `http://localhost:3000` with hot reload. The upload API routes a
- Any associated binary buffer (`.bin`, for example `model.bin`)
- Any associated textures (`.png/.jpg/.jpeg/.webp`)
3. The folder is validated locally. `.glb` files are not accepted.
4. On clicking "Envoyer":
4. On clicking "Envoyer" or "Envoyer en GLTF":
- The app uploads the folder once to a temporary server-side staging area
- The app prepares the final Git payload from this staging area
- The app checks the remote Git repo for existing files and computes diffs
@@ -57,7 +57,7 @@ Invalid or unknown asset names still block the upload.
### Upload flow: Drive first, then Git
5. **Drive upload (archiving)** — Original files from the staging area are uploaded to the Nextcloud Drive with automatic versioning (see below). This serves as the artists' source of truth and version history. If the Drive upload fails, a modal asks the user whether to send to Git only or cancel entirely.
6. **Git upload (delivery to devs)** — The prepared Git payload is reused from staging: `model.gltf` and `.bin` files are preserved, textures are compressed server-side, then all changed files are pushed to GitHub in a single commit. This is what the dev team consumes in the application.
6. **Git upload (delivery to devs)** — The prepared Git payload is reused from staging. By default, Blender exports a single `model.glb` with Draco compression. For specific models, "Envoyer en GLTF" keeps the current separate `model.gltf` + `.bin` + compressed textures workflow.
### Drive versioning (Nextcloud WebDAV)
@@ -99,16 +99,7 @@ All changes are pushed in a **single commit** with a grouped formatted message:
update: upload-gltf add a new model -> my-model
📦 Model
✅ model.gltf
🎨 Textures (color)
✅ color_porte.jpg (compressed)
🪶 Textures (roughness)
✅ roughness_tuyaux.png (compressed)
🧩 Assets
✅ model.bin
✅ opacity_fenetre.png (compressed)
✅ model.glb (compressed)
```
**Update (only one texture changed):**
@@ -116,10 +107,7 @@ update: upload-gltf add a new model -> my-model
update: upload-gltf update -> coffeetest
📦 Model
↔️ model.gltf
🎨 Textures (color)
🔄 color_tuyaux.jpg (compressed)
🔄 model.glb (compressed)
```
Commit sections:
@@ -135,7 +123,7 @@ Commit sections:
Symbols: `✅` new — `🔄` modified — `↔️` unchanged (model always re-pushed) — `❌` deleted
7. Orphan files (present on remote but not in the new upload) are deleted in the same commit
8. `model.gltf` is pushed as-is so companion files like `model.bin` remain valid
8. Default Git delivery pushes `model.glb` only; "Envoyer en GLTF" pushes separate `model.gltf`, `.bin`, and compressed textures.
Uploaded models are pushed to `public/models/<folderName>/` in the target repo.
@@ -143,6 +131,7 @@ Uploaded models are pushed to `public/models/<folderName>/` in the target repo.
- Large uploads are faster than before because the folder is staged only once, but the Drive upload remains sequential.
- Git LFS batch uploads are sequential by batch.
- Default GLB Draco delivery reduces Git LFS usage by replacing many support files with one compressed model file.
- Uploads expect a single `model.gltf` file plus optional flat support files (`.bin`, `.png`, `.jpg`, `.jpeg`, `.webp`).
## Project Structure
@@ -193,11 +182,14 @@ lib/
├── upload-lock.ts # Lightweight in-memory per-folder upload lock
├── asset-classification.ts # Group assets by family for commit messages
├── asset-naming.ts # Allowed asset families and naming convention helpers
├── blender.ts # Blender Draco compression helper
├── commit-message.ts # Commit message builder
├── parse-upload.ts # FormData parser + validation
├── validate-folder.ts # Client-side folder validation (discriminated union)
└── format-bytes.ts # Byte formatting utility
Dockerfile # Multi-stage build: Node 20 slim + tini
scripts/
└── compress.py # Blender Draco compression script
Dockerfile # Multi-stage build: Node 20 slim + Blender + tini
docker-entrypoint.sh # Startup check + launch
```
@@ -253,7 +245,7 @@ docker run -p 3000:3000 \
upload-gltf
```
The Docker image runs the Next.js app and server-side asset preparation in a single container. The `docker-entrypoint.sh` script checks for required environment variables before launching the app
The Docker image runs the Next.js app, Blender Draco compression, and server-side asset preparation in a single container. The `docker-entrypoint.sh` script checks for required environment variables before launching the app
## Supported Formats
@@ -263,6 +255,8 @@ The Docker image runs the Next.js app and server-side asset preparation in a sin
| Binary buffers | `.bin` |
| Textures | `.png`, `.jpg`, `.jpeg`, `.webp` |
Git delivery outputs `.glb` by default, or keeps the source `.gltf` structure when "Envoyer en GLTF" is selected.
## License
See [MIT](LICENSE) License