├── .env.example
├── .eslintrc.json
├── .gitignore
├── README.md
├── app
├── api
│ ├── auth
│ │ ├── [...nextauth]
│ │ │ ├── options.ts
│ │ │ └── route.ts
│ │ └── signin
│ │ │ └── page.tsx
│ └── chat
│ │ ├── createNewChat
│ │ └── route.ts
│ │ ├── getChats
│ │ └── route.ts
│ │ └── route.ts
├── chat
│ └── [[...chatId]]
│ │ └── page.tsx
├── components
│ ├── ChatSidebar.tsx
│ └── Message.tsx
├── context
│ └── AuthProvider.tsx
├── favicon.ico
├── globals.css
├── layout.tsx
└── page.tsx
├── middleware.tsx
├── models
└── chat.ts
├── next.config.js
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── public
└── gaterebot.webp
├── tailwind.config.ts
└── tsconfig.json
/.env.example:
--------------------------------------------------------------------------------
1 | # NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=replace_me
2 | # CLERK_SECRET_KEY=replace_me
3 | NEXTAUTH_SECRET=replace_me
4 | GITHUB_ID=replace_me
5 | GITHUB_SECRET=replace_me
6 | GOOGLE_CLIENT_ID=replace_me
7 | GOOGLE_CLIENT_SECRET=replace_me
8 | OPENAI_API_KEY=replace_me
9 | MONGODB_URI=replace_me
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # GatereBot
4 |
5 | GatereBot is a ChatGPT-inspired project that leverages the OpenAI API for real-time natural language processing. It is built using NextJS, Tailwind CSS, OpenAI API, MongoDB and Mongoose for chat storage, React Markdown, Vercel AI SDK, and Next Auth for authentication.
6 |
7 |
14 |
15 | ---
16 |
17 |
24 |
25 | ## Table of Contents
26 |
27 | - [Features](#features)
28 | - [Technologies Used](#technologies)
29 | - [Installation](#installation)
30 | - [Deployment](#deployment)
31 | - [Contributing](#contributing)
32 |
33 | ## Features
34 |
35 | - Utilizes NextJS and Tailwind CSS for a responsive and modern UI
36 | - Real-time natural language processing using OpenAI API
37 | - Chat storage in MongoDB with Mongoose
38 | - User authentication with Next Auth
39 | - Integration with Vercel AI SDK for enhanced functionality
40 | - Supports rendering of React Markdown for rich content
41 |
42 | ## Technologies
43 |
44 | - [NextJS](https://nextjs.org/) : React framework for server-side rendering and optimal performance.
45 | - [Tailwind CSS](https://tailwindcss.com/) : A utility-first CSS framework for rapidly designing responsive web pages.
46 | - [OpenAI API](https://platform.openai.com/docs/overview) : Enables real-time natural language processing for user interactions.
47 | - [MongoDB](https://www.mongodb.com/) and [Mongoose](https://mongoosejs.com/) : NoSQL database and ODM for flexible data storage and modeling.
48 | - [React Markdown](https://www.npmjs.com/package/react-markdown) : Library for rendering Markdown content as React components.
49 | - [Vercel AI SDK](https://sdk.vercel.ai/docs) : Integrates AI capabilities into the application deployed on Vercel.
50 | - [Next Auth](https://next-auth.js.org/) : Authentication library for secure user access with social authentication providers.
51 |
52 | ## Installation
53 |
54 | 1. Clone the repository:
55 |
56 | ```bash
57 | git clone https://github.com/gateremark/gaterebot.git
58 | ```
59 |
60 | 2. Install dependencies:
61 |
62 | ```bash
63 | cd gaterebot
64 | pnpm install
65 | ```
66 |
67 | 3. Set up environment variables. Create a `.env` file in the root of your project and add the following:
68 |
69 | ```bash
70 | NEXTAUTH_SECRET=replace_me
71 | GITHUB_ID=replace_me
72 | GITHUB_SECRET=replace_me
73 | GOOGLE_CLIENT_ID=replace_me
74 | GOOGLE_CLIENT_SECRET=replace_me
75 | OPENAI_API_KEY=replace_me
76 | MONGODB_URI=replace_me
77 | ```
78 |
79 | 4. Run the development server:
80 |
81 | ```bash
82 | pnpm run dev
83 | ```
84 |
85 | 5. Open your browser and navigate to http://localhost:3000.
86 |
87 | ## Deployment
88 |
89 | GatereBot is deployed using Vercel. Any changes pushed to the main branch will trigger an automatic deployment.
90 | You can visit the live version of gaterebot at https://gaterebot.vercel.app/.
91 |
92 | ## Contributing
93 |
94 | Welcoming all contributions to improve the project! To contribute, please follow these steps:
95 |
96 | 1. Fork the repository.
97 |
98 | 2. Create a new branch for your feature:
99 | ```bash
100 | git checkout -b feature-name
101 | ```
102 | 3. Make your changes and commit them:
103 | ```bash
104 | git commit -m "Description of your changes"
105 | ```
106 | 4. Push your changes to your fork:
107 | ```bash
108 | git push origin feature-name
109 | ```
110 | 5. Submit a pull request to the main branch of the original repository.
111 |
--------------------------------------------------------------------------------
/app/api/auth/[...nextauth]/options.ts:
--------------------------------------------------------------------------------
1 | import type { NextAuthOptions } from "next-auth";
2 | import GitHubProvider from "next-auth/providers/github";
3 | import GoogleProvider from "next-auth/providers/google";
4 | // import CredentialsProvider from "next-auth/providers/credentials";
5 |
6 | export const options: NextAuthOptions = {
7 | providers: [
8 | GitHubProvider({
9 | clientId: process.env.GITHUB_ID as string,
10 | clientSecret: process.env.GITHUB_SECRET as string,
11 | httpOptions: { timeout: 10000 },
12 | }),
13 |
14 | GoogleProvider({
15 | clientId: process.env.GOOGLE_CLIENT_ID as string,
16 | clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
17 | httpOptions: { timeout: 10000 },
18 | }),
19 |
20 | // CredentialsProvider({
21 | // // The name to display on the sign in form (e.g. "Sign in with...")
22 | // name: "Credentials",
23 | // // `credentials` is used to generate a form on the sign in page.
24 | // // You can specify which fields should be submitted, by adding keys to the `credentials` object.
25 | // // e.g. domain, username, password, 2FA token, etc.
26 | // // You can pass any HTML attribute to the tag through the object.
27 | // credentials: {
28 | // username: {
29 | // label: "Username",
30 | // type: "text",
31 | // placeholder: "A cool username...",
32 | // },
33 | // password: {
34 | // label: "Password",
35 | // type: "password",
36 | // placeholder: "Your Password",
37 | // },
38 | // },
39 | // async authorize(credentials, req) {
40 | // // Add logic here to look up the user from the credentials supplied
41 | // const user = {
42 | // id: "1",
43 | // name: "Mark Gatere",
44 | // email: "mark5gatere@gmail.com",
45 | // };
46 |
47 | // if (user) {
48 | // // Any object returned will be saved in `user` property of the JWT
49 | // return user;
50 | // } else {
51 | // // If you return null then an error will be displayed advising the user to check their details.
52 | // return null;
53 |
54 | // // You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
55 | // }
56 | // },
57 | // }),
58 | ],
59 | pages: {
60 | signIn: "/signin",
61 | },
62 | callbacks: {
63 | async redirect({ url, baseUrl }) {
64 | return baseUrl;
65 | },
66 | },
67 | };
68 |
--------------------------------------------------------------------------------
/app/api/auth/[...nextauth]/route.ts:
--------------------------------------------------------------------------------
1 | import NextAuth from "next-auth";
2 | import { options } from "./options";
3 |
4 | const handler = NextAuth(options);
5 |
6 | export { handler as GET, handler as POST };
7 |
--------------------------------------------------------------------------------
/app/api/auth/signin/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { FaGithub } from "react-icons/fa6";
4 | import { FcGoogle } from "react-icons/fc";
5 | import Image from "next/image";
6 | import { signIn, getProviders } from "next-auth/react";
7 | import { useEffect, useState } from "react";
8 | // import { useRouter } from "next/navigation";
9 | import ReactTyped from "react-typed";
10 |
11 | const Signin = () => {
12 | const [providers, setProviders] = useState | null>(
13 | null
14 | );
15 | // const router = useRouter();
16 |
17 | useEffect(() => {
18 | const fetchProviders = async () => {
19 | const providers = await getProviders();
20 | // Handle providers data as needed
21 | // console.log(providers);
22 | setProviders(providers as Record | null);
23 | };
24 |
25 | fetchProviders();
26 | }, []);
27 |
28 | return (
29 |
30 |
31 |
39 |
40 |
41 | {" "}
42 | {providers && (
43 | <>
44 |
Hello there!
45 |
46 |
59 |
60 | >
61 | )}
62 |
63 | {providers ? (
64 | Object.values(providers).map((provider) => (
65 |
70 | {provider.id === "github" ? (
71 |
78 |
79 | ) : (
80 |
87 | )}
88 |
89 | ))
90 | ) : (
91 |
95 | )}
96 |
97 |
98 |
99 | );
100 | };
101 |
102 | export default Signin;
103 |
--------------------------------------------------------------------------------
/app/api/chat/createNewChat/route.ts:
--------------------------------------------------------------------------------
1 | import Chat from "@/models/chat";
2 | import { NextResponse } from "next/server";
3 |
4 | export async function POST(req: any) {
5 | try {
6 | const body = await req.json();
7 | const chatData = body;
8 | // console.log(chatData);
9 |
10 | await Chat.create(chatData);
11 |
12 | return NextResponse.json({ message: "Chat Created" }, { status: 201 });
13 | } catch (err) {
14 | // console.log(err);
15 | return NextResponse.json({ message: "Error", err }, { status: 500 });
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/api/chat/getChats/route.ts:
--------------------------------------------------------------------------------
1 | import Chat from "@/models/chat";
2 | import { NextResponse } from "next/server";
3 |
4 | export async function GET() {
5 | try {
6 | const chats = await Chat.find().sort({ createdAt: -1 });
7 |
8 | return NextResponse.json({ chats }, { status: 200 });
9 | } catch (err) {
10 | // console.log(err);
11 | return NextResponse.json({ message: "Error", err }, { status: 500 });
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/api/chat/route.ts:
--------------------------------------------------------------------------------
1 | import OpenAI from "openai";
2 | import { OpenAIStream, StreamingTextResponse } from "ai";
3 |
4 | // Create an OpenAI API client (that's edge friendly!)
5 | const openai = new OpenAI({
6 | apiKey: process.env.OPENAI_API_KEY,
7 | });
8 |
9 | // Set the runtime to edge for best performance
10 | export const runtime = "edge";
11 |
12 | export async function POST(req: Request) {
13 | const { messages } = await req.json();
14 | const initialMessage = {
15 | role: "system",
16 | content:
17 | "Your name is gaterebot. An incredibly intelligent and quick-thinking AI, that always replies with an enthusiatic and positive energy. You were created by [gateremark](https://bit.ly/gatere) and your response must be formatted as markdown.",
18 | };
19 |
20 | // Ask OpenAI for a streaming completion given the prompt
21 | const response = await openai.chat.completions.create({
22 | model: "gpt-3.5-turbo-1106",
23 | stream: true,
24 | // temperature: 0.6,
25 | // max_tokens: 300,
26 | messages: messages.concat(initialMessage),
27 | });
28 | // Convert the response into a friendly text-stream
29 | const stream = OpenAIStream(response);
30 | // Respond with the stream
31 | return new StreamingTextResponse(stream);
32 | }
33 |
--------------------------------------------------------------------------------
/app/chat/[[...chatId]]/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { FormEvent } from "react";
4 | import ChatSidebar from "@/app/components/ChatSidebar";
5 | import { IoSend } from "react-icons/io5";
6 | import { useChat } from "ai/react";
7 | import Message from "@/app/components/Message";
8 | import { useSession } from "next-auth/react";
9 | import Image from "next/image";
10 | import { useState, useEffect, useRef } from "react";
11 |
12 | export default function Home() {
13 | const { data: session } = useSession();
14 | const user = session?.user;
15 | const email = user?.email;
16 | const bottomRef = useRef(null);
17 |
18 | const { messages, input, handleInputChange, handleSubmit, isLoading } =
19 | useChat();
20 | // console.log("Messages:", messages);
21 | // const [prompt, ai] = messages;
22 | // console.log("Prompt:", prompt?.content);
23 | // messages.map((m) => console.log("new content:", m.content));
24 | // console.log("AI:", ai?.content);
25 | // const userData = prompt?.content + "\n" + ai?.content;
26 | // console.log("User Data:", userData);
27 |
28 | useEffect(() => {
29 | bottomRef.current?.scrollIntoView({
30 | behavior: "smooth",
31 | block: "start",
32 | });
33 | }, [messages]);
34 |
35 | const mongoHandleSubmit = async () => {
36 | try {
37 | // console.log("Sending data:", {
38 | // email: email,
39 | // title: input,
40 | // messages: messages,
41 | // });
42 |
43 | const response = await fetch("/api/chat/createNewChat", {
44 | method: "POST",
45 | headers: {
46 | "Content-Type": "application/json",
47 | },
48 | body: JSON.stringify({
49 | email: email,
50 | title: input,
51 | messages: messages,
52 | }),
53 | });
54 |
55 | const json = await response.json();
56 | // console.log("Response:", json);
57 | } catch (error) {
58 | console.error("Error submitting the chat:", error);
59 | }
60 | };
61 |
62 | // setTimeout(() => {
63 | // mongoHandleSubmit();
64 | // }, 10000);
65 | // setTimeout(mongoHandleSubmit, 10000);
66 |
67 | const handleKeyDown = (e: React.KeyboardEvent) => {
68 | if (e.key === "Enter") {
69 | e.preventDefault();
70 | const syntheticEvent = e as unknown as FormEvent;
71 | // Submit the form
72 | // handleSubmit(syntheticEvent);
73 | finalSubmit(e);
74 | }
75 | };
76 | const finalSubmit = (e: any) => {
77 | e.preventDefault();
78 | handleSubmit(e);
79 | mongoHandleSubmit();
80 | };
81 | // console.log(messages);
82 | // console.log("Messages:", messages[0]?.content);
83 | // console.log("Input:", input);
84 |
85 | return (
86 | <>
87 | New Chat
88 |
89 |
90 |
91 |
92 | {!messages.length && !isLoading && (
93 |
94 |
102 |
103 | Ask me a question
104 |
105 |
106 | )}
107 |
108 | {messages.map((m) => (
109 |
110 | ))}
111 |
112 |
113 |
114 |
151 |
152 |
153 | >
154 | );
155 | }
156 |
--------------------------------------------------------------------------------
/app/components/ChatSidebar.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useSession, signOut } from "next-auth/react";
4 | import Image from "next/image";
5 | import { LuLogOut } from "react-icons/lu";
6 | import { useState, useEffect } from "react";
7 | import Link from "next/link";
8 | import { AiFillMessage } from "react-icons/ai";
9 | import classNames from "classnames";
10 | // import { IoChevronBackSharp } from "react-icons/io5";
11 |
12 | const ChatSidebar = () => {
13 | const { data: session } = useSession();
14 | const [chatList, setChatList] = useState([]);
15 | const [openSidebar, setOpenSidebar] = useState(true);
16 | const [filteredData, setFilteredData] = useState([])
17 |
18 | const user = session?.user;
19 | const email = user?.email;
20 | // console.log("email: ", email);
21 |
22 | // const params = new URLSearchParams({ email: email ?? '' });
23 | // console.log("params")
24 |
25 | useEffect(() => {
26 | const getChats = async () => {
27 | try {
28 | const response = await fetch(`/api/chat/getChats`, {
29 | method: "GET",
30 | headers: {
31 | "Content-Type": "application/json",
32 | },
33 | });
34 |
35 | const json = await response.json();
36 | // console.log("Response:", json);
37 | setChatList(json?.chats);
38 | } catch (error) {
39 | console.error("Error getting chats:", error);
40 | }
41 | };
42 |
43 | getChats();
44 | }, [email]);
45 | // console.log("chatList", chatList);
46 |
47 | useEffect(()=>{
48 | const filteredData = chatList.filter((chat:any)=> chat.email == email)
49 | setFilteredData(filteredData);
50 | }, [chatList])
51 |
52 | // console.log(filteredData)
53 |
54 | return (
55 |
64 |
65 |
69 | {" "}
70 |
78 | New Chat{" "}
79 |
80 | {/*
83 | setOpenSidebar((openSidebar) => !openSidebar)
84 | }
85 | /> */}
86 |
87 |
88 |
89 | {filteredData.map((chat: any) => (
90 |
91 |
95 |
96 |
97 | {chat.title}
98 |
99 |
100 |
101 | ))}
102 |
103 |
104 |
121 |
122 | );
123 | };
124 |
125 | export default ChatSidebar;
126 |
--------------------------------------------------------------------------------
/app/components/Message.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useSession } from "next-auth/react";
4 | import Image from "next/image";
5 | import Markdown from "react-markdown";
6 | import rehypeHighlight from "rehype-highlight";
7 |
8 | interface MessageProps {
9 | role: string;
10 | content: string;
11 | isLoading: boolean;
12 | }
13 |
14 | const Message: React.FC = ({ role, content, isLoading }) => {
15 | const { data: session } = useSession();
16 | const email = session?.user?.email;
17 |
18 | return (
19 | <>
20 | {role === "user" ? (
21 |
22 |
30 |
31 |
{content}
32 |
33 | ) : (
34 |
35 |
43 |
44 | {/* {isLoading ? (
45 |
50 | ) : ( */}
51 |
52 | {content}
53 |
54 |
55 | {/* )} */}
56 |
57 |
58 | )}
59 | >
60 | );
61 | };
62 |
63 | export default Message;
64 |
--------------------------------------------------------------------------------
/app/context/AuthProvider.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { SessionProvider } from "next-auth/react";
4 |
5 | export default function AuthProvider({
6 | children,
7 | }: {
8 | children: React.ReactNode;
9 | }) {
10 | return {children};
11 | }
12 |
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gateremark/gaterebot/c135c3be755e60c4900833d37f6dd950f2547236/app/favicon.ico
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Playpen+Sans&display=swap");
2 |
3 | @tailwind base;
4 | @tailwind components;
5 | @tailwind utilities;
6 |
7 | ::-webkit-scrollbar {
8 | width: 8px;
9 | height: 5px;
10 | }
11 | ::-webkit-scrollbar-track {
12 | background: #343541;
13 | border-radius: 10px;
14 | height: 100%;
15 | }
16 | ::-webkit-scrollbar-thumb {
17 | background: #444654;
18 | opacity: 1;
19 | border-radius: 10px;
20 | }
21 |
22 | ::-webkit-scrollbar-thumb:hover {
23 | background: #747484;
24 | }
25 |
26 | .playpen {
27 | font-family: "Playpen Sans", cursive;
28 | }
29 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import { Roboto } from "next/font/google";
3 | import "./globals.css";
4 | import AuthProvider from "./context/AuthProvider";
5 |
6 | const roboto = Roboto({
7 | weight: "400",
8 | subsets: ["latin"],
9 | display: "swap",
10 | });
11 |
12 | export const metadata: Metadata = {
13 | title: "gaterebot",
14 | description:
15 | "gaterebot is an innovative chat application powered by ChatGPT through the OpenAI API.",
16 | openGraph: {
17 | images: [
18 | {
19 | url: "https://res.cloudinary.com/dvuazircp/image/upload/v1699262306/new_portfolio/gaterebot_ul4hei.webp",
20 | },
21 | ],
22 | },
23 | icons: {
24 | icon: "/favicon.ico",
25 | },
26 | };
27 |
28 | export default function RootLayout({
29 | children,
30 | }: {
31 | children: React.ReactNode;
32 | }) {
33 | return (
34 |
35 | {/*
36 |
37 | */}
38 |
39 | {children}
40 |
41 |
42 | );
43 | }
44 |
--------------------------------------------------------------------------------
/app/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import Image from "next/image";
4 | import { Toaster, toast } from "sonner";
5 | import { useSession, signOut } from "next-auth/react";
6 | import Link from "next/link";
7 |
8 | export default function Home() {
9 | const { data: session } = useSession();
10 |
11 | if (session) {
12 | toast.success(
13 | `Welcome ${
14 | session?.user?.name ? session?.user?.name : session?.user?.email
15 | }!`
16 | );
17 | }
18 |
19 | // console.log(session?.user);
20 | // console.log(session?.user?.name ?? "No user found");
21 |
22 | return (
23 |
29 |
30 |
31 |
32 | Hello{" "}
33 | {session?.user?.name
34 | ? session?.user?.name
35 | : session?.user?.email}{" "}
36 |
37 |
45 |
46 | Welcome to gaterebot
47 |
48 | {/* Link to chat */}
49 |
50 |
54 | Continue to Chat
55 |
56 |
62 |
63 |
64 |
65 | );
66 | }
67 |
--------------------------------------------------------------------------------
/middleware.tsx:
--------------------------------------------------------------------------------
1 | export { default } from "next-auth/middleware";
2 |
3 | // export const config = {matcher: ["/chat"]}
4 |
--------------------------------------------------------------------------------
/models/chat.ts:
--------------------------------------------------------------------------------
1 | import mongoose, { Schema } from "mongoose";
2 |
3 | mongoose.connect(process.env.MONGODB_URI ?? "MONGODB_URI is not defined");
4 | mongoose.Promise = global.Promise;
5 |
6 | const chatSchema = new Schema(
7 | {
8 | email: String,
9 | title: String,
10 | messages: Object,
11 | },
12 | {
13 | timestamps: true,
14 | }
15 | );
16 |
17 | const Chat = mongoose.models.Chat || mongoose.model("Chat", chatSchema);
18 |
19 | export default Chat;
20 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | images: {
4 | remotePatterns: [
5 | {
6 | protocol: "https",
7 | hostname: "**",
8 | },
9 | ],
10 | },
11 | };
12 |
13 | module.exports = nextConfig;
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gaterebot",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@clerk/nextjs": "^4.27.1",
13 | "@uiw/react-markdown-preview": "^4.2.2",
14 | "ai": "^2.2.23",
15 | "classnames": "^2.3.2",
16 | "mongodb": "^6.2.0",
17 | "mongoose": "^8.0.1",
18 | "next": "14.0.2",
19 | "next-auth": "^4.24.5",
20 | "openai": "^4.18.0",
21 | "react": "^18",
22 | "react-dom": "^18",
23 | "react-icons": "^4.11.0",
24 | "react-markdown": "^9.0.0",
25 | "react-syntax-highlighter": "^15.5.0",
26 | "react-typed": "^1.2.0",
27 | "rehype-highlight": "^7.0.0",
28 | "remark-gfm": "^4.0.0",
29 | "sonner": "^1.2.0",
30 | "uuid": "^9.0.1"
31 | },
32 | "devDependencies": {
33 | "@tailwindcss/typography": "^0.5.10",
34 | "@types/node": "^20",
35 | "@types/react": "^18",
36 | "@types/react-dom": "^18",
37 | "autoprefixer": "^10.0.1",
38 | "eslint": "^8",
39 | "eslint-config-next": "14.0.2",
40 | "postcss": "^8",
41 | "tailwindcss": "^3.3.0",
42 | "typescript": "^5"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/gaterebot.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gateremark/gaterebot/c135c3be755e60c4900833d37f6dd950f2547236/public/gaterebot.webp
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from 'tailwindcss'
2 |
3 | const config: Config = {
4 | content: [
5 | "./pages/**/*.{js,ts,jsx,tsx,mdx}",
6 | "./components/**/*.{js,ts,jsx,tsx,mdx}",
7 | "./app/**/*.{js,ts,jsx,tsx,mdx}",
8 | ],
9 | theme: {
10 | extend: {
11 | backgroundImage: {
12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
13 | "gradient-conic":
14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
15 | },
16 | boxShadow: {
17 | top: "0 -35px 50px -15px #343541",
18 | },
19 | },
20 | },
21 | plugins: [require("@tailwindcss/typography")],
22 | };
23 | export default config
24 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "esnext",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "paths": {
22 | "@/*": ["./*"]
23 | }
24 | },
25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "app/chat/hello"],
26 | "exclude": ["node_modules"]
27 | }
28 |
--------------------------------------------------------------------------------