The stack
What βWave is built on, what it runs on, and what you need to host it yourself. Every figure below is counted from the repository, not estimated.
48,761 lines of TypeScript 45 API route modules 55 services 82 database tables 7 model providers 2 vCPUs to run itRuntime
One language end to end, so there is no context switch between the API, the interface and the scripts that drive them.
| Layer | What |
|---|---|
| Language | TypeScript 5.4, across server, client and tooling |
| Server | Node.js + Express 4, executed directly with tsx — no server build step |
| Interface | React 19 single-page app, bundled with Vite 5 |
| Validation | Zod schemas on the boundaries |
| Scheduling | In-process scheduler (60s tick) and job runner (15s tick) — no external queue, no broker |
Why no build step on the server. The server runs straight off TypeScript. Deploying is git pull and a restart. That is one fewer thing standing between a problem and a fix, which matters more than a few milliseconds of cold start.
Data
SQLite, through libsql, in WAL mode. Eighty-two tables covering clients, content, syndication, discovery, outreach, citations, invoicing, commissions and the model-usage ledger.
Why not Postgres. βWave has to be installable by someone who runs a franchise, not a data centre. SQLite is a single file: no database server to provision, no connection strings to get wrong, and a backup is a file copy. It carries the entire multi-tenant platform on two vCPUs. Postgres would buy concurrency this workload does not need, and cost the thing we are actually selling — that you can run this on your own box.
The model layer
Seven providers sit behind a single interface, selectable per tenant:
- Anthropic — Claude, the default for long-form and brand voice
- OpenAI — GPT models and image generation
- DeepSeek and Qwen — high-volume, low-cost classification work
- Ollama — local inference, zero API cost, nothing leaves the machine
- Plus a generic OpenAI-compatible endpoint for anything else
Around them: a per-tenant spend guard that hard-stops at a ceiling rather than silently downgrading you to a cheaper model, a usage ledger that records every call with its true billed cost, and prompt caching on the long system prompts.
Why seven. We sell to people who have been burned by a vendor. If a provider triples its price, degrades its model, or an EU client refuses US-hosted inference, that is one setting — not a migration. The point of owning your marketing engine is that nobody can move your cheese.
What it connects to
| Integration | Purpose |
|---|---|
| MCP server | stdio and HTTP transports, so other AI agents can drive βWave directly |
| Browser extension | Manifest V3. Reads context already rendered on pages you visit; no automated browsing |
| Puppeteer | Headless Chrome for generated PDF reports |
| Astro + Netlify | Static sites βWave builds and publishes for clients |
| SMTP | Newsletters and sequenced outreach, through your own mail server |
| RSS, Search Console | Source ingestion and performance data |
How it is hosted
The reference deployment is deliberately unremarkable, because unremarkable is reproducible.
| Piece | What |
|---|---|
| Machine | 2 vCPU · 4 GB RAM · 40 GB NVMe, Ubuntu 24.04 LTS |
| Process | systemd service, with timers for nightly backup and weekly site archive |
| Web | nginx reverse proxy, Let's Encrypt certificates on auto-renew |
| Backups | Fourteen nightly local snapshots, mirrored off-site; secrets encrypted with GPG AES-256 before they ever leave the box |
That is the whole hosting bill. There is no managed database, no queue service, no object store and no per-seat SaaS underneath it.
Security
- Provider API keys are encrypted at rest with AES-256-GCM; the master key is never stored in the database
- Passwords hashed with scrypt; sessions are HMAC-signed cookies
- The client-scoped
operatorrole is deny-by-default — a new endpoint is inaccessible to operators until it is explicitly allowed, rather than the other way round - Self-hosted with Ollama, no content, client data or prompt ever leaves your machine
To run it yourself
Node.js, git, and a machine. Clone the repository, set a few environment variables, npm install, npm start. Bring your own model keys, or point it at a local Ollama and bring none.
βWave is licensed, not subscribed to per seat. One licence covers every client you run through it — an agency licence for up to ten tenants, or an exclusive licence that keeps it out of the hands of anyone else selling into your vertical. The software is identical either way; what differs is who else is allowed to have it.
What it does not have
βWave has been built by one person shipping daily against live clients, so the feedback loop has been production rather than continuous integration. There is no automated test suite yet. It is the first thing that changes with a second pair of hands.
We would rather you read that here than discover it in month three.
Questions a page cannot answer: book a call — a technical review of the code is part of licensing, not a public download.