# 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"]