Useful. Brutally Honest. Zero filters, no corporate fluff.
Just the answers you need with the grit you expect.
| Landing Page | Character Selection & Chat |
![]() |
|
| Voice Call Mode | RAG Knowledge Base |
![]() |
![]() |
SavageAI is a multi-agent AI chat platform where users interact with toxic AI personalities that actually solve your problems β just with zero patience for nonsense.
Unlike typical polished AI assistants, SavageAI characters have attitude. They'll roast you, compare you to the neighbor's kid, or tell you to go dig potatoes β but they'll also give you the correct answer.
| Character | Personality | Specialty |
|---|---|---|
| π₯ Angry Grandpa | Old-school curmudgeon. Thinks the modern world is soft. Real work was done with hands, not keyboards. | Grumpy but wise β gives you the right answer while complaining about everything |
| π Balkan Dad | Hot-headed Balkan tough guy. Loud, opinionated. Thinks he knows everything and has zero tolerance for nonsense. | Tough love. Compares you to the neighbor's kid. Still fixes your problem. |
| π‘ Corporate Shark | Ruthless business predator who measures everything in ROI. No time for excuses or feelings. | Cuts through the fluff. Gives brutal business advice. |
Each character has a unique voice in Voice Call mode (TTS via ElevenLabs), responds in your language, and delivers fully formatted answers with code blocks, markdown, and savage commentary.
- π΄ Real-Time Streaming Chat β Token-by-token streaming responses via OpenRouter. Optimistic UI, typing indicators, streaming cursor.
- ποΈ Voice Call Mode β Speak directly to your character. ElevenLabs TTS delivers each character's unique voice with live audio waveform animation.
- π RAG Knowledge Base β Upload your own documents (PDF, DOCX, CSV, TXT, Markdown, Code). Characters use your personal context when answering. Powered by pgvector + LangChain.
- 𧬠Multi-Model Routing β OpenRouter lets each character use the optimal AI model (Claude, GPT, Llama) for its personality.
- π Secure Auth β Supabase Auth with Row Level Security. Every user's data is isolated at the database level.
- π± Fully Responsive β Mobile-first dark UI. Sheet sidebar on mobile, persistent sidebar on desktop.
- ποΈ Conversation History β All chats are persisted and loadable. Auto-generated titles from first message.
- β‘ Rate Limited API β Every API route is protected with Upstash Redis rate limiting. No abuse.
- π§ͺ Tested β Unit tests (Vitest + Testing Library) and E2E tests (Playwright).
User (Browser)
β
Next.js 16.2 App Router
βββ proxy.ts β Optimistic auth routing (cookie-only, no DB)
βββ / (landing) β Public landing page
βββ /login, /signup β Auth pages with Server Actions + Zod validation
βββ /chat β New conversation + character selection
βββ /chat/[id] β Existing conversation with history
βββ /knowledge β RAG knowledge base management
βββ /api/chat β POST streaming endpoint β OpenRouter
/api/conversations β CRUD for conversations
/api/knowledge β RAG upload + management
Supabase (PostgreSQL + pgvector)
βββ auth.users β Supabase built-in auth
βββ profiles β User metadata, preferences
βββ conversations β Chat sessions (owned by user)
βββ messages β Chat history (streaming-safe persistence)
βββ knowledge_entries β RAG document chunks + embeddings
proxy.tsβ Next.js 16 file convention for optimistic auth checks (cookie-only, zero DB calls)- DAL (Data Access Layer) β All DB access goes through
src/lib/dal.ts, which enforces ownership after()β Post-response DB writes (saves messages after stream completes without blocking)- Streaming β
ReadableStreampiped from OpenRouter β browser, char-by-char rendering - Server Components by default β
'use client'only where strictly needed - Feature-based structure β Business logic lives in
src/features/, routes insrc/app/
| Layer | Technology |
|---|---|
| Framework | Next.js 16.2 (App Router, Turbopack, React Compiler) |
| UI | React 19, TailwindCSS v4, shadcn/ui, Radix UI |
| Auth & DB | Supabase (PostgreSQL, Row Level Security, pgvector) |
| AI Routing | OpenRouter API (multi-model: Claude, GPT, Llama) |
| RAG | LangChain + pgvector + OpenAI Embeddings |
| Voice (TTS) | ElevenLabs React SDK |
| Data Fetching | TanStack Query v5 (useQuery, useMutation) |
| Validation | Zod v4 |
| Rate Limiting | Upstash Redis + @upstash/ratelimit |
| Testing | Vitest + Testing Library + Playwright |
| Deployment | Vercel |
| Language | TypeScript (strict mode) |
- Node.js 20+
- npm
- Supabase account
- OpenRouter API key
- Upstash Redis instance
git clone https://github.com/Krasimir-Hristov/Savage-AI.git
cd Savage-AI
npm installCopy .env.example to .env.local and fill in your values:
cp .env.example .env.local# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# OpenRouter
OPENROUTER_API_KEY=sk-or-...
# Upstash Redis (rate limiting)
UPSTASH_REDIS_REST_URL=https://your-url.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-token
# ElevenLabs (TTS)
ELEVENLABS_API_KEY=your-key
NEXT_PUBLIC_ELEVENLABS_AGENT_ID=your-agent-idRun the migrations against your Supabase project:
# Via Supabase CLI
supabase db push
# Or apply manually via Supabase SQL editor
# Files: supabase/migrations/npm run devOpen http://localhost:3000.
# Unit tests (Vitest)
npm test
# Run once with coverage
npm run test:coverage
# E2E tests (Playwright)
npm run test:e2esrc/
βββ app/ # Next.js routes (thin layer β no business logic)
β βββ proxy.ts # Auth routing (Next.js 16 convention)
β βββ (auth)/ # /login, /signup
β βββ (main)/ # Authenticated area (/chat, /knowledge)
β βββ api/ # API routes (chat, conversations, knowledge, tts)
β
βββ features/ # Feature modules (business logic lives here)
β βββ auth/ # Login/signup forms, actions, Zod schemas
β βββ chat/ # Chat components, hooks, streaming
β βββ characters/ # Character definitions, system prompts, cards
β βββ rag/ # Knowledge base: upload, embed, search
β βββ tts/ # Voice call components
β
βββ lib/
β βββ supabase/ # Browser, server, admin clients
β βββ openrouter/ # Streaming client (server-only)
β βββ dal.ts # Data Access Layer (auth-enforced queries)
β βββ ratelimit.ts # Upstash rate limit helpers
β βββ utils.ts # cn(), formatDate(), etc.
β
βββ types/ # Global TypeScript types
βββ database.ts # Supabase-generated types
βββ chat.ts # Message, Conversation
βββ character.ts # Character interface
- Row Level Security on all Supabase tables β users can only access their own data
- DAL enforces ownership on every query β no relying on client-side filtering
proxy.tsuses cookie-only session checks β zero DB calls on route transitions- Server-only imports (
import 'server-only') prevent API keys from reaching the browser - Zod validation on all API inputs and Server Actions
- Rate limiting on every API route via Upstash Redis
- httpOnly cookies for session management via
@supabase/ssr
MIT β do whatever you want, just don't be a corporate shark about it.
Built with rage, caffeine, and zero tolerance for boring AI.


