SPB Git

Repository Public

spbchat-spboucher

Private universal chat interface over the OpenRouter ecosystem — 400+ models, branching, streaming, usage tracking. Next.js 16 + SQLite, PWA, deployed on m4m64a at chat.spboucher.ai

12 entries at the root
History

Latest commit chore(retrait cluster): synchro copie du nœud M4M64a + README « URL live hors fonction » (2026-09-04) 790ed53

NameLast commitUpdated
ops feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
public feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
scripts feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
src feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
.gitignore feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
CLAUDE.md feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
eslint.config.mjs Initial commit from Create Next App
next.config.ts feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
package-lock.json feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
package.json feat: chat.spboucher.ai — universal OpenRouter chat, v1 production release
README.md chore(retrait cluster): synchro copie du nœud M4M64a + README « URL live hors fonction »...
tsconfig.json Initial commit from Create Next App
README.md View source

⚠️ URL live hors fonction pour le moment. L'application a été retirée du cluster MacLustr le 2026-09-04 (processus arrêtés, copie du nœud supprimée). Ce dépôt spbgit est désormais la seule source de vérité du projet. Ancienne URL : https://chat.spboucher.ai

# chat.spboucher.ai

Status Models Next.js TypeScript SQLite Gateway PWA Node License

Author: Simon-Pierre Boucher Contact: contact@spboucher.ai Production: https://chat.spboucher.ai

A private, universal chat interface over the entire OpenRouter ecosystem — one login, one server-side API key, 400+ models behind a single catalog, full conversation persistence with branching and per-message model attribution. Designed mobile-first as an installable PWA: a personal ChatGPT/Claude-class product, not an API demo.


# Highlights

  • One gateway, hundreds of models — the catalog is synced dynamically from OpenRouter into SQLite (never hand-maintained); removed models are marked Unavailable, historical conversations stay intact forever.
  • Real streaming — normalized SSE event protocol (generation.start, content.delta, reasoning.delta, usage, …) with 15 s keep-alive pings that survive ngrok and mobile radio sleep. Stop truly aborts the upstream OpenRouter stream.
  • Branching & regeneration — regenerating never destroys an answer; siblings live side by side with ‹ 1/2 › navigation, so the same prompt can be compared across models.
  • Generation state machine — queued → starting → streaming → completed | cancelled | failed, persisted per generation; a dropped mobile connection resyncs from the server.
  • Usage & cost tracking — prompt/completion/reasoning/cached tokens and reported cost per generation, with a Today / 7d / 30d / All-time dashboard broken down by model.
  • Instrument Panel design — ink/graphite surfaces, one teal accent for "alive", one amber accent for "cost", mono type for model IDs and meters, and the signature Model Rail cartridge attached to the composer (provider glyph · mono model ID · live context meter · price-per-1M chip).
  • Security posture for a public tunnel — argon2id single-user auth, DB-backed sessions, aggressive login rate limiting, Secure/HttpOnly/SameSite cookies, CSP + security headers, zero unauthenticated API surface.

# Architecture

text
Browser (phone or desktop, PWA)
   │  POST /api/chat  (SSE)
   ▼
Next.js 16 backend — node m4m64a (Apple Silicon, macOS)
   │  src/lib/openrouter/  (single client module, normalized errors/streaming)
   ▼
OpenRouter API ──► Anthropic · OpenAI · Google · Meta · Qwen · DeepSeek · Mistral · …
  • Runtime: single Node.js process (API + UI), port 3000, exposed via ngrok at chat.spboucher.ai
  • Database: SQLite (better-sqlite3, WAL) — conversations, message tree, generations, usage, model catalog cache, sessions
  • Supervision: three launchd agents (app, ngrok, nightly backup at 03:30 with 14-day retention)

# Local development

bash
cp .env.example .env                          # fill in OPENROUTER_API_KEY
npm install
npm run set-password <username> [password]    # generates a strong one if omitted
npm run dev

# Deployment (m4m64a)

bash
rsync -az --delete --exclude node_modules --exclude .next --exclude data --exclude .env \
  ~/Desktop/chat-spboucher/ M4M64a:apps/chat.spboucher.ai/
ssh M4M64a '~/apps/chat.spboucher.ai/ops/deploy.sh'
launchd agent Role
ai.spboucher.chat.app npm run start on port 3000, KeepAlive
ai.spboucher.chat.ngrok ngrok http --url=chat.spboucher.ai 3000, KeepAlive
ai.spboucher.chat.backup nightly SQLite backup 03:30, 14-day retention

# API surface

All routes require a session cookie except POST /api/auth/login.

Endpoint Purpose
POST /api/chat send a message or regenerate ({regenerateOf}) — returns a normalized SSE stream
POST /api/generations/:id/cancel abort the upstream OpenRouter generation
GET /api/models · POST /api/models/sync cached catalog · manual refresh
POST /api/models/prefs favorites / pinned models
GET/PATCH/DELETE /api/conversations[/:id] conversation CRUD, branch leaf selection
GET /api/usage?period=today|7d|30d|all usage & cost dashboard data

# License

Private software — © Simon-Pierre Boucher. All rights reserved.


Simon-Pierre Boucher · contact@spboucher.ai · chat.spboucher.ai

Clone chat-spboucher

Anonymous clone and fetch. Pushing requires the owner's personal access token.

Snapshot of main

Files main
Menu

Theme