dwgx@blog:~$dwgx
> cd ../posts

skiapi-frontend: A frontend console for the NewAPI/SKIAPI gateway

// created

skiapi-frontend is a pure frontend console I wrote for my own SKIAPI deployment, with the backend running on NewAPI-compatible interfaces. Tech stack is React 19 + Vite + MUI v7, a single-page app that talks to the backend over /api and /v1. It handles the frontend only; auth, billing, routing, and keys are all backed by the backend. Channels, users, tokens, logs, billing, redemption codes, model routing, and system settings are all managed in the browser.

Channels are the focus. Over fifty upstreams are supported: OpenAI, Azure, Claude, Gemini/Vertex, DeepSeek, xAI, Ollama, OpenRouter, Tongyi, Zhipu, Moonshot, plus the likes of Midjourney and Suno. Each one comes with a test dialog, so one click tells you whether it’s reachable, no need to dig through backend logs guessing which one is down.

Users come in three tiers: regular, admin, and super admin. Payments hook up Alipay, WeChat, Stripe, Creem, and Waffo. There’s an in-browser Playground and Chat, so once a model is set up you can try it on the spot. It also packs in an AI assistant with tool calling (src/components/common/AiAssistant.jsx), so you can just ask it things while working in the admin panel. i18next covers seven languages, default Simplified Chinese, with Japanese deliberately kept in since I’m in Kobe.

Fault tolerance is something I ground out bit by bit in production. Browser extensions injecting junk into the DOM would crash React, so I added a DOM patch to block that; old chunks failing to load after a new release got a retry; if it won’t start up, a startup watchdog falls back to /legacy/; and the API layer does request deduplication.

Development is the usual routine: npm install then npm run dev. The dev server proxies /api and /v1 to http://127.0.0.1:3001 by default; set VITE_PROXY_TARGET to point at a different backend. Deployment goes through scripts/deploy.py, which does build, package, SSH transfer, switch the static directory, and reload nginx all in one, then runs a smoke test afterward. The version number is still stuck at 0.0.0 with no proper release, but it’s been running on my real deployment all along.