| # Hugging Face Spaces - Full Stack Deployment | |
| # Serves both React frontend and FastAPI backend | |
| FROM node:18-slim AS frontend-builder | |
| WORKDIR /frontend | |
| COPY frontend/package*.json ./ | |
| RUN npm ci --legacy-peer-deps | |
| COPY frontend/ ./ | |
| ENV CI=false | |
| RUN npm run build | |
| # Production image | |
| FROM python:3.11-slim | |
| # Create non-root user (required by HF Spaces) | |
| RUN useradd -m -u 1000 user | |
| WORKDIR /app | |
| # Install system dependencies | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| gcc g++ && \ | |
| rm -rf /var/lib/apt/lists/* | |
| # Install Python dependencies | |
| COPY backend/requirements.txt . | |
| RUN pip install --no-cache-dir -r requirements.txt | |
| # Pre-download the sentence transformer model into the image | |
| # so startup doesn't require network access to huggingface.co | |
| RUN python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2')" | |
| # Copy backend | |
| COPY --chown=user backend/ /app/backend/ | |
| # Copy frontend build | |
| COPY --from=frontend-builder --chown=user /frontend/build /app/frontend/build | |
| # Copy app.py (HF Spaces entry point) | |
| COPY --chown=user app.py /app/ | |
| # Create directories for runtime data | |
| RUN mkdir -p /app/precomputed_data /app/cache && chown -R user:user /app/precomputed_data /app/cache | |
| # Copy precomputed data if available (metadata only in repo) | |
| # Directory contains: .gitkeep, metadata_v1.json, and README.txt | |
| # These files ensure the directory is never empty, so COPY will always succeed | |
| COPY --chown=user precomputed_data/ /app/precomputed_data/ | |
| # Switch to non-root user | |
| USER user | |
| ENV PYTHONUNBUFFERED=1 | |
| ENV PORT=7860 | |
| ENV ALLOW_ALL_ORIGINS=true | |
| ENV SAMPLE_SIZE=50000 | |
| ENV HF_PRECOMPUTED_DATASET=modelbiome/hf-viz-precomputed | |
| WORKDIR /app | |
| EXPOSE 7860 | |
| CMD ["python", "app.py"] | |