GLB Studio Deploy commited on
Commit
ca1349e
Β·
1 Parent(s): 60cf654

fix: all HF Space issues resolved

Browse files

1. PropertiesPanel.jsx: fixed operator precedence bug
!model[key]??true β†’ !(model[key]??true)
(was causing incorrect boolean logic on shadow toggles)

2. nginx.conf: removed Cross-Origin-Embedder-Policy header
COEP was blocking ALL cross-origin resource loading:
- GLB/GLTF models from threejs.org, supabase.co etc
- HDR/image skyboxes from external URLs
- Google Fonts
Removing COEP fixes model loading completely

3. README.md: clean valid HF front-matter, no trailing content issues

4. dist/: rebuilt with all fixes applied (index-CPjiwba7.js)
Dockerfile still uses pre-built dist/ so HF build = ~20 sec

Deployment strategy: nginx-only Docker image (no node/npm on HF)
- FROM nginx:1.25-alpine only
- COPY dist/ β†’ nginx serves it
- Build time on HF free tier: ~20 seconds

README.md CHANGED
@@ -15,12 +15,8 @@ short_description: GLB 3D Animation Studio β€” Three.js + React
15
  Professional browser-based 3D animation studio for GLB/GLTF models.
16
 
17
  ## Features
18
- - GLB/GLTF model loading, transform controls, keyframe animation
19
- - Multi-camera system with fly controls and camera path animation
20
- - Cannon.js physics engine (gravity, impulse, damping)
21
- - AI scene controller via OpenRouter (free models, auto-retry)
22
- - Undo/redo, project save/load, material editor, clean render mode
23
- - Video export (WebM) + PNG sequence, mobile optimised
24
-
25
- ## Tech Stack
26
- React 18 Β· Vite Β· Three.js Β· React Three Fiber Β· Zustand Β· nginx Β· Docker
 
15
  Professional browser-based 3D animation studio for GLB/GLTF models.
16
 
17
  ## Features
18
+ - GLB/GLTF loading Β· Transform controls Β· Keyframe animation
19
+ - Multi-camera system with fly controls
20
+ - Cannon.js physics Β· AI scene controller
21
+ - Clean render mode Β· Video/PNG export
22
+ - Mobile optimised
 
 
 
 
dist/assets/{index-BMPzxcxL.js β†’ index-CPjiwba7.js} RENAMED
The diff for this file is too large to render. See raw diff
 
dist/index.html CHANGED
@@ -11,7 +11,7 @@
11
  </style>
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
  <link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
14
- <script type="module" crossorigin src="/assets/index-BMPzxcxL.js"></script>
15
  <link rel="modulepreload" crossorigin href="/assets/three-BDVXI0HY.js">
16
  <link rel="modulepreload" crossorigin href="/assets/r3f-D7cvq2vh.js">
17
  <link rel="modulepreload" crossorigin href="/assets/state-D3gY4USI.js">
 
11
  </style>
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
  <link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
14
+ <script type="module" crossorigin src="/assets/index-CPjiwba7.js"></script>
15
  <link rel="modulepreload" crossorigin href="/assets/three-BDVXI0HY.js">
16
  <link rel="modulepreload" crossorigin href="/assets/r3f-D7cvq2vh.js">
17
  <link rel="modulepreload" crossorigin href="/assets/state-D3gY4USI.js">
