Freelance client project — three front ends and the AI backend for a 1,000+ staff manufacturer: executive dashboards replace hand-built Excel reports, and a company-wide AI assistant answers from the firm's own documents, with citations.

A consumer-electronics manufacturer (1,000+ staff, mostly on the production line) reported production by hand: a backend colleague ran SQL queries, another turned the results into Excel or PowerPoint, and that deck was what executives actually saw. I was brought in as a freelance full-stack developer (2025-06 to 2025-10) to replace that chain with live dashboards, and to build a company-wide AI knowledge assistant on top of the firm's own documents. I built three React front ends — a unified login / permission portal, 16+ production reports with AI-streamed analysis, and the knowledge-assistant UI — plus the Spring Boot orchestration layer behind the assistant. Executives now read reports themselves and catch production issues early enough to fix them; the assistant is open to the whole company. Screens recreated with sample data; client identity withheld under NDA.
Before this project, seeing how the factory floor was doing meant waiting on a chain of people: a backend colleague would run SQL queries, another colleague would turn the results into Excel sheets or a PowerPoint deck, and only then did a report reach the executives — hours or days after the numbers were current. Nobody outside that chain could just go look. I was brought in as a freelance full-stack developer (2025-06 to 2025-10) to replace it with dashboards executives could open themselves, and to give the whole company — 1,000+ staff, mostly on the production line — a single place to ask questions against the firm's own documents instead of hunting for the right person to ask.
A single sign-on portal in front of the other systems: username / password plus DingTalk auto-login, with other systems redirecting here first and bouncing back with a token afterwards — the return-URL is checked against an allowlist so it can't be turned into an open redirect. Access is modelled as user → role → permission tree, split into menu-level and button-level permission codes (17 in total), across 7 pages wired to roughly 85 backend endpoints.
A "Report Center" used inside DingTalk by office staff and line managers: 16+ report pages covering shipments, AOI colour / appearance yield (down to the furnace batch), TT-station production tracking, PVD tracking reports, and TDM lead time — the time from incoming-material registration to first shipment, shown as a P25 / median / P75 distribution, with an internal variant that adds an Excel import / export data centre. 24 business-specific chart and table components sit on top of 6 reusable chart primitives (bar, line, area, combo, pie, plus gauges and number cards), built on Recharts inside shadcn/ui's chart components, with one-click PNG export and Excel export, and caching tuned for DingTalk's in-app webview. Reports refresh on query — down to the hour — rather than push updates in real time.
About 20 of the report pages have an AI-analysis button wired in: one click streams back a written explanation of the chart in front of you, with the model's reasoning shown as a collapsible trace above the final answer. It's the fastest path from "here's a chart" to "here's what's going on and why" without waiting for someone to write a commentary slide.
Unlike the dashboards (fewer than 10 executives), this front end is open to everyone. It has two modes: "Knowledge Q&A" answers from documents the company has uploaded, with clickable inline citations that preview or download the source file; "AI Chat" lets staff pick a built-in assistant role or write their own system prompt, and attach a file for the model to read. A separate knowledge-management page handles batch upload of PDF / DOC / DOCX / XLSX / XLS, polling each file's status until processing finishes. I parsed the server's streamed response myself with fetch + ReadableStream (no SSE library), rendered a collapsible reasoning section, resolved inline citation markers into hoverable references, and kept multi-turn history per session with renaming. The retrieval and generation themselves run in a managed knowledge service behind a separate backend — this front end is the interface and the API integration, not the RAG pipeline.
Behind the knowledge assistant sits a Spring Boot 3.4 / Java 17 service I wrote to orchestrate, not to re-implement, retrieval and generation. Query rewriting, recall and rerank happen in a managed knowledge-service API; the hosted LLM does the generation. My layer sits around that: it filters retrieved chunks by a score threshold before they're used as citations, streams the response back over a bounded thread pool using Spring's SseEmitter (parsing the upstream SSE line-by-line and re-emitting typed events — metadata, answer, reasoning, end, error), and runs a separate chat mode against the LLM with two built-in roles plus custom system prompts. For documents: Word files go straight into the knowledge base; PDFs are rendered to images, and scanned or table-heavy pages that yield little extractable text are handed to a vision-capable model so they stay searchable too. Deletes are applied in order across the knowledge service, object storage and the database so the three stay consistent. This was in production for internal use, not hardened for public exposure — there's no auth on the endpoints yet and that's on the list for whoever maintains it next.
Front ends (×3): React 19, TypeScript (strict), Vite 7, Bun, TanStack Router / Query / Table, Zod 4 (validates every API response), shadcn/ui + Tailwind CSS 4, Recharts inside shadcn/ui Charts for the dashboards, Vercel AI Elements + react-markdown + KaTeX for the knowledge assistant.
Backend: Spring Boot 3.4, Java 17, MySQL via MyBatis-Plus, Spring MVC SseEmitter for streaming, Apache POI (Word) and PDFBox (PDF) for document text extraction.
AI: a managed knowledge-service API for retrieval, a hosted LLM for generation and vision-based text extraction from scanned documents.
Deploy: PM2 (front ends), PM2 + Nginx (dashboard), inside the client's own infrastructure.