Skip to content

lukmanc405/9router-miniapp

Repository files navigation

9router Mini App

A mobile-first read-only dashboard for 9router — the AI Router & Token Saver. Built as a Telegram Mini App on top of Hermes Agent.

It reads 9router's local SQLite database directly (read-only), so it works without the dashboard password, has no session expiry, and never touches 9router's runtime. No tokens or secrets are ever exposed — API keys are masked, raw OAuth/refresh tokens and client secrets stay server-side.

Features

  • ⚡ Overview — requests, cost, and tokens today, lifetime requests, provider health, RTK / proxy feature state
  • 🔌 Providers — connection status per account (Kiro, Xiaomi MiMo, etc.), auth type, OAuth token expiry, last error, last-used time
  • 📊 Usage — breakdown by model and by provider, sorted by cost (requests, in/out tokens, cost)
  • 📜 Logs — 50 most recent requests, tap to expand for latency, tokens, cost, endpoint, and error details
  • ⚙️ Settings — API base URL config + backend health check

Install Instantly via AI Agent

If you use an AI coding agent, paste this prompt and it handles everything (clone → deps → secure password → build → run → CF tunnel → hardening):

Install 9router-miniapp from https://github.com/lukmanc405/9router-miniapp
Read SKILL.md in the repo root first and follow it step by step.
9router is already running on localhost:20128. Set a strong APP_PASSWORD,
build, start the service, and apply the Step 7 security hardening.

For Hermes Agent specifically: skill_view(name='9router-miniapp-deploy')

The agent reads SKILL.md (full playbook: prerequisites, 9 install steps, CF tunnel + IP/API hardening, security limitations, verification). See AI Agent Installation at the bottom for details.

Install Methods

Option A — npm create (recommended, fastest)

npm create 9router-miniapp@latest my-dashboard
cd my-dashboard
npm run build
cd server && node index.js

Auto-generates secure APP_PASSWORD, installs all deps, prints next steps. Requires repo to be public.

Option B — npx degit (no git history)

npx degit lukmanc405/9router-miniapp my-dashboard
cd my-dashboard
npm install && cd server && npm install && cd ..
cp .env.example .env
# Edit .env → set APP_PASSWORD
npm run build && cd server && node index.js

Option C — git clone (full history, for contributors)

git clone https://github.com/lukmanc405/9router-miniapp.git
cd 9router-miniapp
npm install && cd server && npm install && cd ..
cp .env.example .env
# Edit .env → set APP_PASSWORD
npm run build && cd server && node index.js

Option D — GitHub template

Click "Use this template" button on the GitHub repo page → creates a new repo under your account with the full source.


After install: open http://localhost:9122, log in with your APP_PASSWORD. For production deployment + security hardening, read SKILL.md or paste the AI Agent prompt above.

Quick Start (Manual)

# 1. Clone
git clone https://github.com/lukmanc405/9router-miniapp.git
cd 9router-miniapp

# 2. Install dependencies
npm install
cd server && npm install && cd ..

# 3. Configure environment
cp .env.example .env
# Edit .env — set NROUTER_DB to your 9router SQLite path (default: ~/.9router/db/data.sqlite)

# 4. Build the frontend
npm run build

# 5. Start the server
cd server && node index.js

Open http://localhost:9122 to preview.

Architecture

├── src/                      # React 19 + Vite + TypeScript frontend
│   ├── config.ts             # App name, version, API base URL
│   ├── types.ts              # Shared TS types (mirror server responses)
│   ├── App.tsx               # Tab nav (Overview / Providers / Usage / Logs / Settings)
│   ├── pages/
│   │   ├── Home.tsx          # Overview — daily stats + provider health
│   │   ├── Providers.tsx     # Per-connection status + errors
│   │   ├── Models.tsx        # Usage breakdown (models / providers toggle)
│   │   ├── Logs.tsx          # Recent request logs (expandable)
│   │   └── Settings.tsx      # API config + backend health
│   └── lib/api.ts            # Fetch wrapper
├── server/
│   ├── index.js              # Express API + static file serving
│   └── lib/nrouter.js        # Read-only 9router SQLite data layer (sanitized)
└── .env.example

API Endpoints

