Deployment
WCAGify stores share links in a SQLite database. By default, this is a local file on disk (.data/shares.sqlite). For serverless platforms without persistent storage, you can connect a remote database instead.
Storage Options
Local SQLite (default)
Works out of the box on any platform with persistent disk storage. No configuration needed — the database is created automatically at .data/shares.sqlite.
Recommended for: Docker, Railway, Fly.io, Render, VPS, self-hosted
Remote database (LibSQL)
For serverless platforms like Vercel and Netlify, set DATABASE_URL to connect to a remote LibSQL-compatible database. This includes Turso (managed) or a self-hosted libsql-server.
Set the environment variables for your LibSQL database:
DATABASE_URL=libsql://your-db.turso.io
DATABASE_AUTH_TOKEN=your-auth-tokenWCAGify includes @libsql/client out of the box and automatically detects DATABASE_URL to switch to the remote database. No code changes needed.
Recommended Platforms
| Platform | Type | Persistent Disk | Free Tier |
|---|---|---|---|
| Railway | Container | Yes (volumes) | $5/month credit |
| Fly.io | Container | Yes (volumes) | Limited free tier |
| Render | Container | Yes (disks) | Free tier available |
| Coolify | Self-hosted | Yes | Free |
| VPS (Hetzner, DigitalOcean) | Server | Yes | From ~$4/month |
| Vercel | Serverless | No — requires DATABASE_URL | Free tier available |
| Netlify | Serverless | No — requires DATABASE_URL | Free tier available |
Environment Variables
| Variable | Required | Description |
|---|---|---|
WCAGIFY_ADMIN_SECRET | Yes (production) | Password to access reports |
DATABASE_URL | No | LibSQL database URL for serverless platforms |
DATABASE_AUTH_TOKEN | No | Auth token for the remote database |
PORT | No | Server port (defaults to 3000) |
Create a .env file from the included example:
cp .env.example .envBuild
pnpm buildThis generates a .output/ directory with a standalone Node.js server.
Docker
The scaffolded project includes a Dockerfile. Build and run:
docker build -t my-audit .
docker run -p 3000:3000 -e WCAGIFY_ADMIN_SECRET=your-secret -v audit-data:/app/.data my-auditThe -v flag mounts a volume at /app/.data so share link data persists across container restarts.
Railway
Railway is the easiest option — it auto-detects the Dockerfile and supports persistent volumes.
- Create a new project from your GitHub repo
- Railway auto-detects the
Dockerfile - Add the
WCAGIFY_ADMIN_SECRETenvironment variable - Add a volume mounted at
/app/.data(Settings > Volumes) - Generate a domain (Settings > Networking)
Vercel / Netlify
Serverless platforms work when connected to a remote database:
- Create a LibSQL database (e.g. on Turso)
- Set
DATABASE_URLandDATABASE_AUTH_TOKENin your environment variables - Set
WCAGIFY_ADMIN_SECRET - Deploy as usual
VPS / Bare Metal
Run the built server directly with Node.js:
pnpm build
WCAGIFY_ADMIN_SECRET=your-secret node .output/server/index.mjsUse a process manager like PM2 to keep it running:
pm2 start .output/server/index.mjs --name my-auditData Storage
| Deployment method | Data location |
|---|---|
| Docker / Railway | /app/.data/shares.sqlite — mount a volume at /app/.data |
| VPS / Bare Metal | .data/shares.sqlite — in the working directory |
| Vercel / Netlify | Remote database via DATABASE_URL |