2026 · Co-Founder & Software Engineer, ShapAI

mianGPT

A multi-model AI chat platform with a Django/OpenRouter backend and a streaming Next.js PWA frontend, unifying a web app and a Telegram bot behind one credit-billed API.

Next.jsDjangoPostgreSQLRedisDockerNginx

Overview

mianGPT is a multi-model AI chat product: users pick from a catalog of LLMs synced live from OpenRouter, chat through a streaming web interface or a Telegram bot, and pay per token from a wallet billed in Toman. The system serves two very different clients — a Next.js PWA and a Telegram bot — from one Django backend, which shaped most of the interesting engineering decisions.

One pipeline, two clients

The chat logic — build the message payload, call OpenRouter, stream the response, persist the assistant message, deduct credit — is written once as a shared async generator and reused by both the web SSE endpoint and the bot endpoint. The alternative, duplicating that logic per client, would have meant two billing implementations quietly drifting apart. Instead the two surfaces differ only where they have to: the web app authenticates with JWT and speaks REST plus SSE, while the bot authenticates with a static API key and gets endpoints shaped to match the schema of the Telegram bot's original SQLite database, so migrating existing bot users onto the new backend didn't require touching the bot's own logic.

Billing on live exchange rates

Wallet balances are held in Toman, but every model's cost from OpenRouter arrives in USD per token. Billing pulls the USD-to-Toman rate live from the Bitpin API on a short cache window, with a database-configurable fallback rate for when that call fails, so a pricing-provider outage degrades to a stale rate instead of breaking checkout. Per-model prices can be pinned by an admin independently of what OpenRouter reports, which matters because "pass through the raw provider cost" and "the price we want to charge" are not always the same policy, and the system needed room for both.

Frontend

The web client is a Next.js PWA — a real one, with a generated service worker, offline caching, and an install prompt, not just a manifest file bolted onto a normal site. Chat responses stream token-by-token through streamdown, rendering Markdown, LaTeX math, code blocks, and Mermaid diagrams as they arrive rather than waiting for the full response. State is split the same way across this codebase as elsewhere: TanStack Query owns server state, Zustand owns the client-only state, and forms run through React Hook Form with Zod schemas shared with the API layer.

Delivery

Both services are containerized and run behind Nginx, with Redis backing OTP state and API throttling and PostgreSQL as the system of record. Attachment uploads go through MinIO/S3-compatible storage, and the backend enforces that an upload has actually finished — non-zero size, 201 returned — before it can be attached to a message, closing a race where a message sent mid-upload would silently reference an empty file.