TenuChat (AI Chatbot)

React, TypeScript, NodeJS, Tailwind CSS

Main project image

Tenu Chat is a full-stack AI chat application built with React, TypeScript, and Express, featuring real-time streaming responses, markdown rendering, bilingual support (EN/ES), and dark/light mode.

Visit the aplication ↗

Table of Contents

  1. Overview
  2. Key Features
  3. Role
  4. Goal
  5. Challenges and Learnings
  6. Final Thoughts

Overview

Tenu Chat is a simple chat application where you can talk to a custom-trained AI bot in real time. It features streaming responses, markdown rendering, bilingual support (English/Spanish), dark/light mode, and a responsive layout that works on both mobile and desktop.

Note: The app is hosted on Render’s free tier, if it’s been inactive, the server may take a moment to spin up. Give it a few seconds and the page will load.


Key Features

  1. Streaming Responses: AI tokens appear in real time as they’re generated via Server-Sent Events (SSE).
  2. Secure Proxy Architecture: API keys, system prompts, and model names are injected server-side — never exposed to the browser bundle.
  3. Markdown Rendering: Assistant messages support rich formatting (headings, lists, code blocks, links) with sanitized link protocols.
  4. Bilingual Support: Full UI translation between English and Spanish via a custom lightweight i18n layer.
  5. Dark/Light Mode: Toggle via header button with a custom brand accent color and Inter font typography.
  6. Responsive Design: Layout adapts at all breakpoints; sidebar collapses gracefully on smaller screens.
  7. Security First: Helmet headers, rate limiting (20 req/min), body size limits, error masking, and no data persistence.

Role

Lead Developer


Goal

  1. Build a clean, minimalist AI chat app with real-time streaming responses.
  2. Demonstrate a secure server-proxy pattern where the client never touches sensitive data.
  3. Deliver a polished, bilingual, responsive UI that works seamlessly across mobile and desktop.

Challenges and Learnings

  1. SSE Streaming: Implementing an async generator pattern to parse SSE streams token-by-token from OpenRouter through the Express proxy to the client.
  2. Security Architecture: Designing the proxy so API keys, system prompts, and model names are injected server-side, with rate limiting, Helmet headers, and error masking to prevent data leakage.
  3. Smart Auto-Scroll: Tracking whether the user has scrolled up and only auto-scrolling if they’re near the bottom, avoiding the frustrating behavior of being scrolled down while reading.
  4. Lightweight i18n: Building a typed dictionary-based translation system instead of pulling in a full i18n library, keeping the bundle small with full TypeScript safety.

Final Thoughts

  1. Security by Design: Keeping sensitive data server-side from the start is far easier than retrofitting it — the proxy pattern should be the default for any AI chat app.
  2. Clean UX Matters: Streaming responses, smart auto-scroll, and a minimalist UI make the chat feel fast and natural, which is what users expect from modern AI tools.