Skip to content

Commit 3e69332

Browse files
committed
Rebrand
1 parent 44c9303 commit 3e69332

39 files changed

Lines changed: 721 additions & 397 deletions

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44

55
## Project Overview
66

7-
T3Chat is an open-source AI chat application built with the T3 stack. It supports multiple LLM providers (OpenAI, Google, Anthropic) routed through a TypeGPT API proxy, with Stripe subscriptions (FREE/PRO tiers), Google OAuth, and real-time streaming responses.
7+
RouterAI is an open-source AI chat application. It supports multiple LLM providers (OpenAI, Google, Anthropic) with Stripe subscriptions (FREE/PRO tiers), Google OAuth, and real-time streaming responses.
88

99
## Commands
1010

README.md

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
1-
# 𝙏3𝙘𝒉𝙖𝒕
1+
# RouterAI
22

3-
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2F100xEnginners%2Ft3dotgg&env=DATABASE_URL,BETTER_AUTH_SECRET,BETTER_AUTH_URL,BETTER_AUTH_TRUSTED_ORIGINS,GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GOOGLE_REDIRECT_URI,GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET&envDescription=For%20more%20info%20on%20setting%20up%20your%20API%20keys%2C%20checkout%20the%20Readme%20below&envLink=https%3A%2F%2Fgithub.com%2F100xEnginners%2Ft3dotgg%2Fblob%2Fmain%2FREADME.md&project-name=t3chat&repository-name=t3chat&redirect-url=t3chat&demo-title=T3chat&demo-description=An%20open%20source%20t3chat%20clone&demo-url=t3chat.xyz)
3+
An open-source AI chat application that routes your prompts to multiple LLM providers — all in one place.
44

5-
An Open-Source Version of t3.chat.
5+
## What is RouterAI?
66

7-
## What is T3.chat?
7+
RouterAI is a fast and sleek AI chat application that lets you talk to multiple AI models from different providers (OpenAI, Google, Anthropic) through a single, unified interface.
88

9-
T3 Chat is a fast and sleek AI chat application.
9+
## Why RouterAI?
1010

11-
it's "best AI chat app ever made" ~ Theo
12-
13-
## Why T3chat?
14-
It supports different LLM, respond very fast, user friendly, have customization, cheap.
11+
It supports different LLMs, responds fast, is user friendly, has customization, and is affordable.
1512
-**Open-Source** – No hidden agendas, fully transparent.
1613
- 🚀 **Developer-Friendly** – Built with extensibility and integrations in mind.
1714

1815
## Tech Stack
1916

20-
T3 is built with modern and reliable technologies:
17+
RouterAI is built with modern and reliable technologies:
2118

2219
- **Frontend**: Next.js, TypeScript, TailwindCSS, Shadcn UI
2320
- **Backend**: tRPC, Prisma ORM
2421
- **Database**: PostgreSQL
2522
- **Authentication**: Google OAuth
26-
- **Overall**: We're using t3 stack 💙
2723
<!-- - **Testing**: Jest, React Testing Library -->
2824