nginx.conf CHANGED
@@ -1,49 +1,30 @@
1
- # ═══════════════════════════════════════════════════════════════════════════════
2
- # nginx config for GLB Animation Studio on Hugging Face Spaces
3
- # Listening on port 7860 (HF Spaces requirement)
4
- # ═══════════════════════════════════════════════════════════════════════════════
5
-
6
  server {
7
  listen 7860;
8
  server_name _;
9
  root /usr/share/nginx/html;
10
  index index.html;
11
 
12
- # ── Gzip compression ────────────────────────────────────────────────────
13
  gzip on;
14
  gzip_vary on;
15
  gzip_min_length 1024;
16
  gzip_proxied any;
17
  gzip_comp_level 6;
18
  gzip_types
19
- text/plain
20
- text/css
21
- text/javascript
22
- application/javascript
23
- application/json
24
- application/wasm
25
- model/gltf+json
26
- model/gltf-binary
27
- image/svg+xml
28
- font/woff
29
- font/woff2;
30
-
31
- # ── Security headers ────────────────────────────────────────────────────
32
- add_header X-Content-Type-Options "nosniff" always;
33
- add_header X-Frame-Options "SAMEORIGIN" always;
34
- add_header X-XSS-Protection "1; mode=block" always;
35
- add_header Referrer-Policy "strict-origin-when-cross-origin" always;
36
 
37
- # SharedArrayBuffer support (required for FFmpeg.wasm / WebCodecs)
38
- add_header Cross-Origin-Opener-Policy "same-origin" always;
39
- add_header Cross-Origin-Embedder-Policy "require-corp" always;
 
40
 
41
- # ── JavaScript / CSS / fonts β€” immutable cache ──────────────────────────
42
  location ~* \.(js|css|woff2?|ttf|otf|eot)$ {
43
  expires 1y;
44
  add_header Cache-Control "public, immutable";
45
- add_header Cross-Origin-Opener-Policy "same-origin" always;
46
- add_header Cross-Origin-Embedder-Policy "require-corp" always;
47
  }
48
 
49
  # Images
@@ -52,7 +33,7 @@ server {
52
  add_header Cache-Control "public";
53
  }
54
 
55
- # GLB / GLTF / HDR / KTX2 3D assets
56
  location ~* \.(glb|gltf|bin|hdr|exr|ktx2)$ {
57
  expires 7d;
58
  add_header Cache-Control "public";
@@ -64,25 +45,14 @@ server {
64
  default_type application/wasm;
65
  expires 7d;
66
  add_header Cache-Control "public";
67
- add_header Cross-Origin-Opener-Policy "same-origin" always;
68
- add_header Cross-Origin-Embedder-Policy "require-corp" always;
69
  }
70
 
71
- # ── SPA fallback β€” all routes go to index.html ─────────────────────────
72
  location / {
73
  try_files $uri $uri/ /index.html;
74
  add_header Cache-Control "no-cache, no-store, must-revalidate";
75
- add_header Cross-Origin-Opener-Policy "same-origin" always;
76
- add_header Cross-Origin-Embedder-Policy "require-corp" always;
77
  }
78
 
79
  error_page 404 /index.html;
80
-
81
- # Large GLB file upload support (up to 200 MB)
82
  client_max_body_size 200M;
83
-
84
- # Timeouts
85
- proxy_read_timeout 300s;
86
- proxy_connect_timeout 60s;
87
- send_timeout 300s;
88
  }
 
 
 
 
 
 
1
  server {
2
  listen 7860;
3
  server_name _;
4
  root /usr/share/nginx/html;
5
  index index.html;
6
 
7
+ # Gzip
8
  gzip on;
9
  gzip_vary on;
10
  gzip_min_length 1024;
11
  gzip_proxied any;
12
  gzip_comp_level 6;
13
  gzip_types
14
+ text/plain text/css text/javascript
15
+ application/javascript application/json
16
+ application/wasm model/gltf+json model/gltf-binary
17
+ image/svg+xml font/woff font/woff2;
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ # Security (no COEP - would block cross-origin GLB/image loading)
20
+ add_header X-Content-Type-Options "nosniff" always;
21
+ add_header X-Frame-Options "SAMEORIGIN" always;
22
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
23
 
24
+ # JS/CSS - immutable cache
25
  location ~* \.(js|css|woff2?|ttf|otf|eot)$ {
26
  expires 1y;
27
  add_header Cache-Control "public, immutable";
 
 
28
  }
29
 
30
  # Images
 
33
  add_header Cache-Control "public";
34
  }
35
 
36
+ # 3D assets - allow cross-origin
37
  location ~* \.(glb|gltf|bin|hdr|exr|ktx2)$ {
38
  expires 7d;
39
  add_header Cache-Control "public";
 
45
  default_type application/wasm;
46
  expires 7d;
47
  add_header Cache-Control "public";
 
 
48
  }
49
 
50
+ # SPA fallback
51
  location / {
52
  try_files $uri $uri/ /index.html;
53
  add_header Cache-Control "no-cache, no-store, must-revalidate";
 
 
54
  }
55
 
56
  error_page 404 /index.html;
 
 
57
  client_max_body_size 200M;
 
 
 
 
 
58
  }
src/components/PropertiesPanel.jsx CHANGED
@@ -286,7 +286,7 @@ export default function PropertiesPanel() {
286
  {[['Cast Shadow','castShadow'],['Receive Shadow','receiveShadow']].map(([lbl,key])=>(
287
  <div key={key} style={{display:'flex',justifyContent:'space-between',alignItems:'center'}}>
288
  <span style={{fontSize:11,color:'var(--text1)'}}>{lbl}</span>
289
- <button onClick={()=>updateModelTransform(model.id,key,!model[key]??true)} style={{
290
  width:36,height:20,borderRadius:10,cursor:'pointer',position:'relative',
291
  background:(model[key]??true)?'var(--accent)':'var(--bg4)',border:'none',
292
  transition:'background 0.2s',
 
286
  {[['Cast Shadow','castShadow'],['Receive Shadow','receiveShadow']].map(([lbl,key])=>(
287
  <div key={key} style={{display:'flex',justifyContent:'space-between',alignItems:'center'}}>
288
  <span style={{fontSize:11,color:'var(--text1)'}}>{lbl}</span>
289
+ <button onClick={()=>updateModelTransform(model.id,key,!(model[key]??true))} style={{
290
  width:36,height:20,borderRadius:10,cursor:'pointer',position:'relative',
291
  background:(model[key]??true)?'var(--accent)':'var(--bg4)',border:'none',
292
  transition:'background 0.2s',