RAGELITE / rules.md
triflix
initial: automAIta boilerplate (FastAPI + React PWA, single-port HF Space)
a6229e1

Rules

Contract for every contributor β€” human or AI β€” working in this repo.

Project Overview

automAIta is a deployment-ready boilerplate for HuggingFace Spaces.

  • Backend: FastAPI (MVC) managed by uv, defined in backend/pyproject.toml.
  • Frontend: Vite + React + TypeScript + Tailwind + PWA. No app frameworks.
  • Container: one Docker image, single port 7860. FastAPI serves the built React bundle as static files at / and the API under /api/*.
  • Deploy: GitHub main β†’ .github/workflows/sync-to-hf.yml mirrors the repo to a HuggingFace Space, which rebuilds automatically.

Scope & Goals

  • Stay a boilerplate. The only "feature" is App.tsx proving the /api/status round-trip works.
  • New projects fork this repo and fill it in β€” they should not have to rewire Docker, ports, the workflow, or the layout.

Coding Rules

  • No hardcoded values. Backend goes through app/core/config.py (env prefix AUTOMAITA_). Frontend uses Vite env vars (import.meta.env.VITE_*) when needed.
  • Backend MVC layering:
    • controllers/ β€” APIRouters only. Thin: parse, call a service, return.
    • services/ β€” business logic. No FastAPI imports.
    • schemas/ β€” pydantic request/response DTOs.
    • models/ β€” pydantic domain models.
    • core/ β€” config, lifespan, anything cross-cutting.
  • Frontend:
    • TypeScript strict is on. Don't downgrade it.
    • Tailwind is the only styling system. No Material UI, Chakra, Mantine, shadcn, etc., without explicit approval.
    • No state libraries (Redux/Zustand/Jotai) or routers (React Router/TanStack Router) until the project actually needs one.
    • All API calls go through src/api/client.ts.
  • Single-port contract. The container exposes only 7860. Don't introduce nginx, supervisord, or a second process. FastAPI mounts the static SPA itself.
  • Same-origin in prod. API client uses relative URLs (/api/...). Don't hardcode http://localhost:8000 or any HF URL.

Agent Behavior Rules

  • Never bypass the frontend/ ↔ backend/ boundary β€” they communicate over HTTP, not shared imports.
  • Never break the single-port contract or the non-root UID 1000 Dockerfile.
  • Never edit .github/workflows/sync-to-hf.yml to add deploy logic that belongs inside the container β€” the workflow's job is mirroring, nothing else.
  • Preserve the Dockerfile's two-stage shape (frontend-build β†’ runtime). New build steps go inside an existing stage; don't add stages without need.
  • When adding a backend route, create a controller in app/controllers/, register it in app/main.py, and put the logic in app/services/.

Workflow Rules

  • Local dev (split):
    • Backend: cd backend && uv sync && uv run uvicorn app.main:app --reload --port 8000
    • Frontend: cd frontend && npm install && npm run dev (proxy handles /api).
  • Container parity (run what HF runs): docker build -t automaita . && docker run --rm -p 7860:7860 automaita β†’ http://localhost:7860.
  • Deploy: push to GitHub main. Required repo secrets: HF_TOKEN, HF_USER, HF_SPACE_NAME.
  • Don't push directly to the HF Space repo β€” let the action do it, otherwise you fork history.

Conventions

  • Env var prefix: AUTOMAITA_ (backend), VITE_ (frontend).
  • API prefix: all backend routes live under /api/*. The PWA service worker explicitly excludes /api/* from navigation fallback.
  • Filenames:
    • Backend: snake_case modules, controllers suffixed _controller.py, services suffixed _service.py.
    • Frontend: PascalCase for components (App.tsx), camelCase for utilities (client.ts).
  • Health: /api/health is the simplest possible OK probe; /api/status is the rich one (used by the SPA on mount).
  • Python: 3.12+, ruff for linting (config in pyproject.toml).
  • Node: 20+ (matches the Dockerfile build stage).

HuggingFace Space deployment

  • The HF Space's README is generated at CI time by .github/workflows/sync-to-hf.yml from the template at .github/hf-space.README.tpl.md. Don't hand-edit the repo's README.md expecting it to ship to HF β€” edit the template instead. The repo's README.md is purely for GitHub readers and is overwritten in the workflow's checkout (never pushed back to GitHub).
  • Required GitHub repo secrets (Settings β†’ Secrets and variables β†’ Actions β†’ Secrets):
    • HF_TOKEN β€” HF user access token, write scope.
    • HF_USER β€” HF username or org that owns the Space.
    • HF_SPACE_NAME β€” the Space's repo name (no user/ prefix).
  • Optional GitHub repo variables (Settings β†’ Secrets and variables β†’ Actions β†’ Variables) β€” each falls back to a default if unset:
    • HF_SPACE_TITLE, HF_SPACE_EMOJI, HF_COLOR_FROM, HF_COLOR_TO, HF_APP_PORT, HF_SHORT_DESCRIPTION.
  • Persistent storage lives at /data. It's mounted at runtime only if persistent storage is enabled in the Space's Settings UI. Without it, /data still exists and is writable, but writes are wiped on every restart. The boilerplate works in both modes.
  • /data is runtime-only per HF docs β€” never write to /data from the Dockerfile (build step). Pre-create + chown is fine; writes are not.
  • Do not use VOLUME /data in the Dockerfile β€” HF Spaces don't honor VOLUME declarations and it complicates layer permissions.
  • Container must run as UID 1000. $HOME must be writable by that user (we set HOME=/home/app in the Dockerfile so libraries like huggingface_hub can cache to ~/.cache/huggingface).
  • Build-time secrets (private model downloads, etc.) use --mount=type=secret,id=NAME and are read from /run/secrets/NAME per HF docs. Never pass runtime secrets through ARG β€” they would bake into image layers.
  • Runtime secrets/variables set in the HF Space Settings UI become regular env vars in the container β€” read them via os.environ.get(...) or via pydantic-settings (AUTOMAITA_* prefix for our config).
  • The backend reports storage status under storage in /api/status (exists, writable, persistent). The persistent flag is a heuristic: it's true when a marker file from a previous startup survived to the current one.

Out of Scope

  • Auth, database, persistence, queues, LLM integrations β€” add per project, don't bake into the boilerplate.
  • Tests β€” the boilerplate has nothing meaningful to test. Add tests when you add logic.
  • Analytics, telemetry, error tracking β€” opt in per project.
  • HF Hub Storage Buckets (hf://buckets/...) β€” that's a separate object-storage product accessed via huggingface_hub, not a filesystem mount. Not wired in by default; add the lib + auth if you need it per project.