All under /api/ (Caddy handle_path /app/* strips the /app prefix before forwarding).

Endpoint Returns
GET /api/health Server + DB health
GET /api/overview Aggregate stats for Overview
GET /api/providers Provider connections (sanitized)
GET /api/breakdown/models Today's usage per model
GET /api/breakdown/providers Today's usage per provider
GET /api/usage/today Raw daily usage
GET /api/usage/:date Usage for a specific day (YYYY-MM-DD)
GET /api/logs?limit=50 Recent request logs
GET /api/keys API keys (masked)
GET /api/combos Model combo groups
GET /api/settings Sanitized settings (no password hash)

Environment Variables

Variable Default Description
PORT 9122 Server port
CORS_ORIGIN * Allowed CORS origin
NROUTER_DB ~/.9router/db/data.sqlite Path to 9router's SQLite DB (read-only)
NROUTER_URL http://localhost:20128 9router HTTP API base URL
APP_PASSWORD (none) Login password. If unset, dashboard is open (dev mode)
MINIAPP_BOT_TOKEN (none) Telegram Bot token for Mini App initData auth (optional)

Security Setup

The app generates runtime secrets automatically on first start. These are stored in ~/.9router/ and never committed to git:

File Purpose
~/.9router/miniapp-session-secret HMAC key for session cookies (auto-generated)
~/.9router/miniapp-webauthn.json WebAuthn credential store (created on first passkey registration)
~/.9router/jwt-secret JWT signing key for 9router API proxy auth

To set up authentication:

# 1. Set a password in .env
echo "APP_PASSWORD=your-secure-password" >> .env

# 2. (Optional) Create a .PASSWORD file instead
echo "your-secure-password" > .PASSWORD
chmod 600 .PASSWORD

# 3. Start the server — session secret is auto-generated on first run
cd server && node index.js

Once logged in with the password, you can register a WebAuthn passkey (Face ID / Touch ID / security key) from the app UI for passwordless login on subsequent visits.

Security Notes

  • The database is opened read-only (better-sqlite3 with readonly: true).
  • The data layer in server/lib/nrouter.js sanitizes every response:
    • API keys → masked preview (tp-s…uu95)
    • OAuth access/refresh tokens → never returned
    • Client secrets → never returned
    • Dashboard password hash → never returned
  • This is a monitoring dashboard. It does not write to 9router or proxy any AI requests.

⚠️ Known Security Limitations (READ BEFORE PUBLIC DEPLOY)

Two app-level hardening gaps exist. Neither leaks secrets, and both are fully mitigated by fronting the app with Cloudflare Access + firewall (see SKILL.md Step 7), but you must address them before exposing publicly:

1. No rate limiting on /api/login — the login endpoint accepts unlimited attempts. If the URL leaks without edge protection, APP_PASSWORD can be brute-forced. Mitigate with Cloudflare Access, a CF WAF rate rule (5 req/min/IP), or an app-level limiter. Always use a strong password (openssl rand -base64 24).

2. CORS wildcard + credentials — default CORS_ORIGIN=* with credentials: true is a CSRF risk in production. Set CORS_ORIGIN to your exact HTTPS domain before deploying:

sed -i "s|^CORS_ORIGIN=.*|CORS_ORIGIN=https://9router.yourdomain.com|" .env

Leave * only for local dev. Session cookies are SameSite=Lax which already blocks most CSRF.

Full mitigation steps and copy-paste code are in SKILL.mdKnown Security Limitations.

Deployment

Cloudflare Tunnel

cloudflared tunnel --url http://localhost:9122

Caddy

your-domain.com {
    handle_path /app/* {
        reverse_proxy 127.0.0.1:9122
    }
}

Connect to Telegram Bot

  1. Open @BotFather
  2. Your bot → Bot SettingsMenu ButtonConfigure
  3. Set URL to your deployed HTTPS URL

License

MIT

AI Agent Installation

If you're using an AI coding agent (Hermes, Cursor, Claude, etc.), load the SKILL.md file in this repo root before starting. It contains the full step-by-step installation, configuration, security setup, and deployment procedure so the agent can install and configure the miniapp end-to-end without missing steps.

# For Hermes Agent:
skill_view(name='9router-miniapp-deploy')

# Or just point your agent to:
cat SKILL.md

About

Mobile-first read-only dashboard for 9router (AI Router & Token Saver) — Telegram Mini App, React + WebAuthn

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors