Deployment
Vercel or your own server.
Two supported ways to put THESIS online. Vercel needs Postgres for the admin; your own server can use a local SQLite file. Either way, serve it over HTTPS.
01Vercel
Who pays: you, on your own Vercel account (commercial sites need a paid plan) and your own Postgres provider such as Neon, billed by them above their free tiers; the item price does not include hosting (Costs).
The commands on this page are written for the shell of macOS and Linux (bash or zsh). On Windows, run them in WSL (Windows Subsystem for Linux, Ubuntu) or Git Bash: commands such as cp, openssl, set -a && . ./.env and multi-line curl with \ do not work as written in PowerShell or cmd. The node and pnpm commands work in any of them.
- Import the projectPush the folder to your own Git repository and import it in Vercel.
vercel.jsonalready sets the build (pnpm build), output (dist), the/appand/adminrewrites,/api/*and/admin/api/*to the functionapi/[...path].ts(60 s limit) and the security headers. - Postgres RequiredCreate a Postgres 14+ database (for example Neon from the Vercel marketplace) and set
DATABASE_URLto its pooled connection string withsslmode=require. The admin creates itsmk_admin_*tables on first use. There is no SQLite on Vercel. - Blob RecommendedStorage → create a private Blob store and connect it; that sets
BLOB_READ_WRITE_TOKEN. Without it the aggregate counters live in/tmpand reset on cold starts, and the Status page says so. A public store needsTHESIS_BLOB_ACCESS=public. - Environment variables
ADMIN_SECRET_KEY(openssl rand -hex 32),ADMIN_SETUP_TOKEN(openssl rand -hex 24, the one-time secret that creates the owner),DATABASE_URL, optionallyANTHROPIC_API_KEY. Set them for every environment you deploy (Production, Preview), then redeploy. Where to click (labels as of October 2026): Vercel dashboard → your project → Settings → Environment Variables → enter Key and Value, tick the environments (Production, Preview) → Save; then Deployments → the latest deployment → Redeploy. Vercel's guide: Vercel docs → Managing environment variables. - Deploy, then create the ownerOpen
/adminand enter the value ofADMIN_SETUP_TOKENwith your email and a password, then remove the variable and redeploy. Without the token: open/adminonce so a function starts, then open the deployment's Logs (orvercel logs <deployment-url>) and search forsetup code. Every cold start before the owner exists prints its own code; any printed code works (next steps). - DomainProject → Settings → Domains. Add your domain and follow the DNS instructions.
Vercel's Hobby plan is for personal, non-commercial use under Vercel's terms; check which plan fits how you run the desk (Costs and services).
Visitor country for blocking live modes comes from Vercel's x-vercel-ip-country header (or cf-ipcountry behind Cloudflare).
02Your own server
Who pays: you, to your server or VPS provider and for your domain; SQLite on the server has no service cost.
- Build on the server
pnpm install pnpm build - SettingsCreate
.env(how). WithoutDATABASE_URLthe admin uses SQLite inTHESIS_DATA_DIR; back that folder up. - Keep it runningUse a process manager. The command it should run, from the project folder:
The process manager must supply the variables fromnode dist-server/server/node.js.env: with systemd,EnvironmentFile=/path/to/thesis/.envandExecStart=/usr/bin/env node dist-server/server/node.jswithWorkingDirectory=/path/to/thesis; pm2,pm2 start dist-server/server/node.js --name thesis; by hand,set -a && . ./.env && set +a && pnpm start. Runpnpm buildagain after every update. - HTTPS in frontPut a reverse proxy (Caddy, nginx) in front of port
8787, setTHESIS_HOST=127.0.0.1so only the proxy can reach it, and setTHESIS_TRUST_PROXY=1so rate limits and theSecurecookie see the real client and scheme. THESIS then takes the right-mostX-Forwarded-Forentry (the one your proxy appends) as the client address and ignores entries further left, which a client could write. If the admin sign-in does not stick, see Troubleshooting → reverse proxy.
On a bare server there is no country header, so nobody is geo-blocked. If you rely on blocked countries, run behind Cloudflare (which adds cf-ipcountry) or on Vercel.
vercel.json sets a strict Content-Security-Policy (only Hyperliquid and api.telegram.org may be contacted by the browser), X-Frame-Options: DENY and more. The Node server applies its own policy from server/csp.ts. If you add another service the browser must reach, add it to both.
03Before you open it to users
- Owner created,
ADMIN_SETUP_TOKENremoved from the environment, two-factor on,ADMIN_SECRET_KEYbacked up, a database backup tested (Backups). - Status page: no blockers.
- Your own risk notice in Legal; your terms linked from the landing copy if you need them.
- Blocked countries reviewed; mainnet left off until you have tested on testnet yourself.
- AI daily cap set to a budget you accept.