├── app
├── favicon.ico
├── globals.css
├── layout.js
├── api
│ └── clerk
│ │ └── route.js
└── page.jsx
├── assets
├── favicon.ico
├── qrcode.png
├── search_icon.svg
├── delete_icon.svg
├── new_icon.svg
├── menu_icon.svg
├── profile_icon.svg
├── three_dots.svg
├── assets.js
├── phone_icon.svg
├── arrow_icon.svg
├── arrow_icon_dull.svg
├── phone_icon_dull.svg
├── pencil_icon.svg
├── pin_icon.svg
├── like_icon.svg
├── sidebar_close_icon.svg
├── logo_icon.svg
├── deepthink_icon.svg
├── sidebar_icon.svg
├── chat_icon.svg
├── chat_icon_dull.svg
├── dislike_icon.svg
├── copy_icon.svg
├── logo_text.svg
└── regenerate_icon.svg
├── jsconfig.json
├── next.config.mjs
├── postcss.config.mjs
├── public
├── vercel.svg
├── window.svg
├── file.svg
├── globe.svg
└── next.svg
├── eslint.config.mjs
├── models
└── User.js
├── middleware.ts
├── context
└── AppContext.jsx
├── config
└── db.js
├── .gitignore
├── package.json
├── README.md
└── components
├── ChatLabel.jsx
├── PromptBox.jsx
├── Message.jsx
└── Sidebar.jsx
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/obito8010/DeepSeek-Clone/HEAD/app/favicon.ico
--------------------------------------------------------------------------------
/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/obito8010/DeepSeek-Clone/HEAD/assets/favicon.ico
--------------------------------------------------------------------------------
/assets/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/obito8010/DeepSeek-Clone/HEAD/assets/qrcode.png
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "paths": {
4 | "@/*": ["./*"]
5 | }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {};
3 |
4 | export default nextConfig;
5 |
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | const config = {
2 | plugins: ["@tailwindcss/postcss"],
3 | };
4 |
5 | export default config;
6 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 |
3 | @theme{
4 | --color-primary: #4d5bfe;
5 | }
6 |
7 | html{
8 | @apply scroll-smooth;
9 | }
10 |
11 | ::-webkit-scrollbar{
12 | display: none;
13 | }
--------------------------------------------------------------------------------
/public/window.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/file.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import { dirname } from "path";
2 | import { fileURLToPath } from "url";
3 | import { FlatCompat } from "@eslint/eslintrc";
4 |
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = dirname(__filename);
7 |
8 | const compat = new FlatCompat({
9 | baseDirectory: __dirname,
10 | });
11 |
12 | const eslintConfig = [...compat.extends("next/core-web-vitals")];
13 |
14 | export default eslintConfig;
15 |
--------------------------------------------------------------------------------
/models/User.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 |
3 | const UserSchema = new mongoose.Schema(
4 | {
5 | _id: {type:String, required: true},
6 | name: {type:String, required: true},
7 | email: {type:String, required: true},
8 | image: {type:String, required: false}
9 | },
10 | {timestamps : true}
11 | );
12 | const User = mongoose.models.User || mongoose.model("User",UserSchema)
13 | export default User;
--------------------------------------------------------------------------------
/middleware.ts:
--------------------------------------------------------------------------------
1 | import { clerkMiddleware } from '@clerk/nextjs/server';
2 |
3 | export default clerkMiddleware();
4 |
5 | export const config = {
6 | matcher: [
7 | // Skip Next.js internals and all static files, unless found in search params
8 | '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
9 | // Always run for API routes
10 | '/(api|trpc)(.*)',
11 | ],
12 | };
--------------------------------------------------------------------------------
/context/AppContext.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useUser } from "@clerk/nextjs";
3 | import { createContext, useContext } from "react";
4 |
5 | export const AppContext = createContext();
6 |
7 | export const useAppContext = () => {
8 | const context = useContext(AppContext);
9 | return useContext(AppContext)
10 | }
11 |
12 | export const AppContextProvider = ({ children }) => {
13 | const {user} = useUser()
14 | const value ={
15 | user
16 | }
17 | return {children}
18 | }
--------------------------------------------------------------------------------
/config/db.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 |
3 | let cached = globalThis.mongoose || {conn: null, promise:null};
4 |
5 | export default async function connectDB(){
6 | if(cached.conn) return cached.conn;
7 | if(!cached.promise){
8 | cached.promise = (await mongoose.connect(process.env.MONGODB_URI)).then((mongoose)=>mongoose);
9 | }
10 | try{
11 | CacheHandler.conn = await cached.promise;
12 | }catch(errpr){
13 | console.error("Error connecting to mongodb:", error);
14 | }
15 | return cached.conn
16 | }
--------------------------------------------------------------------------------
/assets/search_icon.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/.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.*
7 | .yarn/*
8 | !.yarn/patches
9 | !.yarn/plugins
10 | !.yarn/releases
11 | !.yarn/versions
12 |
13 | # testing
14 | /coverage
15 |
16 | # next.js
17 | /.next/
18 | /out/
19 |
20 | # production
21 | /build
22 |
23 | # misc
24 | .DS_Store
25 | *.pem
26 |
27 | # debug
28 | npm-debug.log*
29 | yarn-debug.log*
30 | yarn-error.log*
31 | .pnpm-debug.log*
32 |
33 | # env files (can opt-in for committing if needed)
34 | .env*
35 |
36 | # vercel
37 | .vercel
38 |
39 | # typescript
40 | *.tsbuildinfo
41 | next-env.d.ts
42 |
--------------------------------------------------------------------------------
/assets/delete_icon.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/new_icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/menu_icon.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/profile_icon.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/layout.js:
--------------------------------------------------------------------------------
1 | import { Inter } from "next/font/google";
2 | import "./globals.css";
3 | import { ClerkProvider } from "@clerk/nextjs";
4 | import { AppContextProvider } from "@/context/AppContext";
5 |
6 | const inter = Inter({
7 | variable: "--font-inter",
8 | subsets: ["latin"],
9 | });
10 |
11 | export const metadata = {
12 | title: "DeepSeek",
13 | description: "Full Stack Project Created by Chinmay Saseendran",
14 | };
15 |
16 | export default function RootLayout({ children }) {
17 | return (
18 |
19 |
20 |
21 |
24 | {children}
25 |
26 |
27 |
28 |
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "deepseek",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev --turbopack",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@clerk/nextjs": "^6.22.0",
13 | "axios": "^1.10.0",
14 | "mongoose": "^8.16.0",
15 | "next": "15.3.1",
16 | "openai": "^5.5.1",
17 | "prismjs": "^1.30.0",
18 | "react": "^19.0.0",
19 | "react-dom": "^19.0.0",
20 | "react-hot-toast": "^2.5.2",
21 | "react-markdown": "^10.1.0",
22 | "svix": "^1.67.0"
23 | },
24 | "devDependencies": {
25 | "@eslint/eslintrc": "^3",
26 | "@tailwindcss/postcss": "^4",
27 | "eslint": "^9",
28 | "eslint-config-next": "15.3.1",
29 | "tailwindcss": "^4"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/public/globe.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/three_dots.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #🔍 DeepSeek Clone – Full-Stack AI Search Engine
2 | This project is a full-stack clone of DeepSeek, built by following the tutorial DeepSeek AI Clone - Full Stack Next.js + AI App. It mimics the functionality and interface of an AI-powered semantic search engine, combining the power of modern web technologies with OpenAI’s capabilities.
3 |
4 | 🚀 Features
5 | 🌐 Full-stack application using Next.js 14 (App Router) and TypeScript
6 | 🎨 Elegant UI with Tailwind CSS
7 | 🧠 AI-powered search with OpenAI API
8 | 🔍 Semantic document search using Vector Embeddings
9 | 🗃️ Upload and index PDF documents for context-aware searching
10 | ⚡ Real-time response streaming (using openai-streams)
11 |
12 | 🛠️ Tech Stack
13 | Frontend: Next.js 14, TypeScript, Tailwind CSS
14 | Backend: OpenAI API, Supabase, Pinecone / Vercel KV
15 | Embeddings: OpenAI Embedding API
16 | Authentication: Clerk (or replace with Auth.js/Auth0 if preferred)
17 |
18 | 📁 Project Status
19 | ✅ In Progress – Actively building and refining features
20 |
21 | #📄 How to Use
22 | 1.Clone the repo
23 | 2.Set up environment variables (.env.local)
24 | 3.Run the dev server with npm run dev
25 | 4.Start uploading PDFs and querying them with smart AI search!
26 |
27 |
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/components/ChatLabel.jsx:
--------------------------------------------------------------------------------
1 | import { assets } from "@/assets/assets"
2 | import Image from "next/image"
3 | import React, { useState } from 'react';
4 | const ChatLabel = ({openMenu, setOpenMenu}) => {
5 | return (
6 |
7 |
Chat Name Here
8 |
21 |
22 | )
23 | }
24 | export default ChatLabel
--------------------------------------------------------------------------------
/app/api/clerk/route.js:
--------------------------------------------------------------------------------
1 | import {webhook} from "svix";
2 | import connection from "@/config/db";
3 | import User from "@/models/User";
4 | import { headers } from "next/headers";
5 | import { NextRequest } from "next/server";
6 |
7 | export async function POST(req){
8 | const wh = new webhook(process.env.SIGNING_SECRET)
9 | const headerpayload = await headers()
10 | const svixHeaders = {
11 | "svix-id": headerpayload.get("svix-id"),
12 | "svix-timestamp": headerpayload.get("svix-timestamp"),
13 | "svix-signature": headerpayload.get("svix-signature"),
14 | };
15 | // get the payload
16 |
17 | const payload = await req.json();
18 | const body = JSON.stringify(payload);
19 | const {data, type} = wh.verify(body, svoxHeaders)
20 |
21 | //prepare user data to be saved in the database
22 |
23 | const userData = {
24 | _id: data.id,
25 | email: data.email_addresses[0].email_address,
26 | name: `${data.first_name} ${data.last_name}`,
27 | image:data.image_url,
28 | };
29 | await connectionDB();
30 |
31 | switch(type){
32 | case 'user.created':
33 | await User.create(userData)
34 | break;
35 | case 'user.updated':
36 | await User.findByIdAndUpdate(data.id, userData)
37 | break;
38 | case 'user.deleted':
39 | await User.findByIdAndDelete(data.id)
40 | break;
41 | default:
42 | break;
43 | }
44 | return NextRequest.json({message:"Event Recived"});
45 | }
--------------------------------------------------------------------------------
/assets/assets.js:
--------------------------------------------------------------------------------
1 | import arrow_icon from "./arrow_icon.svg";
2 | import arrow_icon_dull from "./arrow_icon_dull.svg";
3 | import logo_text from "./logo_text.svg";
4 | import logo_icon from "./logo_icon.svg";
5 | import menu_icon from "./menu_icon.svg";
6 | import search_icon from "./search_icon.svg";
7 | import profile_icon from "./profile_icon.svg";
8 | import copy_icon from "./copy_icon.svg";
9 | import deepthink_icon from "./deepthink_icon.svg";
10 | import chat_icon from "./chat_icon.svg";
11 | import dislike_icon from "./dislike_icon.svg";
12 | import like_icon from "./like_icon.svg";
13 | import phone_icon from "./phone_icon.svg";
14 | import phone_icon_dull from "./phone_icon_dull.svg";
15 | import pencil_icon from "./pencil_icon.svg";
16 | import delete_icon from "./delete_icon.svg";
17 | import pin_icon from "./pin_icon.svg";
18 | import regenerate_icon from "./regenerate_icon.svg";
19 | import sidebar_icon from "./sidebar_icon.svg";
20 | import sidebar_close_icon from "./sidebar_close_icon.svg";
21 | import chat_icon_dull from "./chat_icon_dull.svg";
22 | import qrcode from "./qrcode.png";
23 | import three_dots from "./three_dots.svg";
24 | import new_icon from "./new_icon.svg";
25 |
26 | export const assets = {
27 | arrow_icon,
28 | arrow_icon_dull,
29 | logo_text,
30 | logo_icon,
31 | menu_icon,
32 | search_icon,
33 | profile_icon,
34 | copy_icon,
35 | deepthink_icon,
36 | chat_icon,
37 | dislike_icon,
38 | like_icon,
39 | phone_icon,
40 | phone_icon_dull,
41 | pencil_icon,
42 | delete_icon,
43 | pin_icon,
44 | regenerate_icon,
45 | sidebar_icon,
46 | sidebar_close_icon,
47 | chat_icon_dull,
48 | qrcode,
49 | three_dots,
50 | new_icon,
51 | };
--------------------------------------------------------------------------------
/assets/phone_icon.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/arrow_icon.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/assets/arrow_icon_dull.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/app/page.jsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 | import { assets } from "@/assets/assets";
3 | import PromptBox from "@/components/PromptBox";
4 | import Sidebar from "@/components/Sidebar";
5 | import Message from "@/components/Message";
6 | import Image from "next/image";
7 | import { useState } from "react";
8 |
9 | export default function Home() {
10 |
11 | const[expand , setExpand] = useState(false);
12 | const[messages , setMessages] = useState([]);
13 | const[isLoading , setIsLoading] = useState(false);
14 |
15 | return (
16 |
17 |
18 | {/* --sidebar-- */}
19 |
20 |
21 |
22 | (expand ? setExpand(false):setExpand(true))}
23 | className="rotate-180" src={assets.menu_icon} alt=""/>
24 |
25 |
26 |
27 | {messages.length ===0 ? (
28 | <>
29 |
30 |
31 |
Hi, i am deepseek
32 |
33 |
How can i help you today
34 | >
35 | ):
36 | (
)
37 | }
38 |
39 | {/* --prompt box-- */}
40 |
41 | Ai generated , for reference only
42 |
43 |
44 |
45 |
46 |
47 | );
48 | }
49 |
--------------------------------------------------------------------------------
/assets/phone_icon_dull.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/components/PromptBox.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Image from "next/image";
3 | import { assets } from "@/assets/assets";
4 |
5 | const PromptBox = ({setIsLoading,isLoading}) => {
6 |
7 | const[prompt,setPrompt] = useState('');
8 |
9 | return(
10 |
33 | )
34 | }
35 | export default PromptBox;
--------------------------------------------------------------------------------
/assets/pencil_icon.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/components/Message.jsx:
--------------------------------------------------------------------------------
1 | import { assets } from '@/assets/assets'
2 | import Image from 'next/image'
3 | import React from 'react'
4 |
5 | const Message = ({role, content}) => {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 | {
13 | role === 'user' ? (
14 | <>
15 |
16 |
17 |
18 | >
19 | ):(
20 | <>
21 |
22 |
23 |
24 |
25 | >
26 | )
27 | }
28 |
29 |
30 | {
31 | role === 'user' ?
32 | (
33 |
{content}
34 | )
35 | :
36 | (
37 | <>
38 |
39 |
40 | {content}
41 |
42 | >
43 | )
44 | }
45 |
46 |
47 |
48 | )
49 | }
50 | export default Message
--------------------------------------------------------------------------------
/assets/pin_icon.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/assets/like_icon.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/sidebar_close_icon.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/assets/logo_icon.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/assets/deepthink_icon.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/sidebar_icon.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/assets/chat_icon.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/assets/chat_icon_dull.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/components/Sidebar.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { assets } from '@/assets/assets'
3 | import Image from 'next/image'
4 | import React, { useState } from 'react';
5 | import { useClerk,UserButton } from '@clerk/nextjs'
6 | import { useAppContext } from '@/context/AppContext'
7 | import ChatLabel from './ChatLabel';
8 |
9 | const Sidebar = ({expand,setExpand}) => {
10 |
11 | const { openSignIn } = useClerk()
12 | const {user} = useAppContext()
13 | const [openMenu, setOpenMenu] = useState({id:0, open: false})
14 |
15 | return (
16 |
17 |
18 |
19 |
20 |
expand ? setExpand(false) : setExpand(true)}
21 | className='group relative flex item center justify-center hover:bg-gray-500/20 transition-all duration-300 h-9 w-8 aspect-square rounded-lg cursor-pointer'>
22 |
23 |
24 |
25 | {expand ? "Close sidebar" : "Open sidebar"}
26 |
27 |
28 |
29 |
30 |
31 |
39 |
40 |
41 |
42 |
Recents
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
Scan to get DeepSeek App
56 |
57 |
58 |
59 | {expand && <>
Get App>}
60 |
61 |
62 |
64 | {
65 | user ? :
66 | }
67 | {expand && my profile}
68 |
69 |
70 |
71 | )
72 | }
73 |
74 | export default Sidebar
--------------------------------------------------------------------------------
/assets/dislike_icon.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/assets/copy_icon.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/assets/logo_text.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/assets/regenerate_icon.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------