Skip to content

Repository files navigation

Rouwang

Self-hosted local AI router with OpenAI-compatible API, provider fallback, usage tracking, quota tools, and dashboard UI.

Rouwang runs as one Go binary on 127.0.0.1:17171, serves /v1 for AI clients, serves /api for dashboard operations, and embeds a statically exported Next.js dashboard.

What Rouwang Does

  • Exposes OpenAI-compatible /v1/chat/completions endpoint for AI coding tools.
  • Routes requests across configured providers and accounts.
  • Supports provider management, OAuth/API-key connections, aliases, combos, and fallback chains.
  • Tracks usage and quota in local SQLite.
  • Provides dashboard pages for endpoint setup, providers, combos, usage, quota, console, CLI tools, playground, translator, profile, and settings.
  • Includes translators for OpenAI, Claude, Gemini, Cursor, and Kiro formats.
  • Includes RTK token saver package for reducing repeated tool-result payloads.
  • Runs locally by default and stores data under ~/.rouwang.

Status

Project is active work-in-progress. Docs under docs/ describe product plan, architecture, milestones, and handoffs. Codebase already contains Go backend modules, Next.js dashboard, tests, Docker setup, and build scripts.

Tech Stack

Backend

  • Go 1.23
  • chi router
  • GORM
  • SQLite via github.com/glebarez/sqlite
  • Goose migrations embedded with embed.FS
  • JWT auth via github.com/golang-jwt/jwt/v5
  • bcrypt / crypto from golang.org/x/crypto
  • stdlib log/slog

Frontend

  • Next.js 16.2.6
  • React 19.2.6
  • TypeScript 6.0.3
  • Tailwind CSS 4.3.0
  • TanStack Query 5.100.13
  • React Hook Form
  • Zod
  • Recharts
  • Axios

Runtime / Deployment

  • Single Go binary serving embedded Next.js static export
  • SQLite database in configurable data directory
  • Docker and Docker Compose support

Repository Layout

.
├── cmd/rouwang/                 # Go entrypoint and embedded web assets
│   ├── main.go                  # Loads config, DB, JWT secret, server
│   └── web/out/                 # Next.js static export copied here during build
├── internal/
│   ├── authjwt/                 # JWT secret handling
│   ├── config/                  # Env/config loading
│   ├── database/                # SQLite open + embedded migrations
│   ├── middleware/              # Auth, CSRF, CORS, security, logging, recovery
│   ├── models/                  # Shared database models
│   ├── modules/                 # Feature modules and route registration
│   │   ├── aliases/
│   │   ├── apikeys/
│   │   ├── auth/
│   │   ├── clitools/
│   │   ├── combos/
│   │   ├── init/
│   │   ├── media/
│   │   ├── oauth/
│   │   ├── playground/
│   │   ├── providers/
│   │   ├── proxypools/
│   │   ├── quota/
│   │   ├── settings/
│   │   ├── usage/
│   │   └── v1/
│   ├── response/                # JSON response helpers
│   ├── routedeps/               # Shared route dependencies
│   ├── rtk/                     # RTK token saver
│   ├── server/                  # HTTP server and route tree
│   └── translator/              # Provider format translators
├── web/                         # Next.js dashboard
│   ├── app/                     # App Router pages and layouts
│   ├── features/                # Feature-specific UI/API modules
│   ├── hooks/                   # Shared hooks
│   ├── lib/                     # API client, utilities, validation, i18n
│   ├── providers/               # React providers
│   └── styles/                  # Design tokens, layout, typography, utilities
├── docs/                        # Product, spec, architecture, milestones, handoffs
├── design-system/               # Visual design canon and smoke docs
├── mockups-fresh/               # HTML mockups and screenshots
├── scripts/                     # PowerShell build/test helpers
├── Dockerfile
├── docker-compose.yml
├── Makefile
└── .env.example

Main HTTP Surfaces

Public / mixed-auth

  • GET /api/health — health check, returns { "status": "ok" }.
  • Init and auth routes register without global dashboard-auth wrapper.

Dashboard API

Protected by dashboard session auth:

  • API keys
  • Providers
  • Proxy pools
  • Aliases
  • Media providers
  • Combos
  • CLI tools
  • Playground
  • Settings
  • Usage
  • Quota
  • OAuth

