Run a dev server, build for production, and deploy to any hosting provider. wwwhat runs anywhere Docker or Rust runs.
Start the dev server with file watching and auto-reload:
run-what dev
Options:
| Flag | Default | Description |
|---|---|---|
--path, -p | . | Path to project directory |
--port, -P | 8085 | Port to listen on |
--host, -H | 127.0.0.1 | Host to bind to |
--verbose, -v | — | Enable debug logging |
--strict | — | Warn about unresolved template variables |
--open, -o | — | Open browser after server starts |
--production | — | Production mode: disables live reload, debug tags, source viewer |
# Common usage
run-what dev --port 3000 --verbose
run-what dev --path ./my-project --strict
The dev server watches for file changes and reloads automatically. No need to restart when editing templates, components, or static files.
For static sites without server-side features, pre-render to HTML:
run-what build --output dist
This renders all pages to static HTML, minifies CSS/JS, and copies assets. Deploy the dist/ folder to any static host (Cloudflare Pages, Netlify, Vercel).
Docker is the simplest way to deploy wwwhat to any server. One command generates an optimized Dockerfile.
run-what deploy --target docker
This creates an optimized multi-stage Dockerfile that builds your binary and creates a minimal runtime image.
# Build the image
docker build -t my-app .
# Run with data persistence
docker run -d \
--name my-app \
-p 8085:8085 \
-v $(pwd)/data:/app/project/data \
-v $(pwd)/uploads:/app/project/uploads \
my-app
-v volume mounts are essential. Without them, your database and uploads are destroyed when the container restarts. Always mount data/ and uploads/. For production data that must persist reliably, consider using Cloudflare D1 or Supabase instead of local SQLite.
| File | Persists? | Requires |
|---|---|---|
data/app.db (database) | Yes | -v ./data:/app/project/data |
data/sessions.db | Yes | Same volume as above |
uploads/ | Yes | -v ./uploads:/app/project/uploads |
| Templates, components | Rebuilt on deploy | Baked into image |
Hetzner offers affordable VPS hosting starting at ~4.50/month. This is how getwhatnow.com is deployed.
ssh root@YOUR_SERVER_IP "curl -fsSL https://get.docker.com | sh"
run-what deploy --target ssh
The first run prompts for your server details interactively:
65.108.xx.xx)root/opt/wwwhat (default)This builds a release binary, syncs your project via rsync, and installs a systemd service for automatic restarts. Config is saved to wwwhat.toml for future deploys:
[deploy.ssh]
host = "65.108.xx.xx"
user = "root"
remote_dir = "/opt/wwwhat"
Subsequent deploys are one command: run-what deploy --target ssh
The SSH deploy uses rsync which excludes data/ and *.db files from sync. Your database and sessions remain untouched on the server across redeploys.
Deploy from a GitHub repository with automatic builds. Digital Ocean's App Platform detects the Dockerfile and handles the rest.
run-what deploy --target docker
git add Dockerfile && git commit -m "Add Dockerfile" && git push
/app/project/data8085Add any ${ENV_VAR} values (database credentials, API keys) in the App Platform settings under App-Level Environment Variables.
The persistent volume at /app/project/data survives all redeploys and container restarts. Your SQLite database and sessions are safe.
For global edge performance, deploy your wwwhat server on any VPS and use Cloudflare services for data and uploads. This is not a static deployment — your server runs wwwhat and connects to Cloudflare for persistent storage.
[Your VPS] ——> [Cloudflare D1] (database)
|
+——> [Cloudflare R2] (file uploads)
|
+——> [Local SQLite] (sessions only)
Follow the D1 setup instructions in the Database section above. For uploads, create an R2 bucket in the Cloudflare dashboard.
[database]
type = "d1"
[cloudflare]
account_id = "${CF_ACCOUNT_ID}"
api_token = "${CF_API_TOKEN}"
d1_database_id = "your-d1-database-id"
r2_bucket = "my-uploads"
r2_public_url = "https://pub-abc123.r2.dev"
[uploads]
enabled = true
provider = "r2"
Use any of the deployment methods above (Hetzner SSH, Docker, Digital Ocean). The server connects to Cloudflare for data, so your database persists regardless of what happens to the VPS.
data/ is preservedFor a production setup with SSL and reverse proxy, use Docker Compose:
services:
app:
build: .
restart: unless-stopped
volumes:
- ./my-project:/app/project:ro
- app-data:/app/project/data
- app-uploads:/app/project/uploads
environment:
- RUST_LOG=info
command: ["run-what", "dev", "--path", "/app/project", "--host", "0.0.0.0", "--production"]
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
depends_on:
- app
certbot:
image: certbot/certbot
volumes:
- ./certbot/www:/var/www/certbot
- ./certbot/conf:/etc/letsencrypt
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
volumes:
app-data:
app-uploads:
Named volumes (app-data, app-uploads) persist across container rebuilds.
Package your wwwhat app as a standalone binary that anyone can run — no Rust or wwwhat installation required. The binary embeds all project files, starts the server, and opens a browser automatically.
run-what bundle
This creates a bundle/ directory containing a complete Rust project:
project.tar.gz — compressed archive of your site filesCargo.toml — depends on wwwhat-core from crates.iosrc/main.rs — extracts files, starts server, opens browser# Option 1: Compile separately
cd bundle && cargo build --release
# Binary at bundle/target/release/wwwhat-app
# Option 2: Compile in one step
run-what bundle --compile
# Binary at bundle/wwwhat-app
Options:
| Flag | Default | Description |
|---|---|---|
--path, -p | . | Path to project directory |
--output, -o | bundle | Output directory for the generated project |
--compile | — | Also compile the bundle to a release binary |
# Just run it — browser opens automatically
./wwwhat-app
The binary extracts project files to a temp directory and starts the server. Database and uploads are stored in the current working directory:
./data/ — SQLite database and sessions./uploads/ — uploaded filesrun-what dev instead.
cargo build --target x86_64-unknown-linux-gnu inside the bundle directory. Share the resulting binary with anyone — they just double-click to run.
Generate a sitemap.xml from your project's routes:
run-what sitemap --host https://example.com
| Flag | Default | Description |
|---|---|---|
--path, -p | . | Path to project directory |
--host | — | Base URL for the sitemap (required) |
--output, -o | static/sitemap.xml | Output file path |
Verify your project setup before deploying:
run-what doctor
Checks project structure, template syntax, component resolution, and configuration correctness.