Self-hosting

The server, the API and this website are in the same repository. Run them locally with SQLite, or deploy to Vercel with Supabase.

Run locally

Requires Node.js 22.13 or newer. There are no dependencies to install.

git clone https://github.com/Gauravkumar6617/whyline.git
cd whyline
pnpm start

The server listens on port 3000 (set PORT to change it) and stores data in SQLite at server/whyline.db (set DB_PATH to change it). Open http://localhost:3000/app to create a workspace, then log the CLI in with --url http://localhost:3000.

pnpm test

Deploy on Vercel and Supabase

  1. In the Supabase SQL editor, run supabase.sql. The tables are prefixed whyline_, so they can share a project. The file is safe to run again: when upgrading an existing deployment, run it before deploying the new code, so the event_id column and its unique index exist when the server starts writing them.
  2. Import the repository into Vercel. No build settings are needed; vercel.json serves the public/ folder and the functions in api/.
  3. Set the environment variables SUPABASE_URL (or NEXT_PUBLIC_SUPABASE_URL, which the Vercel Supabase integration sets) and SUPABASE_SERVICE_ROLE_KEY.
Keep the service role key secretIt gives full access to the tables. It is used only by the server code, never sent to browsers.

Test against Supabase

WHYLINE_DB=supabase SUPABASE_URL=... SUPABASE_SERVICE_ROLE_KEY=... pnpm test

This runs the test suite against your Supabase project and creates a few test workspaces.

Signup is open

Anyone who can reach your server can create a workspace through POST /api/workspaces, limited to 10 per hour per address (per /64 network for IPv6). The self-hosted server uses the address of the connection and ignores X-Forwarded-For, because any client can send that header. Behind a reverse proxy, set WHYLINE_TRUST_PROXY to the number of proxies in front of the server (usually 1); the address is then read from the X-Forwarded-For entry those proxies added, and anything the client put in front of it is ignored. Without it, every request through the proxy shares the proxy's single limit. On Vercel the platform sets the header, so nothing needs configuring. If the server should be private, restrict access at the network or hosting level.

Repository layout

PathWhat it is
public/This website: pages, the dashboard at /app, styles and logo.
api/Vercel functions that call lib/handle.js with Supabase storage.
lib/handle.jsThe API: authentication, validation and routes.
lib/db-supabase.jsCloud storage over the Supabase REST API.
lib/db-sqlite.jsSelf-hosted storage.
server/The self-hosted server (node:http with SQLite). Also used by the tests.
cli/The whyline CLI. Every integration calls it.
adapters/claude-code/The Claude Code plugin: hooks that call the CLI.