Skip to main content

Uploads and Storage

The app has two storage classes: public uploads for browser-rendered media and private document storage for rule/source files.

Public Uploads

Public uploads include campaign covers, avatars, and NPC profile photos. They are served from /uploads by FastAPI and proxied by Vite during development.

Primary files:

  • server/app/lib/uploads.py
  • server/app/main.py
  • web/src/lib/api.ts (resolveAssetUrl)

Public upload routes must validate file type and size. Store only paths that can be safely resolved by the serving layer.

Private Documents

Core-rule uploads are private and live under server/storage/. Campaign documents are also managed through storage helpers and exposed through scoped download routes, not raw file serving.

Primary files:

  • server/app/lib/core_rules_storage.py
  • server/app/lib/campaign_docs_storage.py
  • server/app/routers/admin.py
  • server/app/routers/campaign_documents.py

Sidecar Files

Document ingestion stores extracted Markdown sidecars so Process can re-derive chunks without re-parsing the original source file.

Change Checklist

  • Decide whether the file is public media or private source material.
  • Validate size and MIME/content type before writing.
  • Clean up replaced or deleted files when practical.
  • Never put admin core-rule files under /uploads.
  • Update proxy/static serving if a new public path is introduced.