Skip to content

Self-hosting

Each XLR8 instance belongs to one owner and runs on accounts you control: a Convex project for the backend, a Clerk application for sign-in, and a static host for the web app. This page gives you the overview; the pages after it walk through each part.

Part Service Example address What it does
Web app a static host, for example Vercel https://xlr8.example.com serves the landing page, the sign-in page and the app
Sign-in a Clerk application (production instance) https://clerk.xlr8.example.com shows the sign-in form, issues tokens
Backend a Convex project (production deployment) https://happy-otter-123.convex.cloud database and backend functions
HTTP endpoints the same Convex deployment https://happy-otter-123.convex.site MCP for agents, GitHub webhook, health check
Domain yours xlr8.example.com points to the static host; Clerk needs DNS records under it

The examples in these docs use xlr8.example.com for the app, clerk.xlr8.example.com for Clerk and happy-otter-123 for the Convex deployment. Replace them with your own values.

  • Your browser loads the app as static files from your domain.
  • If you are not signed in, / shows the landing page. Sign in leads to /sign-in, where Clerk’s sign-in form is embedded in the page.
  • After sign-in, the app asks Clerk for a token and sends it with every request to Convex.
  • Convex checks that the token comes from your Clerk instance, and XLR8 checks that your account is in the XLR8_OWNER_IDS list. Anyone else is turned away.
  • Agents talk to the Convex HTTP endpoint (…convex.site/mcp) directly, with their own key or as an OAuth connector.
  • Node.js 24 and pnpm 11 (corepack enable provides the pinned pnpm version), and a clone of the repository with pnpm install done. The deploy scripts run from it.
  • A Convex account. The free plan is enough for one person.
  • A Clerk account. A Clerk production instance needs a domain you control, because Clerk serves its sign-in API from clerk.<your domain>.
  • A static host. The repository ships a deploy script for Vercel. Any host that can rewrite paths based on a cookie works too.
  • Optional: a GitHub token for the pull request integration and a GitHub repository for nightly backups.

The deploy scripts read the non-secret settings of your instance from a JSON file. Copy the example and fill it in as you go through the setup:

Terminal window
cp deploy/instance.example.json deploy/instance.json

deploy/instance.json is ignored by Git. If it does not exist, the scripts read ~/.config/xlr8/instance.json instead, which is handy if you work with several checkouts. Every field can also be overridden with an environment variable.

Field Environment variable Example Used for
convexDeployment XLR8_CONVEX_DEPLOYMENT happy-otter-123 Convex addresses in the build, deploy key check
appUrl XLR8_APP_URL https://xlr8.example.com absolute links in the build, target of redirects
clerkPublishableKey XLR8_CLERK_PUBLISHABLE_KEY pk_live_… Clerk in the browser
vercelProject XLR8_VERCEL_PROJECT xlr8 Vercel project to deploy to
vercelScope XLR8_VERCEL_SCOPE your Vercel team slug Vercel team to deploy to
mcpHosts XLR8_MCP_HOSTS ["mcp.xlr8.example.com"] optional custom address for MCP
redirectHosts XLR8_REDIRECT_HOSTS ["old.example.org"] old domains that redirect to appUrl
branchPrefix VITE_XLR8_BRANCH_PREFIX jane optional prefix of suggested Git branch names

Nothing in this file is secret: these values end up in the browser or in public DNS anyway. Deploy keys and tokens never go into it.

  1. Clerk: create the application, the JWT template and your user. Note the publishable key, the Frontend API URL and your user id.

  2. Convex: create the project, store the deploy key, set the environment variables and deploy the backend. Check /health.

  3. Web app: build and deploy the app to Vercel or another static host, and point your domain at it.

  4. First sign-in: open your domain, sign in and create your first team.

Afterwards, add what you need:

To keep your instance current, see Updating.

  • One owner per instance. All accounts in XLR8_OWNER_IDS act as the same owner.
  • Fixed time zone. Calendar days (due dates, sprints, recurring issues, the morning notifications) are computed in Europe/Berlin. There is no setting for this yet.