RD Chat — AI Chat & Text Analyzer
A ChatGPT-grade streaming chat and a structured text analyzer, built from scratch — token-by-token SSE, typewriter rendering, and Zod-validated JSON output.
- React 19
- TypeScript
- Vite
- Express 5
- Gemini
- SSE
- Zod
- Tailwind
A dual-tool app with no chat SDK: a real-time streaming chat that renders Gemini's output token by token, and a text analyzer that turns free text into Zod-validated structured JSON. Built from scratch on an Express 5 backend and a React 19 + Vite frontend, with a hand-rolled SSE pipeline and deliberate UX polish.
// Problem
Off-the-shelf chat SDKs hide the streaming pipeline behind a black box, and free-text input is hard to act on programmatically. I wanted to build the streaming UX by hand and pair it with a tool that turns prose into reliable, typed data.
// Approach
Two tools in one app. The chat streams model output token by token over Server-Sent Events with a typewriter reveal; the analyzer takes free text and returns a fixed JSON shape — topics, sentiment, summary, action items, and follow-up questions — validated before it ever reaches the client.
// Architecture
An Express 5 / Node backend calls Google Gemini and pipes the response as a text/event-stream; the React 19 + Vite frontend decodes it with a ReadableStream reader and drives the typewriter with requestAnimationFrame so rendering is decoupled from network arrival. Generation is abortable mid-stream via AbortController, conversation history persists in localStorage, and a smart auto-scroll respects where the user is reading. The analyze endpoint validates its output against a Zod schema; the backend adds rate limiting, Helmet security headers, and input validation. React Router 7 splits the Chat and Analyzer tools, styled with Tailwind v4 and shadcn/ui.
// Outcome
A from-scratch streaming chat that feels SDK-grade — smooth typewriter output, cancellable generation, persistent history — plus a structured analyzer that reliably converts free text into validated JSON, all on a single hardened Express backend.