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. SetBLENDER_PATHin.env.localaccordingly. 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 Dockerfile includes Blender headless for automatic Draco compression.
How it works
- The user enters their access key
- They pick a destination (
farm,map,powergrid,workshop,general,environment) - They select a folder containing:
model.glbormodel.gltf(required)- Textures:
roughness,normal,metalness,color,displace(.png/.jpg/.webp, optional)
- The model is displayed in a 3D preview
- On clicking "Envoyer sur GitHub":
- The app checks if the folder already exists on the remote repo
- If it exists, a confirmation dialog is shown listing the existing files that will be replaced
- On confirmation (or if the folder is new), all files are sent to the
/api/uploadendpoint
- For models: the file is written to
/tmp, compressed with Blender Draco, then the compressed version is pushed - For textures: pushed directly without compression
- All files are pushed in a single commit with a formatted message:
update: upload-gltf add a new model -> farm/my-model 📦 Model ✅ model.gltf (compressed) 🎨 Textures ✅ color.jpg ❌ metalness (manquant) - If the folder already existed, orphan files (present in the old version but not in the new upload) are deleted in the same commit
- 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 existence) + POST (compress + push)
├── globals.css # Tailwind + Google Fonts
├── layout.tsx # Root layout
└── page.tsx # Home page
components/
├── UploadZone.tsx # UI: key input, destination picker, folder picker, validation, overwrite confirmation, upload
├── ModelViewer.tsx # Lazy wrapper for the 3D viewer
└── SceneViewer.tsx # Three.js Canvas
scripts/
└── compress.py # Blender Draco compression script
Supported Formats
| Type | Extensions |
|---|---|
| 3D Models | .glb, .gltf |
| Textures | .png, .jpg, .jpeg, .webp |
License
MIT