2925
## Getting Started
@@ -85,16 +81,16 @@ For more in-depth information on environment variables, please refer to the [Env
8581
```
8682
### Environment Variables
8783
88-
Copy `.env.example` located in `.env` in the configure the following variables:
84+
Copy `.env.example` to `.env` and configure the following variables:
8985
9086
```env
9187
# Auth
92-
AUTH_TRUST_HOST=
88+
AUTH_TRUST_HOST=
9389
AUTH_SECRET= # Required: Secret key for authentication
9490
9591
# Google OAuth ( Required )
96-
GOOGLE_CLIENT_ID=
97-
GOOGLE_CLIENT_SECRET=
92+
GOOGLE_CLIENT_ID=
93+
GOOGLE_CLIENT_SECRET=
9894
9995
# Turnstile ( Required )
10096
NEXT_PUBLIC_TURNSTILE_SITE_KEY=
@@ -108,25 +104,23 @@ STRIPE_WEBHOOK_SECRET=
108104
109105
# Upstash ( Required )
110106
UPSTASH_REDIS_REST_URL=
111-
UPSTASH_REDIS_REST_TOKEN =
107+
UPSTASH_REDIS_REST_TOKEN =
112108
113109
# Mail ( Optional )
114110
MAIL_APP_USER =
115-
MAIL_APP_PASSWORD =
116-
117-
# TypeGPT ( Required )
118-
NEXT_PUBLIC_TYPEGPT_API_KEY=
119-
TYPEGPT_API_KEY=
120-
TYPEGPT_API_URL=
111+
MAIL_APP_PASSWORD =
121112
122-
# Discord webhook ( Optinal )
113+
# Discord webhook ( Optional )
123114
WEBHOOK_URL
124115
125116
# Database ( Required )
126-
DATABASE_URL=
117+
DATABASE_URL=
118+
119+
# GROQ ( Required )
120+
GROQ_API_KEY=
127121
```
128122

129-
Migration the database by running `bunx prisma migrate dev` and generate prisma client `bunx prisma generate`.
123+
Run the database migration with `bunx prisma migrate dev` and generate the Prisma client with `bunx prisma generate`.
130124

131125

132126
### Running Locally
@@ -140,4 +134,4 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the
140134

141135
## Contribute
142136

143-
Contributions are welcome ❤️.
137+
Contributions are welcome!

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "t3dotgg",
2+
"name": "routerai",
33
"version": "0.1.0",
44
"private": true,
55
"type": "module",

prisma/schema.prisma

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ model Transaction {
9090
model Chat {
9191
id String @id @default(cuid())
9292
userId String
93+
title String?
94+
modelId String?
9395
isSaved Boolean @default(false)
9496
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
9597
messages Message[]

public/favicon.ico

1.29 MB
Binary file not shown.

public/og.png

1.29 MB
Loading

src/actions/sendSubscriptionMail.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@ export const sendEmailNotification = async (to: string): Promise<EmailResponse>
1111
console.log("Sending email to", to);
1212
const mailOptions = {
1313
from: {
14-
name: "T3Chat",
14+
name: "RouterAI",
1515
address: user,
1616
},
1717
to: to,
18-
subject: "Thank you for subscribing to T3Chat",
18+
subject: "Thank you for subscribing to RouterAI",
1919
html: `
2020
<!DOCTYPE html>
2121
<html lang="en">
2222
<head>
2323
<meta charset="UTF-8">
2424
<meta name="viewport" content="width=device-width, initial-scale=1.0">
25-
<title>Thank you for subscribing to T3Chat</title>
25+
<title>Thank you for subscribing to RouterAI</title>
2626
<style type="text/css">
2727
/* Base styles */
2828
body, html {
@@ -129,20 +129,20 @@ export const sendEmailNotification = async (to: string): Promise<EmailResponse>
129129
<div class="email-container">
130130
<!-- Header -->
131131
<div class="header">
132-
<a href="https://t3chat.xyz" class="logo">T3CHAT</a>
132+
<a href="https://t3chat.xyz" class="logo">ROUTERAI</a>
133133
</div>
134134
135135
<!-- Content -->
136136
<div class="content">
137-
<h1>Thank you for subscribing to T3Chat!</h1>
138-
<p>Thank you for subscribing to T3Chat. We're excited to have you on board.</p>
137+
<h1>Thank you for subscribing to RouterAI!</h1>
138+
<p>Thank you for subscribing to RouterAI. We're excited to have you on board.</p>
139139
<p>Your subscription has been successfully created with the following email address:</p>
140140
141141
<div class="highlight">
142142
${to}
143143
</div>
144144
145-
<p>With your T3Chat account, you can now access our platform's features and services.</p>
145+
<p>With your RouterAI account, you can now access our platform's features and services.</p>
146146
147147
<p>If you didn't request this account, please ignore this email or contact our support team.</p>
148148
@@ -153,7 +153,7 @@ export const sendEmailNotification = async (to: string): Promise<EmailResponse>
153153
154154
<!-- Footer -->
155155
<div class="footer">
156-
<p>&copy; ${new Date().getFullYear()} T3Chat. All rights reserved.</p>
156+
<p>&copy; ${new Date().getFullYear()} RouterAI. All rights reserved.</p>
157157
<p>
158158
<a href="https://t3chat.xyz">Privacy Policy</a> |
159159
<a href="https://t3chat.xyz">Terms of Service</a>

src/app/(app)/settings/subscription/page.tsx

Lines changed: 19 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -53,48 +53,32 @@ export default async function SubscriptionPage() {
5353
plan={user?.subscription?.plan as string}
5454
/>
5555

56-
{/* Message Usage */}
57-
<div className="bg-accent space-y-4 rounded-xl p-4 dark:bg-black">
58-
<div className="flex items-center justify-between">
59-
<span className="text-foreground font-medium">
60-
Message Usage
61-
</span>
62-
<span className="text-muted-foreground text-sm">
63-
Resets today at 5:30 AM
64-
</span>
65-
</div>
56+
<div className="space-y-1 pt-8">
57+
<h2 className="text-xl font-bold text-white">Danger Zone</h2>
58+
<p className="text-muted-foreground text-sm">
59+
Permanently delete your account and all associated data.
60+
</p>
61+
<Button
62+
variant="destructive"
63+
className="mt-4 rounded-lg bg-red-600 px-6 py-2 font-medium text-white hover:bg-red-700"
64+
>
65+
Delete Account
66+
</Button>
67+
</div>
6668

67-
<div className="space-y-2">
68-
<div className="flex items-center justify-between">
69-
<span className="text-foreground">Standard</span>
70-
<span className="text-foreground font-mono">0/20</span>
71-
</div>
72-
<div className="bg-muted h-2 w-full rounded-full">
73-
<div
74-
className="bg-primary h-2 rounded-full"
75-
style={{ width: "0%" }}
76-
></div>
77-
</div>
78-
<p className="text-muted-foreground text-sm">
79-
20 messages remaining
80-
</p>
81-
</div>
82-
</div>
8369
</div>
8470

8571
{/* Right Column - Tabs Section */}
8672
<div className="lg:col-span-2">
8773
<Tabs defaultValue="account" className="max-w-full overflow-x-auto">
8874
<div className="no-scrollbar overflow-x-auto">
8975
<TabsList className="h-[34px] rounded-lg">
90-
<TabsTrigger className="rounded-md text-xs" value="account">
91-
Account
92-
</TabsTrigger>
76+
9377
<TabsTrigger
9478
className="rounded-lg text-xs"
95-
value="customisation"
79+
value="account"
9680
>
97-
Customisation
81+
Account
9882
</TabsTrigger>
9983
<TabsTrigger className="rounded-lg text-xs" value="history">
10084
History & Sync
@@ -105,21 +89,14 @@ export default async function SubscriptionPage() {
10589
<TabsTrigger className="rounded-lg text-xs" value="api-keys">
10690
API Keys
10791
</TabsTrigger>
108-
<TabsTrigger
109-
className="rounded-lg text-xs"
110-
value="attachments"
111-
>
112-
Attachments
113-
</TabsTrigger>
92+
11493
<TabsTrigger className="rounded-lg text-xs" value="contact">
11594
Contact
11695
</TabsTrigger>
11796
</TabsList>
11897
</div>
119-
<TabsContent value="account" className="mt-6">
120-
<Account />
121-
</TabsContent>
122-
<TabsContent value="customisation">
98+
99+
<TabsContent value="account">
123100
<Customisation />
124101
</TabsContent>
125102
<TabsContent value="history">
@@ -131,9 +108,7 @@ export default async function SubscriptionPage() {
131108
<TabsContent value="api-keys">
132109
<APIKeysPage />
133110
</TabsContent>
134-
<TabsContent value="attachments">
135-
<AttachmentsPage />
136-
</TabsContent>
111+
137112
<TabsContent value="contact">
138113
<ContactUsPage />
139114
</TabsContent>

src/app/_components/Chat.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { useTheme } from "next-themes";
3131
import { Globe, Loader2Icon, Paperclip, WrapText } from "lucide-react";
3232
import { atomOneDark } from "react-syntax-highlighter/dist/esm/styles/hljs";
3333
import { api } from "@/trpc/react";
34+
import { useRouter } from "next/navigation";
3435

3536
const geistMono = Geist_Mono({
3637
subsets: ["latin"],
@@ -71,6 +72,7 @@ const Chat = ({ chatId: initialChatId }: { chatId: string }) => {
7172
const [attachments, setAttachments] = useState<File[]>([]);
7273
const [chatId, setChatId] = useState<string>(initialChatId);
7374
const { getKey } = useApiKeys();
75+
const utils = api.useUtils();
7476

7577
const getUserApiKey = useCallback(() => {
7678
const modelInfo = getModelById(model);
@@ -258,8 +260,10 @@ const Chat = ({ chatId: initialChatId }: { chatId: string }) => {
258260
content: currentQuery,
259261
};
260262

263+
const updatedMessages = [...messages, userMessage];
264+
261265
setQuery("");
262-
setMessages((prev) => [...prev, userMessage]);
266+
setMessages(updatedMessages);
263267
setIsLoading(true);
264268

265269
if (abortControllerRef.current) {
@@ -278,7 +282,7 @@ const Chat = ({ chatId: initialChatId }: { chatId: string }) => {
278282
"Content-Type": "application/json",
279283
},
280284
body: JSON.stringify({
281-
messages: [{ role: "user", content: currentQuery }],
285+
messages: updatedMessages.map((m) => ({ role: m.role, content: m.content })),
282286
model: model,
283287
chatId: chatId,
284288
userApiKey: getUserApiKey(),
@@ -287,6 +291,7 @@ const Chat = ({ chatId: initialChatId }: { chatId: string }) => {
287291
});
288292

289293
await processStream(response, currentQuery);
294+
void utils.chat.getAllChats.invalidate();
290295
} catch (error) {
291296
if ((error as Error).name !== "AbortError") {
292297
console.error("Error sending message:", error);
@@ -336,12 +341,11 @@ const Chat = ({ chatId: initialChatId }: { chatId: string }) => {
336341
content: input,
337342
};
338343

339-
setMessages((prev) => [...prev, userMessage]);
340-
341344
const currentMessage = input.trim();
345+
const updatedMessages = [...messages, userMessage];
342346

347+
setMessages(updatedMessages);
343348
setInput("");
344-
345349
setIsLoading(true);
346350

347351
if (abortControllerRef.current) {
@@ -357,7 +361,7 @@ const Chat = ({ chatId: initialChatId }: { chatId: string }) => {
357361
"Content-Type": "application/json",
358362
},
359363
body: JSON.stringify({
360-
messages: [{ role: "user", content: currentMessage }],
364+
messages: updatedMessages.map((m) => ({ role: m.role, content: m.content })),
361365
model: model,
362366
chatId: chatId,
363367
userApiKey: getUserApiKey(),
@@ -366,6 +370,8 @@ const Chat = ({ chatId: initialChatId }: { chatId: string }) => {
366370
});
367371

368372
await processStream(response, currentMessage);
373+
// Invalidate sidebar so it reflects updated chat
374+
void utils.chat.getAllChats.invalidate();
369375
} catch (error) {
370376
if ((error as Error).name !== "AbortError") {
371377
console.error("Error sending message:", error);

src/app/_components/Feedback.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const Feedback = () => {
4949
return (
5050
<>
5151
<Toaster />
52-
<div className="">
52+
<div id="feedback">
5353
<div className="container mx-auto px-4 py-12 lg:px-8">
5454
<div className="mx-auto max-w-6xl">
5555
<div className="grid grid-cols-1 items-center gap-12 lg:grid-cols-2">

0 commit comments

Comments
 (0)