NotT3Chat: The C# Answer to the T3 Stack
November 18, 2025 Β· View on GitHub
Welcome to NotT3Chat, a fully-featured, real-time chat application built for the cloneathon.t3.chat. This project serves as a testament to the raw power and elegance of C# and ASP.NET Core, proving that you don't need TypeScript to build amazing, modern web applications. (Sorry, Theo.)
Too much bullshit just take me to Getting Started.
Check out the demo!

π€ Why?
Why build another chat app? Two reasons:
- To participate in the T3 Clone-a-thon and have some fun.
- To lovingly poke at the T3 stack and demonstrate that a robust, type-safe, and high-performance application can be built with the glorious combination of C# on the backend and plain ol' JavaScript on the front. It's a love letter to backend developers who appreciate strongly-typed languages that aren't a superset of JavaScript.
β¨ Core Features
This is far from just a "hello world" chat. We've packed in some serious features:
- π€ Multi-LLM Support: Seamlessly switch between different models and providers (OpenAI, Google, Anthropic, Groq, DeepSeek, and more). Add custom providers via config.
- β‘ Blazing-Fast Real-Time Chat: Built with the magic of SignalR, messages stream in real-time.
- π Advanced Stream Resumption: Did you close your browser tab mid-stream? No problem. Re-open the chat, and the stream will pick up right where it left off.
- π€ Multi-Session Sync: Open the same chat in multiple windows or on different devices, and watch the messages stream in perfect sync across all of them.
- π Flexible Authentication: Email/password login and/or Google OAuth. Configure what you need.
- π¨ Customizable Branding: Custom fonts, logos, titles, and icons via environment variables.
- π Chat History: All your conversations are saved and can be revisited anytime.
- π Smart Message Limits: 64KB message size limit with visual warnings to prevent context overflow.
- π‘οΈ Repetition Loop Detection: Automatically detects and stops infinite LLM loops using n-gram analysis.
π οΈ Tech Stack & How It Was Built
This project was a collaboration between human and machine.
Backend
The backend was primarily built by me, with some expert consulting from Sonnet 4. The goal was a lean, powerful, and scalable foundation using ASP.NET Core 8. The multi-LLM support is powered by the fantastic LlmTornado.Toolkit library β a huge shout-out for making the integration so seamless. Hoping to move to ASP.NET Core 10 soon.
Frontend
The UI was mostly crafted with the help of Claude Code. It was a surprisingly smooth experience, resulting in a clean, component-based React app built with Vite and styled with MUI.
π Getting Started
Prerequisites
- .NET SDK 8.0
- On Ubuntu 22+:
apt update && apt install dotnet-sdk-8.0
- On Ubuntu 22+:
- Node.js v18+
1. Launching the Backend
The backend runs on port http://localhost:5128 by default in debug mode.
Configuration:
The backend reads configuration from environment variables and appsettings.json:
# LLM Provider API Keys
# Options: GOOGLE_API_KEY, OAI_API_KEY, OPENROUTER_API_KEY, ANTHROPIC_API_KEY, COHERE_API_KEY, GROQ_API_KEY, DEEPSEEK_API_KEY, MISTRAL_API_KEY, XAI_API_KEY, PERPLEXITY_API_KEY
export XXXXXX_API_KEY=... # or use dotnet user-secrets set, better
# Optional: Filter which models to display
export NOTT3CHAT_MODELS_FILTER=gpt-4o-mini,gemini-2.0-flash-001,gemini-2.0-flash-lite-001
# Optional: Model for chat title generation (default: gemini-2.0-flash-lite-001)
export NOTT3CHAT_TITLE_MODEL=gemini-2.0-flash-lite-001
# Optional: Google OAuth (requires Google Cloud Console setup)
dotnet user-secrets set "Authentication:Google:ClientId" "your-client-id"
dotnet user-secrets set "Authentication:Google:ClientSecret" "your-client-secret"
Edit appsettings.json for additional settings:
{
"Authentication": {
"UseGoogle": false, // Enable Google OAuth login
"UseIdentity": true // Enable email/password login
},
"CustomProviders": [ // Add custom LLM providers
{
"Name": "MyProvider",
"BaseUrl": "https://api.example.com/v1",
"ApiKey": "your-key", // can also be specific "CustomProviders:0:ApiKey"
"Models": ["model-name-1", "model-name-2"]
}
],
"FrontEndUrl": "http://localhost:5173" // For OAuth redirects
}
Debug Mode:
dotnet run --project backend/NotT3ChatBackend.csproj
Note: The first time you run this, it will create a
databse.datSQLite file. When running in debug it will seed it with a default user:
- Username:
admin@example.com- Password:
admin
Production Mode:
# Build for production
dotnet publish backend/NotT3ChatBackend.csproj -c Release -o publish
# Run the published app (example on port 5555)
dotnet publish/NotT3ChatBackend.dll --urls http://0.0.0.0:5555
A few warnings:
- We use MemoryCache right now for synchronization, we will use Redis in the future but this means that it only works on a single server instance, no load balancer.
- Cors policy right now is any domain allowed, feel free to change it yourself.
- The password requirements are very minimal, feel free to change it yourself.
2. Launching the Frontend
The frontend dev server will connect to the backend API.
# Navigate to the frontend directory
cd front-end
# Install dependencies
npm install
# Run the dev server
# Make sure this URL matches your backend's URL
VITE_API_URL=http://localhost:5128 npm run dev
Frontend Configuration:
Create a .env file in the front-end directory with these optional settings:
# Required: Backend API URL
VITE_API_URL=http://localhost:5128
# Optional: Custom branding
VITE_APP_TITLE=NotT3Chat
VITE_APP_SLOGAN=Your AI Chat Companion
VITE_CUSTOM_FONT_URL=https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap
VITE_CUSTOM_FONT_FAMILY=Inter
VITE_CUSTOM_ASSISTANT_ICON_URL=https://example.com/icon.png
VITE_CUSTOM_PROVIDER_FALLBACK_ICON_URL=https://example.com/provider-icon.png
# Optional: Authentication methods (defaults to true for identity, false for google)
VITE_USE_IDENTITY_AUTH=true
VITE_USE_GOOGLE_AUTH=false
# Optional: Terms of Service link
VITE_TERMS_OF_SERVICE_URL=https://example.com/terms
πΊοΈ Roadmap & Future Features
Here's a non-exhaustive list of what's planned when I get around to it:
- Attachments (files, images)
- Better syntax highlighting for code blocks
- Even better syntax highlighting, with copy buttons
- Branching conversations
- Tools (like web search)
- Image generation
- Chat sharing via public links
- Bring Your Own Key (BYOK) for API providers
- Regenerate message (or regenerate with a different model)
- Delete chats
- Delete individual messages?
- Intelligent, automatic naming for new chats
- Search through threads
- Make it prettier?
- Thinking models
π» Developer's Corner
Some notes on the current state of the codebase for aspiring contributors.
Backend Philosophy
The backend is currently in a single Program.cs file. This is an intentional experiment in anticipation of .NET 10's enhanced support for single-file applications (dotnet run app.cs). We are going to split it into a more traditional file structure for clarity soon. It's a WIP!
Frontend Styling Rules
To maintain sanity without TypeScript, we follow a few simple styling rules:
- Component Styling: Use components from MUI whenever possible.
- Class Names: For multiple conditional class names on an element, use the
light-classnameslibrary. - No Inline Styles: All styling should be done via class names in dedicated
.cssfiles. No inlinestyleorsxprops. - No
!important: If you feel the need to use!important, take a break, have some water, and refactor.
Technical To-Do List
- Graceful error handling (e.g., 429 Too Many Requests, content filter blocks). (More or less done, can always be improved)
- Streamline adding new models via environment variables instead of code changes.
- Add configuration to easily switch between db providers (In-Memory, SQLite, PostgreSQL, etc.).
- Consider segmenting larger UI components into smaller, more focused ones.
- Add an easy way to specify a default user account via environment variables for local development.
- Logging
- Add configuration to move to redis for distributed cache for better synchronization & locking for actively streaming chats.
- Fix general chat events to always stream (delete, title, new)
π€ Contributing
Contributions are what make the open-source community such an amazing place to learn, inspire, and create. All contributions are more than welcome! Feel free to fork the repo, create a feature branch, and open a pull request.
π License
This project is licensed under the MIT License.