OpenAI-Compatible API

  • /v1/* routes are registered by internal/modules/v1.
  • Primary intended endpoint: /v1/chat/completions.
  • Used by Claude Code, Cursor, Codex-style clients, and other OpenAI-compatible tools.

Dashboard Pages

Current Next.js pages include:

  • /login
  • /setup
  • /dashboard
  • /dashboard/endpoint
  • /dashboard/providers
  • /dashboard/providers/setup
  • /dashboard/providers/manage
  • /dashboard/media-providers
  • /dashboard/media-providers/manage
  • /dashboard/proxy-pools
  • /dashboard/combos
  • /dashboard/usage
  • /dashboard/quota
  • /dashboard/console
  • /dashboard/cli-tools
  • /dashboard/playground
  • /dashboard/translator
  • /dashboard/profile
  • /dashboard/settings

In development, Next.js rewrites /api/* and /v1/* to http://127.0.0.1:17171.

Requirements

  • Go 1.23+
  • Node.js 22+ recommended for frontend build, matching Dockerfile node:22-alpine
  • npm
  • Docker optional

Configuration

Copy .env.example if local overrides are needed:

cp .env.example .env

Supported env vars in current config:

Variable Default Description
HOST 127.0.0.1 Bind host for Go server. Use 0.0.0.0 in containers.
PORT 17171 Bind port.
DATA_DIR ~/.rouwang Directory for SQLite DB and JWT secret.
COOKIE_SECURE false Set secure cookies. Use true behind HTTPS.
ENABLE_REQUEST_LOGS false Present in .env.example; request-log behavior may depend on middleware implementation.

Runtime files:

  • SQLite DB: ${DATA_DIR}/rouwang.db
  • JWT secret: generated/loaded under ${DATA_DIR} by internal/authjwt
  • DB permissions: data dir created with 0700

Development

Backend only

go run ./cmd/rouwang

Server listens on configured address, default:

http://127.0.0.1:17171

Health check:

curl http://127.0.0.1:17171/api/health

Expected:

{"status":"ok"}

Frontend dev server

cd web
npm install
npm run dev

Next.js dev server proxies backend calls to http://127.0.0.1:17171 through rewrites.

Run backend and frontend in separate terminals during frontend development.

Build

Makefile

make build

This runs:

  1. cd web && npm install && npm run build
  2. Copies web/out into cmd/rouwang/web/out
  3. Builds Go binary from ./cmd/rouwang

Result depends on Go default output for package build. For explicit binary name:

go build -o rouwang ./cmd/rouwang

Manual web build

cd web
npm install
npm run build

Production Next.js config uses static export:

output: "export"

Generated static files live in web/out and must be copied into cmd/rouwang/web/out before building Go binary.

Test

All Go tests

go test ./...

or:

make test

Frontend typecheck / lint

cd web
npm run typecheck
npm run lint

Current frontend lint script runs TypeScript typecheck:

"lint": "tsc --noEmit"

Helper scripts

PowerShell helpers exist:

.\scripts\build.ps1
.\scripts\test.ps1

Docker

Build image

docker build -t rouwang .

Run container

docker run --rm -p 17171:17171 -e HOST=0.0.0.0 -e DATA_DIR=/data -v rouwang-data:/data rouwang

Docker Compose

docker compose up --build

Compose exposes:

http://127.0.0.1:17171

Compose stores data in named volume:

rouwang-data

Basic Usage Flow

  1. Start Rouwang.
  2. Open dashboard at http://127.0.0.1:17171.
  3. Complete setup/login.
  4. Add provider connections.
  5. Create API key for local AI tools.
  6. Configure tool base URL to http://127.0.0.1:17171/v1.
  7. Use generated key as OpenAI-compatible API key.
  8. Monitor traffic in usage/quota pages.

Example OpenAI-compatible request shape:

curl http://127.0.0.1:17171/v1/chat/completions \
  -H "Authorization: Bearer sk_rw_example" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "your-model-or-alias",
    "messages": [
      {"role": "user", "content": "Say hello"}
    ]
  }'

Use dashboard-generated key, not sk_rw_example.

Architecture

AI client
  │
  │ POST /v1/chat/completions
  ▼
Go server
  ├─ middleware: recovery, security, CORS, CSRF/auth as applicable
  ├─ v1 module: route, translate, route, fallback, usage accounting
  ├─ providers module: accounts, credentials, transport
  ├─ combos module: fallback chains and virtual routing
  ├─ quota/usage modules: accounting and analytics
  └─ SQLite: local persistent state
  │
  ▼
Upstream AI provider

Dashboard architecture:

Browser
  │
  ├─ Static Next.js app served by Go binary
  └─ /api/* JSON calls to Go backend

Build architecture:

web/ Next.js static export
  ▼ copied to
cmd/rouwang/web/out
  ▼ embedded by
//go:embed all:web/out
  ▼ served by
single Go binary

Data Model / Persistence

  • SQLite database stored in DATA_DIR.
  • Goose migrations are embedded from internal/database/migrations/*.sql.
  • GORM provides DB access.
  • Foreign keys, busy timeout, and WAL mode are enabled in SQLite DSN.

SQLite DSN behavior from code:

rouwang.db?_pragma=foreign_keys(1)&_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)

Security Notes

  • Default bind is 127.0.0.1, local-only.
  • Use HOST=0.0.0.0 only when network exposure is intended.
  • Use COOKIE_SECURE=true behind HTTPS.
  • Dashboard API modules are protected by dashboard session auth.
  • Provider credentials and API keys should stay in local data directory or Docker volume.
  • Do not commit .env, database files, generated secrets, or provider credentials.

Documentation Map

  • docs/README.md — spec-plan index and TL;DR.
  • docs/PRD.md — product requirements and goals.
  • docs/SPEC.md — implementation spec and feature pillars.
  • docs/ARCHITECTURE.md — detailed system architecture.
  • docs/OPEN-DECISIONS.md — locked decisions and pending decisions.
  • docs/M*.md — milestone documents.
  • docs/*HANDOFF*.md — session/UI handoff notes.
  • design-system/DESIGN.md — visual design canon.
  • mockups-fresh/ — static mockups and screenshots.

Common Commands

Task Command
Run backend go run ./cmd/rouwang
Run Go tests go test ./...
Build web cd web && npm install && npm run build
Typecheck web cd web && npm run typecheck
Build full app make build
Docker build docker build -t rouwang .
Docker Compose docker compose up --build

Troubleshooting

pattern all:web/out: no matching files found

Build frontend first and copy web/out into cmd/rouwang/web/out:

make web-build

Frontend dev calls fail

Ensure backend is running at:

http://127.0.0.1:17171

Next dev rewrites /api/* and /v1/* to that address.

Port already in use

Change port:

PORT=17172 go run ./cmd/rouwang

Then update client base URL accordingly.

Need clean local state

Stop server, back up if needed, then remove configured data directory. Default:

~/.rouwang

This deletes DB and generated secrets.

License

No license file currently present in repository.

About

Self-hosted local AI router with OpenAI-compatible API, provider fallback, usage tracking, quota tools, and dashboard UI.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages