Back to PolicyTrace

PolicyTrace implementation note A

Deploying PolicyTrace with GitHub, Docker, and Hugging Face Spaces

A practical deployment walkthrough for packaging a FastAPI backend and React review UI into one Docker app, then running it as a public Hugging Face Space.

Deployment Map

PolicyTrace ships as a single container: GitHub holds the source, Docker builds the React UI and Python backend, FastAPI serves both API and app, and Hugging Face Spaces runs the container on port 7860.

Source and configuration Container build Runtime service Production hardening
Source handoff GitHub repository
Application sourceFastAPI backend, React UI, prompts, settings, tests, synthetic sample data.github.com/AItoolstack/ai-policytrace
Deployment notesThe repo documents local Docker testing and Hugging Face Docker Space setup.docs/hugging-face.md
No CI/CD claimThe current repo does not include root GitHub Actions workflows, so automation is future hardening.no .github/workflows
Docker build Two-stage package
Node UI stageInstalls UI dependencies and builds the Vite React review dashboard.node:20-slim -> npm ci -> npm run build
Python app stageInstalls backend requirements and downloads the small spaCy English model.python:3.11-slim -> requirements.txt -> en_core_web_sm
Static handoffThe compiled UI is copied into the Python image so one service can serve the whole app.ui/dist
Runtime app FastAPI plus React
API serviceFastAPI handles processing, sessions, PDF serving, review updates, and health checks./api/process, /api/session, /api/health
SPA hostingFastAPI mounts static assets and falls back to index.html for React routes./assets + /{full_path:path}
Port contractThe container starts uvicorn on the host and uses the Space-friendly default port.0.0.0.0:${PORT:-7860}
Public demo Hugging Face Space
Docker SpaceThe app is deployed as a Docker Space rather than a pure Gradio or Streamlit app.SDK: Docker, Port: 7860
SecretsThe Groq key belongs in Space Secrets, with optional model override variables.GROQ_API_KEY
Demo storageDefault Space storage is ephemeral, so session artifacts are fine for a demo, not durable review history.output/sessions

Current implementation boundary

This is a deployable public demo shape. It proves packaging and hosting, but it does not claim production controls such as authentication, durable storage, audit logging, monitoring, or CI/CD gates.

Why Docker is the right choice here

PolicyTrace is not only a notebook or a single UI framework. It has a Python API, a compiled React frontend, PDF dependencies, spaCy model setup, and runtime secrets.

Core thesis

Deployment is part of the architecture, not a final upload step.

PolicyTrace is built around a backend extraction pipeline and a frontend review workflow. That means deployment has to preserve both halves of the system: the FastAPI service that processes documents and the React interface reviewers use to inspect evidence.

The current repo solves that with a single Docker image. The image builds the UI, installs the backend, copies the compiled frontend into the app, and starts FastAPI on a port that Hugging Face Spaces can run.

The demo is public, but the architecture is still explicit.

A useful portfolio deployment should make the running system easy to try while also making its limits visible. That is better than pretending a public demo is already an enterprise platform.

  • 1
    GitHub stores the source, docs, prompts, settings, Dockerfile, and synthetic sample data.
  • 2
    Docker packages backend and frontend into one runtime service.
  • 3
    Hugging Face Spaces provides public demo hosting with secrets and a container port contract.

Why Docker

PolicyTrace is not a pure Gradio or Streamlit app.

Hugging Face Spaces is often associated with Gradio or Streamlit demos, but PolicyTrace is a FastAPI plus React application. The backend owns PDF processing, model calls, arbitration, provenance, sessions, and review endpoints. The frontend owns the upload flow and split-screen review UI.

Docker gives that shape a clean contract. Instead of trying to squeeze the project into a single notebook-style runtime, the container can install system packages, Python dependencies, the spaCy model, and the compiled Vite app in a predictable build.

APIBackend stays real

FastAPI remains the application boundary for upload, extraction, PDF serving, and review state.

UIFrontend stays real

React, Vite, Tailwind, react-pdf, and Zustand can be built as the actual review dashboard.

ENVSecrets stay outside code

The Groq API key is supplied through environment variables or Hugging Face Space Secrets.

PORTRuntime stays simple

The app exposes one HTTP service on port 7860 for the public demo.

Dockerfile shape

The image has a build stage and an app stage.

The Dockerfile starts with a Node stage. It copies the UI package files, runs a clean install, copies the UI source, and builds the Vite app. The second stage uses Python 3.11, installs backend dependencies, downloads the small spaCy model, copies the project files, and brings in the compiled UI.

Deployment contractDockerfile
FROM node:20-slim AS ui-build
RUN npm ci
RUN npm run build

FROM python:3.11-slim AS app
RUN pip install --no-cache-dir -r requirements.txt
RUN python -m spacy download en_core_web_sm
COPY --from=ui-build /app/ui/dist ./ui/dist
CMD uvicorn api:app --app-dir src --host 0.0.0.0 --port ${PORT:-7860}

That sequence matters because the public demo is still the real application. The reviewer is not seeing a separate mock frontend. FastAPI serves the compiled UI and the API from the same deployed service.

Serving model

FastAPI serves the API and the React app.

In local development, Vite runs on port 5173 and proxies API calls to FastAPI on port 8000. In Docker and Hugging Face, the built React app lives in ui/dist. FastAPI mounts the static assets and falls back to index.html so React routes keep working after refresh.

This keeps the public demo easy to run: one container, one port, one service. It also makes the boundary clear. API routes still live under /api/*, while the frontend is just the compiled app being served by FastAPI.

Local development and demo deployment use different serving modes.

That is normal. Local development optimizes for fast frontend iteration. The deployed container optimizes for a simple public runtime.

  • 1
    Local backend: uvicorn api:app --app-dir src --reload --port 8000
  • 2
    Local frontend: npm run dev on Vite port 5173 with an /api proxy.
  • 3
    Docker runtime: FastAPI serves both /api and the compiled React app on port 7860.

Hugging Face Space

The Space setup is intentionally small.

The Hugging Face deployment uses a Docker Space. The important settings are simple: Docker SDK, port 7860, and GROQ_API_KEY as a Space Secret. Optional variables can override the extraction and classifier models.

For a public AI Tool Stack demo, the sample data should stay synthetic. PolicyTrace can process sensitive insurance documents, but the public Space should be treated as a portfolio demo unless stronger access, retention, and storage controls are added.

Space settingsHugging Face
SDK: Docker
Port: 7860

Required Secret:
GROQ_API_KEY=your_groq_key

Optional Variables:
GROQ_MODEL=meta-llama/llama-4-scout-17b-16e-instruct
GROQ_CLASSIFIER_MODEL=llama-3.1-8b-instant

Production honesty

A public Space is not the same thing as production readiness.

This is where the post should be careful. The Hugging Face Space is valuable because it makes the workflow easy to try. It is not a production insurance system. The current app stores sessions under output/sessions, and default Space storage can disappear when the Space restarts.

That is acceptable for a public demo with synthetic data. For a real review workflow, the deployment architecture would need durable storage, identity, audit logging, monitoring, and operational controls.

What the current repo proves

  • 1
    A complete Docker packaging path for FastAPI plus React.
  • 2
    A Hugging Face Docker Space compatible runtime on port 7860.
  • 3
    A public demo path using synthetic PDFs and environment-based secrets.

What production would add

  • 1
    Authentication, RBAC, tenant separation, and stronger upload controls.
  • 2
    Durable session storage, object storage, retention policies, and audit logs.
  • 3
    CI/CD gates, evaluation checks, monitoring, queue workers, cost controls, and runbooks.

Reusable pattern

Ship the demo in the shape of the real system.

The useful lesson is not that every AI app belongs on Hugging Face Spaces. The lesson is that a demo should preserve the architecture you want people to understand. In PolicyTrace, that means preserving the backend, frontend, evidence workflow, review loop, and deployment boundary.

GitHub makes the project inspectable. Docker makes it runnable. Hugging Face Spaces makes it easy to try. The production gap remains visible, which is exactly the point of a practical AI engineering project.

Next implementation note

What I would improve before taking PolicyTrace to production.

The next post should turn the hardening notes into a production roadmap: storage, auth, audit logs, queues, monitoring, evaluation, and operational ownership.