FalconVQA Docs
Getting Started

Configuration

Every environment variable for core and the frontend, what it does, and what it defaults to.

core

Required

VariablePurpose
OPENAI_API_KEYVision-language calls, answer synthesis, and the five LLM-backed aggregators
SUPABASE_URLStorage. Ingest cannot run without it
SUPABASE_SERVICE_ROLE_KEYStorage. Ingest cannot run without it

Optional

VariableDefaultPurpose
HF_TOKENRequired only for the diarization analyzer; its pyannote model is gated
VIDEOMIND_API_TOKENShared secret required on every non-public route. Set this for any deployment reachable from off-box
VIDEOMIND_BUCKETvideosStorage bucket name
VIDEOMIND_MAX_BYTES4 GiBCap on a server-side fetch of a caller-supplied URL
VIDEOMIND_UI10 disables the built-in web UI, same as serve.py --api-only

Paths

Every path is overridable, which is what makes it possible to point a second instance at its own data directory.

VariableDefaultHolds
VIDEOMIND_ROOTthe repo rootBase for the defaults below
VIDEOMIND_DATAdata/Everything the app writes. Wiping it is a full reset
VIDEOMIND_RECORDSdata/recordsOne JSON record per video: chunks, analyzer output, aggregates
VIDEOMIND_VECTORDBdata/vectordbQdrant's embedded storage
VIDEOMIND_UPLOADSdata/uploadsFiles posted as multipart, kept after upload
VIDEOMIND_CACHEdata/cacheVideos pulled back from Storage to be decoded, keyed by content hash
VIDEOMIND_MEDIAmedia/Read-only test assets, deliberately outside data/
VIDEOMIND_MODELSdata/modelsDownloaded weights (YOLO)

data/cache is regenerable — deleting it costs a re-download, never data. data/records and data/vectordb are not: together they are the analysis. Back those two up if anything.

frontend

frontend/.env.local
# Supabase — rows, auth, and the project-assets bucket
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
NEXT_PUBLIC_SUPABASE_ADMIN=""            # service-role key

# The analysis backend
CORE_API_URL="http://127.0.0.1:8077"
CORE_API_TOKEN=""                        # must match VIDEOMIND_API_TOKEN in core/.env

# Model providers — whichever you want in the model picker
OPENAI_API_KEY=""
GOOGLE_GENERATIVE_AI_API_KEY=
XAI_API_KEY=""
GROQ_API_KEY=""
CEREBRAS_API_KEY=""
LMSTUDIO_BASE_URL="http://localhost:1234/v1"   # local LM Studio server, no key needed

# Transactional email (optional)
NEXT_PUBLIC_RESEND_API_KEY=
NEXT_PUBLIC_RESEND_DOMAIN=

NEXT_PUBLIC_APP_NAME="FalconVQA"
NEXT_PUBLIC_APP_ICON='/next.svg'

CORE_API_URL and CORE_API_TOKEN are read server-side only, in lib/core/client.ts. That client is never imported into a client component: core has no per-user auth, so every call is made by a route that has already checked ownership and resolved which video ids the caller may touch.

Available models

The model picker is defined in app/agent/lib/ai/models.ts. Out of the box:

ProviderModels
OpenAIgpt-4o-mini, gpt-4.1-mini, gpt-5.4-mini
Googlegemini-2.5-flash
Groqllama-3.3-70b-versatile, openai/gpt-oss-120b, openai/gpt-oss-20b, moonshotai/kimi-k2-instruct
Cerebrasllama3.1-8b, gpt-oss-120b

A provider whose key is unset simply fails when selected; nothing else breaks.

Security posture

Core has no users, no projects, and no row-level security. Whoever can reach the port can read every video in it. VIDEOMIND_API_TOKEN is a boundary, not an authorisation model — it stops the port from being one. All per-user scoping happens in the frontend: RLS on video_core, plus every agent tool resolving the ids it is allowed to touch through a single choke point before calling core.

For a deployment:

  1. Set VIDEOMIND_API_TOKEN in core and the matching CORE_API_TOKEN in the frontend.
  2. Do not expose core's port publicly. The frontend is the only client that needs it.
  3. Run with --api-only if the built-in UI is not wanted — it has no way to send the token header, which is why / stays open when the UI is enabled.

/health, /docs, /redoc and /openapi.json stay open regardless, so a deployment can be checked without the secret.

On this page