Graph Viewer Deployment
Production Server
Section titled “Production Server”The graph viewer ships with server.mjs — a lightweight Node.js HTTP server that serves the Vite-built static files from dist/. It handles:
- Content-type detection for all common web assets
- Immutable cache headers (
max-age=31536000) on/assets/*(Vite hashed filenames) no-cachefor HTML and non-hashed files- SPA fallback — unknown routes serve
index.htmlfor client-side routing - HEAD request support
- Path traversal protection
The server listens on 0.0.0.0:3000 by default. Override with HOST and PORT environment variables.
Docker
Section titled “Docker”The included multi-stage Dockerfile builds and serves the viewer:
FROM node:20-slim AS builderWORKDIR /appCOPY package*.json ./RUN npm ciCOPY . .RUN npm run build
FROM node:20-slimWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/server.mjs ./COPY --from=builder /app/package*.json ./ENV HOST=0.0.0.0EXPOSE 3000CMD ["node", "server.mjs"]Build and run:
docker build -t automem-graph-viewer .docker run -p 3000:3000 automem-graph-viewerIf you run the viewer locally alongside the AutoMem Docker stack, note that FalkorDB’s built-in browser also defaults to port 3000. Set PORT=3001 (or similar) on one service to avoid a collision.
Railway
Section titled “Railway”Recommended: deploy the published image. Point your Railway service at the public GHCR image instead of building from source:
ghcr.io/verygoodplugins/automem-graph-viewer:stableThis avoids spending Railway compute rebuilding the frontend on every deploy. The viewer service typically needs no custom environment variables in production.
After the viewer’s domain is created, set these variables on the automem API service (not the viewer service) so browser traffic can reach it:
GRAPH_VIEWER_URL=https://<viewer-domain>VIEWER_ALLOWED_ORIGINS=https://<viewer-domain>Browser-to-API traffic must use the API’s public domain — Railway private domains aren’t reachable from user browsers. The viewer itself stores only browser-side config (server URL, token) and should never receive database credentials.
Recommended Railway layout
Section titled “Recommended Railway layout”| Service | Source | Public? | Notes |
|---|---|---|---|
automem | ghcr.io/verygoodplugins/automem:stable | Yes | Auth, API routes, data access, /viewer/* bootstrap |
automem-graph-viewer | ghcr.io/verygoodplugins/automem-graph-viewer:stable | Yes | Static React/Three.js UI; no DB secrets |
mcp-automem | ghcr.io/verygoodplugins/mcp-automem:stable | Yes | Remote MCP bridge for hosted clients |
falkordb | falkordb/falkordb:latest | No | Private graph database |
qdrant | qdrant/qdrant:latest or Qdrant Cloud | No/External | Vector store |
Keep the standalone viewer service served at /. Only set VITE_BASE_PATH=/viewer/ when the built assets are actually served from the AutoMem API origin under /viewer/.
Source-linked deploys. The repository’s railway.toml is kept for preview/source deployments and mirrors the Dockerfile used to publish the GHCR image:
[build]builder = "DOCKERFILE"dockerfilePath = "Dockerfile"
[deploy]healthcheckPath = "/"restartPolicyType = "ON_FAILURE"restartPolicyMaxRetries = 5To deploy from source:
- Push the repository to GitHub
- Connect it to a Railway project
- Railway builds the Dockerfile and deploys automatically on push
The PORT environment variable is set automatically by Railway. Configure the API server URL via the viewer’s settings UI or localStorage after deployment.
Static Hosting
Section titled “Static Hosting”Since the viewer is a static SPA after build, you can also host it on any static file server (Nginx, Cloudflare Pages, Vercel, etc.):
npm run build# Upload dist/ to your hosting providerRequirements for the hosting provider:
- Serve
index.htmlfor all unknown routes (SPA fallback) - Set appropriate cache headers on
/assets/*
The viewer will use relative URLs by default. Users configure the AutoMem API URL through the settings panel on first visit.