GLB Studio Deploy commited on
Commit
fd7b9b7
·
1 Parent(s): f0661a2

fix: 2-stage Dockerfile (npm build on HF), remove dist/ from repo

Browse files

- Dockerfile: node:20-alpine builds app, nginx:1.25-alpine serves it
- dist/ removed from git tracking (built on HF during Docker build)
- .gitattributes removed (was causing LFS hook confusion)
- .gitignore: dist/ excluded again

.gitattributes DELETED
@@ -1,10 +0,0 @@
1
- # Tell HF/git these are regular files, NOT LFS objects
2
- dist/assets/*.js binary
3
- dist/assets/*.css binary
4
- dist/index.html text
5
- *.jsx text
6
- *.js text
7
- *.json text
8
- *.css text
9
- *.md text
10
- *.html text
 
 
 
 
 
 
 
 
 
 
 
.gitignore CHANGED
@@ -3,8 +3,8 @@ node_modules/
3
  .pnp
4
  .pnp.js
5
 
6
- # Build output - dist/ is committed for HF Spaces
7
- #dist/
8
  build/
9
 
10
  # Environment variables
 
3
  .pnp
4
  .pnp.js
5
 
6
+ # Build output
7
+ dist/
8
  build/
9
 
10
  # Environment variables
Dockerfile CHANGED
@@ -1,37 +1,21 @@
1
- # GLB Animation Studio — Hugging Face Spaces
2
- # Pre-built dist/ is committed — this just serves it with nginx
3
- # Build time: < 30 seconds (no npm install needed)
 
 
 
4
 
5
  FROM nginx:1.25-alpine
6
-
7
- # Non-root user (HF Spaces requirement: uid 1000)
8
- RUN addgroup -g 1000 appgroup && \
9
- adduser -u 1000 -G appgroup -s /bin/sh -D appuser
10
-
11
- # Copy pre-built React app
12
  RUN rm -rf /usr/share/nginx/html/*
13
- COPY dist/ /usr/share/nginx/html/
14
  COPY nginx.conf /etc/nginx/conf.d/default.conf
15
-
16
- # Fix permissions for non-root nginx
17
- RUN mkdir -p /var/cache/nginx/client_temp \
18
- /var/cache/nginx/proxy_temp \
19
- /var/cache/nginx/fastcgi_temp \
20
- /var/cache/nginx/uwsgi_temp \
21
  /var/cache/nginx/scgi_temp && \
22
  touch /var/run/nginx.pid && \
23
- chown -R appuser:appgroup \
24
- /var/cache/nginx \
25
- /var/run/nginx.pid \
26
- /var/log/nginx \
27
- /usr/share/nginx/html \
28
- /etc/nginx/conf.d
29
-
30
  USER appuser
31
  EXPOSE 7860
32
-
33
- HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 \
34
- CMD wget -qO- http://localhost:7860/ || exit 1
35
-
36
  CMD ["nginx", "-g", "daemon off;"]
37
-
 
1
+ FROM node:20-alpine AS builder
2
+ WORKDIR /app
3
+ COPY package.json ./
4
+ RUN npm install --legacy-peer-deps
5
+ COPY . .
6
+ RUN npm run build
7
 
8
  FROM nginx:1.25-alpine
9
+ RUN addgroup -g 1000 appgroup && adduser -u 1000 -G appgroup -s /bin/sh -D appuser
 
 
 
 
 
10
  RUN rm -rf /usr/share/nginx/html/*
11
+ COPY --from=builder /app/dist /usr/share/nginx/html
12
  COPY nginx.conf /etc/nginx/conf.d/default.conf
13
+ RUN mkdir -p /var/cache/nginx/client_temp /var/cache/nginx/proxy_temp \
14
+ /var/cache/nginx/fastcgi_temp /var/cache/nginx/uwsgi_temp \
 
 
 
 
15
  /var/cache/nginx/scgi_temp && \
16
  touch /var/run/nginx.pid && \
17
+ chown -R appuser:appgroup /var/cache/nginx /var/run/nginx.pid \
18
+ /var/log/nginx /usr/share/nginx/html /etc/nginx/conf.d
 
 
 
 
 
19
  USER appuser
20
  EXPOSE 7860
 
 
 
 
21
  CMD ["nginx", "-g", "daemon off;"]
 
dist/assets/RGBELoader-BuzHbjmU.js DELETED
@@ -1,5 +0,0 @@
1
- import{aE as z,aF as G,aG as I,aH as B,aQ as Y,ab as U}from"./three-BDVXI0HY.js";class O extends z{constructor(g){super(g),this.type=G}parse(g){const _=function(r,e){switch(r){case 1:throw new Error("THREE.RGBELoader: Read Error: "+(e||""));case 2:throw new Error("THREE.RGBELoader: Write Error: "+(e||""));case 3:throw new Error("THREE.RGBELoader: Bad File Format: "+(e||""));default:case 4:throw new Error("THREE.RGBELoader: Memory Error: "+(e||""))}},V=`
2
- `,D=function(r,e,o){e=e||1024;let s=r.pos,i=-1,a=0,l="",t=String.fromCharCode.apply(null,new Uint16Array(r.subarray(s,s+128)));for(;0>(i=t.indexOf(V))&&a<e&&s<r.byteLength;)l+=t,a+=t.length,s+=128,t+=String.fromCharCode.apply(null,new Uint16Array(r.subarray(s,s+128)));return-1<i?(r.pos+=a+i+1,l+t.slice(0,i)):!1},N=function(r){const e=/^#\?(\S+)/,o=/^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/,n=/^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/,s=/^\s*FORMAT=(\S+)\s*$/,i=/^\s*\-Y\s+(\d+)\s+\+X\s+(\d+)\s*$/,a={valid:0,string:"",comments:"",programtype:"RGBE",format:"",gamma:1,exposure:1,width:0,height:0};let l,t;for((r.pos>=r.byteLength||!(l=D(r)))&&_(1,"no header found"),(t=l.match(e))||_(3,"bad initial token"),a.valid|=1,a.programtype=t[1],a.string+=l+`
3
- `;l=D(r),l!==!1;){if(a.string+=l+`
4
- `,l.charAt(0)==="#"){a.comments+=l+`
5
- `;continue}if((t=l.match(o))&&(a.gamma=parseFloat(t[1])),(t=l.match(n))&&(a.exposure=parseFloat(t[1])),(t=l.match(s))&&(a.valid|=2,a.format=t[1]),(t=l.match(i))&&(a.valid|=4,a.height=parseInt(t[1],10),a.width=parseInt(t[2],10)),a.valid&2&&a.valid&4)break}return a.valid&2||_(3,"missing format specifier"),a.valid&4||_(3,"missing image size specifier"),a},v=function(r,e,o){const n=e;if(n<8||n>32767||r[0]!==2||r[1]!==2||r[2]&128)return new Uint8Array(r);n!==(r[2]<<8|r[3])&&_(3,"wrong scanline width");const s=new Uint8Array(4*e*o);s.length||_(4,"unable to allocate buffer space");let i=0,a=0;const l=4*n,t=new Uint8Array(4),E=new Uint8Array(l);let f=o;for(;f>0&&a<r.byteLength;){a+4>r.byteLength&&_(1),t[0]=r[a++],t[1]=r[a++],t[2]=r[a++],t[3]=r[a++],(t[0]!=2||t[1]!=2||(t[2]<<8|t[3])!=n)&&_(3,"bad rgbe scanline format");let R=0,c;for(;R<l&&a<r.byteLength;){c=r[a++];const h=c>128;if(h&&(c-=128),(c===0||R+c>l)&&_(3,"bad scanline data"),h){const m=r[a++];for(let u=0;u<c;u++)E[R++]=m}else E.set(r.subarray(a,a+c),R),R+=c,a+=c}const P=n;for(let h=0;h<P;h++){let m=0;s[i]=E[h+m],m+=n,s[i+1]=E[h+m],m+=n,s[i+2]=E[h+m],m+=n,s[i+3]=E[h+m],i+=4}f--}return s},x=function(r,e,o,n){const s=r[e+3],i=Math.pow(2,s-128)/255;o[n+0]=r[e+0]*i,o[n+1]=r[e+1]*i,o[n+2]=r[e+2]*i,o[n+3]=1},C=function(r,e,o,n){const s=r[e+3],i=Math.pow(2,s-128)/255;o[n+0]=B.toHalfFloat(Math.min(r[e+0]*i,65504)),o[n+1]=B.toHalfFloat(Math.min(r[e+1]*i,65504)),o[n+2]=B.toHalfFloat(Math.min(r[e+2]*i,65504)),o[n+3]=B.toHalfFloat(1)},w=new Uint8Array(g);w.pos=0;const d=N(w),k=d.width,H=d.height,y=v(w.subarray(w.pos),k,H);let L,F,p;switch(this.type){case I:p=y.length/4;const r=new Float32Array(p*4);for(let o=0;o<p;o++)x(y,o*4,r,o*4);L=r,F=I;break;case G:p=y.length/4;const e=new Uint16Array(p*4);for(let o=0;o<p;o++)C(y,o*4,e,o*4);L=e,F=G;break;default:throw new Error("THREE.RGBELoader: Unsupported type: "+this.type)}return{width:k,height:H,data:L,header:d.string,gamma:d.gamma,exposure:d.exposure,type:F}}setDataType(g){return this.type=g,this}load(g,b,S,A){function M(_,T){switch(_.type){case I:case G:_.colorSpace=Y,_.minFilter=U,_.magFilter=U,_.generateMipmaps=!1,_.flipY=!0;break}b&&b(_,T)}return super.load(g,M,S,A)}}export{O as RGBELoader};
 
 
 
 
 
 
dist/assets/index-CPjiwba7.js DELETED
The diff for this file is too large to render. See raw diff
 
dist/assets/index-DqG64RR3.css DELETED
@@ -1 +0,0 @@
1
- @import"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Syne:wght@700;800&display=swap";:root{--bg0: #0c0c10;--bg1: #111116;--bg2: #17171e;--bg3: #1e1e28;--bg4: #252532;--border: rgba(255,255,255,.07);--border-hi: rgba(255,255,255,.14);--accent: #4f8eff;--accent2: #7c3aed;--accent3: #06d6a0;--warn: #f59e0b;--danger: #ef4444;--text0: #f0f0f8;--text1: #a0a0b8;--text2: #606078;--text3: #383848;--radius-sm: 4px;--radius: 8px;--radius-lg: 12px;--font-ui: "Inter", system-ui, sans-serif;--font-mono: "JetBrains Mono", monospace;--font-brand: "Syne", sans-serif;--shadow-sm: 0 1px 3px rgba(0,0,0,.4);--shadow: 0 4px 16px rgba(0,0,0,.5);--shadow-lg: 0 8px 32px rgba(0,0,0,.7);--glow: 0 0 20px rgba(79,142,255,.25);--glow-green: 0 0 20px rgba(6,214,160,.25)}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body,#root{width:100%;height:100%;overflow:hidden;background:var(--bg0);color:var(--text0);font-family:var(--font-ui);font-size:13px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}::-webkit-scrollbar{width:4px;height:4px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bg4);border-radius:2px}::-webkit-scrollbar-thumb:hover{background:var(--text3)}input[type=range]{-webkit-appearance:none;height:3px;background:var(--bg4);border-radius:2px;cursor:pointer;width:100%}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:13px;height:13px;background:var(--accent);border-radius:50%;box-shadow:0 0 0 3px #4f8eff33;transition:transform .15s}input[type=range]::-webkit-slider-thumb:hover{transform:scale(1.2)}input[type=range]:focus{outline:none}input[type=number],input[type=text],select,textarea{background:var(--bg1);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text0);font-family:var(--font-mono);font-size:11px;padding:5px 7px;outline:none;transition:border-color .15s,box-shadow .15s;width:100%}input[type=number]:focus,input[type=text]:focus,select:focus{border-color:var(--accent);box-shadow:0 0 0 2px #4f8eff26}button{font-family:var(--font-ui);cursor:pointer;outline:none;border:none}*{-webkit-tap-highlight-color:transparent}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.4}}@keyframes fadeUp{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}
 
 
dist/assets/r3f-D7cvq2vh.js DELETED
The diff for this file is too large to render. See raw diff
 
dist/assets/react-vendor-BhNjn4yn.js DELETED
@@ -1 +0,0 @@
1
- import"./r3f-D7cvq2vh.js";
 
 
dist/assets/state-D3gY4USI.js DELETED
@@ -1,17 +0,0 @@
1
- import{r as _,g as R,R as x}from"./r3f-D7cvq2vh.js";const V={},y=e=>{let t;const n=new Set,o=(s,l)=>{const c=typeof s=="function"?s(t):s;if(!Object.is(c,t)){const i=t;t=l??(typeof c!="object"||c===null)?c:Object.assign({},t,c),n.forEach(a=>a(t,i))}},r=()=>t,S={setState:o,getState:r,getInitialState:()=>m,subscribe:s=>(n.add(s),()=>n.delete(s)),destroy:()=>{(V?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),n.clear()}},m=t=e(o,r,S);return S},O=e=>e?y(e):y;var w={exports:{}},D={},$={exports:{}},j={};/**
2
- * @license React
3
- * use-sync-external-store-shim.production.js
4
- *
5
- * Copyright (c) Meta Platforms, Inc. and affiliates.
6
- *
7
- * This source code is licensed under the MIT license found in the
8
- * LICENSE file in the root directory of this source tree.
9
- */var d=_;function z(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var C=typeof Object.is=="function"?Object.is:z,T=d.useState,W=d.useEffect,A=d.useLayoutEffect,P=d.useDebugValue;function F(e,t){var n=t(),o=T({inst:{value:n,getSnapshot:t}}),r=o[0].inst,u=o[1];return A(function(){r.value=n,r.getSnapshot=t,p(r)&&u({inst:r})},[e,n,t]),W(function(){return p(r)&&u({inst:r}),e(function(){p(r)&&u({inst:r})})},[e]),P(n),n}function p(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!C(e,n)}catch{return!0}}function M(e,t){return t()}var G=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?M:F;j.useSyncExternalStore=d.useSyncExternalStore!==void 0?d.useSyncExternalStore:G;$.exports=j;var L=$.exports;/**
10
- * @license React
11
- * use-sync-external-store-shim/with-selector.production.js
12
- *
13
- * Copyright (c) Meta Platforms, Inc. and affiliates.
14
- *
15
- * This source code is licensed under the MIT license found in the
16
- * LICENSE file in the root directory of this source tree.
17
- */var b=_,U=L;function k(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var B=typeof Object.is=="function"?Object.is:k,H=U.useSyncExternalStore,J=b.useRef,K=b.useEffect,N=b.useMemo,Q=b.useDebugValue;D.useSyncExternalStoreWithSelector=function(e,t,n,o,r){var u=J(null);if(u.current===null){var f={hasValue:!1,value:null};u.current=f}else f=u.current;u=N(function(){function S(i){if(!m){if(m=!0,s=i,i=o(i),r!==void 0&&f.hasValue){var a=f.value;if(r(a,i))return l=a}return l=i}if(a=l,B(s,i))return a;var E=o(i);return r!==void 0&&r(a,E)?(s=i,a):(s=i,l=E)}var m=!1,s,l,c=n===void 0?null:n;return[function(){return S(t())},c===null?void 0:function(){return S(c())}]},[t,n,o,r]);var v=H(e,u[0],u[1]);return K(function(){f.hasValue=!0,f.value=v},[v]),Q(v),v};w.exports=D;var X=w.exports;const Y=R(X),I={},{useDebugValue:Z}=x,{useSyncExternalStoreWithSelector:q}=Y;let g=!1;const ee=e=>e;function te(e,t=ee,n){(I?"production":void 0)!=="production"&&n&&!g&&(console.warn("[DEPRECATED] Use `createWithEqualityFn` instead of `create` or use `useStoreWithEqualityFn` instead of `useStore`. They can be imported from 'zustand/traditional'. https://github.com/pmndrs/zustand/discussions/1937"),g=!0);const o=q(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,n);return Z(o),o}const h=e=>{(I?"production":void 0)!=="production"&&typeof e!="function"&&console.warn("[DEPRECATED] Passing a vanilla store will be unsupported in a future version. Instead use `import { useStore } from 'zustand'`.");const t=typeof e=="function"?O(e):e,n=(o,r)=>te(t,o,r);return Object.assign(n,t),n},re=e=>e?h(e):h;export{re as c};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dist/assets/three-BDVXI0HY.js DELETED
The diff for this file is too large to render. See raw diff
 
dist/index.html DELETED
@@ -1,23 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
6
- <title>GLB Animation Studio</title>
7
- <style>
8
- * { margin: 0; padding: 0; box-sizing: border-box; }
9
- body { background: #0a0a0f; color: #fff; font-family: 'Space Mono', monospace; overflow: hidden; }
10
- #root { width: 100vw; height: 100vh; }
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">
18
- <link rel="stylesheet" crossorigin href="/assets/index-DqG64RR3.css">
19
- </head>
20
- <body>
21
- <div id="root"></div>
22
- </body>
23
- </html>