English | 简体中文
This guide only documents deployment paths that match the current repository state.
- Backend: Node.js + Express
- Frontend: built by Vite, then served by the backend
- Queue and job state: Redis
- Rendering runtime: Python + ManimCE + LaTeX +
ffmpeg - AI upstreams: preferably configured with
MANIMCAT_ROUTE_*, or passed per request throughcustomApiConfig
- Run it on your own machine with the least abstraction: local native deployment
- Keep the runtime closer to production: Docker Compose
- Deploy to Hugging Face: Docker Space
- Node.js 18+
- Redis 7+ reachable at
localhost:6379by default - Python 3.11+
- Manim Community Edition 0.19.x
mypy- LaTeX
ffmpeg
git clone https://github.com/Wing900/ManimCat.git
cd ManimCat
cp .env.example .envConfigure at least one routed upstream:
MANIMCAT_ROUTE_KEYS=demo-key
MANIMCAT_ROUTE_API_URLS=https://api.example.com/v1
MANIMCAT_ROUTE_API_KEYS=sk-example
MANIMCAT_ROUTE_MODELS=gpt-4o-miniCommon optional variables:
PORT=3000
LOG_LEVEL=info
PROD_SUMMARY_LOG_ONLY=falsenpm install
npm --prefix frontend install
python -m pip install mypyDevelopment:
npm run devProduction-style run:
npm run build
npm startNotes:
npm run buildcurrently builds the frontend only.npm startrunstsx src/server.ts, so the backend does not depend on precompiled JS output.
- App:
http://localhost:3000 - Health:
http://localhost:3000/health
This is the most practical default. The repo already includes Redis, the Manim runtime, and the Node runtime in the deployment path.
If you have already published the image, you can also deploy from wingflow/manimcat instead of rebuilding locally each time.
cp .env.production .envSet at least one upstream profile:
MANIMCAT_ROUTE_KEYS=demo-key
MANIMCAT_ROUTE_API_URLS=https://api.example.com/v1
MANIMCAT_ROUTE_API_KEYS=sk-example
MANIMCAT_ROUTE_MODELS=gpt-4o-miniIf needed, change ports:
PORT=3000
REDIS_PORT=6379docker compose build
docker compose up -dIf you want to use the published image directly, replace the build section in docker-compose.yml with:
image: wingflow/manimcatdocker compose ps- App:
http://localhost:3000 - Health:
http://localhost:3000/health
Notes:
- Compose exposes port
3000to the host. - Inside Compose, Redis is reached through service name
redis. - Studio session workspaces are persisted in the
studio-workspace-datavolume at/app/.studio-workspace. - Generated and uploaded images are persisted in the
image-storagevolume at/app/public/images. - Generated videos are persisted in the
video-storagevolume at/app/public/videos. - Manim media cache and intermediate artifacts are persisted in the
manim-mediavolume at/app/media. - Temporary render files are persisted in the
manim-tmpvolume at/app/tmp.
Inspect volumes if needed:
docker volume ls
docker volume inspect manimcat_studio-workspace-data- Use a Docker Space.
- The app port is
7860. - Environment variables must be defined in Space Settings, not only in a checked-in
.envfile.
The repository Dockerfile is already the Hugging Face compatible one:
- based on
manimcommunity/manim:stable - installs Node.js, Redis, CJK fonts, and
ffmpeg - starts with
node start-with-redis-hf.cjs - defaults to
PORT=7860
Do not follow older instructions that mention Dockerfile.huggingface. That file is not part of the current repo.
If you have already published a Docker image, other environments can reference wingflow/manimcat; however, Hugging Face Spaces still builds from the repository Dockerfile rather than running a Docker Hub image directly.
Minimum variables:
PORT=7860
NODE_ENV=production
MANIMCAT_ROUTE_KEYS=demo-key
MANIMCAT_ROUTE_API_URLS=https://api.example.com/v1
MANIMCAT_ROUTE_API_KEYS=sk-example
MANIMCAT_ROUTE_MODELS=gpt-4o-miniRecommended:
LOG_LEVEL=info
PROD_SUMMARY_LOG_ONLY=truegit add .
git commit -m "Deploy ManimCat"
git pushAfter deployment:
- App:
https://YOUR_SPACE.hf.space/ - Health:
https://YOUR_SPACE.hf.space/health
MANIMCAT_ROUTE_* is the recommended server-side routing mechanism. It acts as both:
- the Bearer-key whitelist
- the mapping from key to
apiUrl/apiKey/model
Example:
MANIMCAT_ROUTE_KEYS=user_a,user_b
MANIMCAT_ROUTE_API_URLS=https://api-a.example.com/v1,https://api-b.example.com/v1
MANIMCAT_ROUTE_API_KEYS=sk-a,sk-b
MANIMCAT_ROUTE_MODELS=gpt-4o-mini,gemini-2.5-flashRules:
- All four variables support comma-separated or newline-separated values.
MANIMCAT_ROUTE_KEYSis the primary index.- Entries missing
apiUrlorapiKeyare skipped. - If a variable only provides one value, that value is reused for all entries.
- If
modelis empty, the key can still authenticate but has no usable model.
Priority:
- request-body
customApiConfig - server-side
MANIMCAT_ROUTE_*
Use server-side routing when different users should always hit different upstreams. Use the frontend provider settings when one browser user wants to manage multiple providers locally.
There are two optional persistence layers:
- generation history:
ENABLE_HISTORY_DB=true - Studio Agent session/work persistence:
ENABLE_STUDIO_DB=true
Shared connection variables:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-supabase-keyApply:
src/database/migrations/001_create_history.sql
If you also want render-failure export, apply:
src/database/migrations/002_create_render_failure_events.sql
Then configure:
ENABLE_HISTORY_DB=true
ENABLE_RENDER_FAILURE_LOG=true
ADMIN_EXPORT_TOKEN=replace_with_long_random_tokenExport endpoint:
GET /api/admin/render-failures/export- header:
x-admin-token
Apply:
src/database/migrations/003_create_studio_agent.sql
Then enable:
ENABLE_STUDIO_DB=trueCheck:
MANIMCAT_ROUTE_*is fully configured- the request includes a valid Bearer key
- the matched route entry does not have an empty
model
Check:
- Redis is actually running
REDIS_HOSTandREDIS_PORTmatch your environment- in Docker Compose, the backend is pointing to service
redis
Check:
- the Space SDK is Docker
- env vars were added in Space Settings
- you did not follow stale instructions mentioning
Dockerfile.huggingface