Tom Boullay 3adcf9d30e fix: skip model size comparison in diff check (Blender compression changes size)
Models are always re-pushed server-side since Draco compression changes
the file size, making client/remote size comparison unreliable.
Textures are still compared by size (not compressed, reliable).
Client-side diff now only flags models as 'new' if absent from remote,
and never as 'changed' (server handles the actual push decision).
2026-04-14 14:48:59 +02:00
2026-04-14 14:27:50 +02:00
2026-04-03 10:22:24 +02:00
2026-04-14 11:18:53 +02:00
2026-04-14 14:27:50 +02:00
2026-04-03 13:45:23 +02:00
2026-04-03 10:41:56 +02:00
2026-04-14 14:06:04 +02:00
2026-04-14 11:18:53 +02:00
2026-04-14 10:54:43 +02:00
2026-04-14 14:27:50 +02:00
2026-04-03 10:22:24 +02:00
2026-04-14 14:06:04 +02:00
2026-04-14 14:27:50 +02:00
2026-04-03 11:32:56 +02:00

upload-GLTF

A secure web interface for uploading 3D assets (GLTF/GLB + textures) with automatic Draco compression and GitHub push. Built for La Fabrik Durable.

Stack

  • Next.js 16 (App Router) + React 19 + TypeScript
  • Three.js (@react-three/fiber + @react-three/drei) for 3D preview
  • Tailwind CSS for styling
  • Octokit for pushing via the GitHub API
  • Blender (headless) for Draco mesh compression
  • Coolify (Docker) for hosting

Installation

git clone https://github.com/La-Fabrik-Durable/upload-GLTF.git
cd upload-GLTF
npm install

Configuration

Copy .env.example to .env.local and fill in the values:

UPLOAD_SECRET_KEY=your-secret-key-here
GITHUB_TOKEN=ghp_your-github-personal-access-token
GIT_BRANCH=main
GIT_REPO_URL=https://github.com/your-org/your-repo.git
BLENDER_PATH=/Applications/Blender.app/Contents/MacOS/Blender
Variable Description Required
UPLOAD_SECRET_KEY Secret key for upload authentication Yes
GITHUB_TOKEN GitHub Personal Access Token (fine-grained, Contents: Read and write) Yes
GIT_BRANCH Target branch (default: main) No
GIT_REPO_URL Target GitHub repository URL Yes
BLENDER_PATH Path to Blender binary (default: blender) No

To create a token: GitHub > Settings > Developer settings > Fine-grained personal access tokens > select the target repo > Permissions > Contents: Read and write.

Usage

Development

npm run dev

Access the app at http://localhost:3000

Note: Draco compression requires Blender installed locally. On macOS, Blender is typically at /Applications/Blender.app/Contents/MacOS/Blender. Set BLENDER_PATH in .env.local accordingly. If Blender is not available, models are pushed to GitHub without compression.

Production (Coolify / Docker)

docker build -t upload-gltf .
docker run -p 3000:3000 \
  -e UPLOAD_SECRET_KEY=your-key \
  -e GITHUB_TOKEN=ghp_xxx \
  -e GIT_REPO_URL=https://github.com/org/repo.git \
  upload-gltf

The Docker image includes Blender headless (installed once at build time). On startup, the entrypoint checks if Blender is available and logs its version. No extra configuration is needed in production — BLENDER_PATH defaults to blender which is in the container's PATH.

How it works

  1. The user enters their access key

  2. They pick a destination (farm, map, powergrid, workshop, general, environment)

  3. They select a folder containing:

    • model.glb or model.gltf (required)
    • Textures: roughness, normal, metalness, color, displace (.png/.jpg/.webp, optional — missing textures show a warning but don't block the upload)
  4. The model is displayed in a 3D preview

  5. On clicking "Envoyer sur GitHub":

    • The app computes the git SHA of each local file and compares with the remote repo
    • If the folder doesn't exist, upload proceeds directly
    • If the folder exists and files differ, a confirmation dialog shows only the actual changes (modified, new, or deleted files)
    • If the folder exists and nothing changed, the upload is skipped entirely ("Aucun fichier modifie")
  6. For models: the file is written to /tmp, compressed with Blender Draco, then the compressed version is pushed

  7. For textures: pushed directly without compression

  8. Only changed and new files are pushed — unchanged files are skipped to save bandwidth and API calls

  9. All changes are pushed in a single commit with a formatted message that only lists what changed:

    New folder:

    update: upload-gltf add a new model -> farm/my-model
    
    📦 Model
      ✅ model.gltf (compressed)
    🎨 Textures
      ✅ color.jpg
      ❌ metalness (manquant)
    

    Update (only metalness changed):

    update: upload-gltf update -> general/coffeetest
    
    🎨 Textures
      🔄 metalness.jpg
    

    Symbols: new — 🔄 modified — missing or deleted

  10. Orphan files (present on remote but not in the new upload) are deleted in the same commit

  11. If Blender is unavailable, the original model is pushed as-is (graceful fallback)

Destinations

Uploaded models are pushed to public/models/<destination>/<folderName>/ in the target repo:

Destination Path
Farm public/models/farm/
Map public/models/map/
Powergrid public/models/powergrid/
Workshop public/models/workshop/
General public/models/general/
Environment public/models/environment/

Project Structure

app/
├── api/upload/route.ts    # API: GET (check + SHA diff) + POST (compress + smart push)
├── globals.css            # Tailwind + Google Fonts
├── layout.tsx             # Root layout
└── page.tsx               # Home page
components/
├── UploadZone.tsx         # UI: key input, destination picker, folder picker, SHA diff, overwrite confirmation, upload
├── ModelViewer.tsx         # Lazy wrapper for the 3D viewer
└── SceneViewer.tsx         # Three.js Canvas
scripts/
└── compress.py            # Blender Draco compression script
Dockerfile                 # Multi-stage build: Node 20 slim + Blender headless + tini
docker-entrypoint.sh       # Startup: Blender check + launch

Supported Formats

Type Extensions
3D Models .glb, .gltf
Textures .png, .jpg, .jpeg, .webp

License

MIT

S
Description
A secure upload interface for 3D assets with automatic deployment to GitHub via Git LFS
Readme MIT 479 KiB
Languages
TypeScript 92%
Python 6.4%
Dockerfile 1%
Shell 0.5%
CSS 0.1%