├── src ├── App.css ├── App.jsx ├── assets │ ├── 1.png │ ├── Yai.png │ ├── yaicr.png │ ├── YAICropped.png │ ├── titlelogo.png │ ├── YapperAI logo.png │ ├── pixelcut-export.png │ ├── 1-removebg-preview.png │ ├── YapperAILogoTransparent.png │ ├── google-color-svgrepo-com.png │ ├── YapperAII-removebg-preview.png │ ├── google-color-svgrepo-com.svg │ └── react.svg ├── components │ ├── NotFound │ │ └── NotFound.jsx │ ├── Features │ │ ├── FeatureCard.jsx │ │ └── Features.jsx │ ├── Testimonials │ │ ├── TestimonialCard.jsx │ │ └── Testimonial.jsx │ ├── Server │ │ └── server.js │ ├── BuildInfo │ │ └── BuildInfo.jsx │ ├── CallToAction │ │ └── CallToAction.jsx │ ├── Private Route │ │ ├── ReverseRoute.jsx │ │ └── PrivateRoute.jsx │ ├── Sign Up │ │ └── SignUp.jsx │ ├── Header │ │ └── Header.jsx │ ├── About │ │ └── About.jsx │ ├── Hero │ │ └── Hero.jsx │ └── Home │ │ └── Home.jsx ├── index.css ├── Layout.jsx └── main.jsx ├── postcss.config.js ├── vercel.json ├── vite.config.js ├── .gitignore ├── index.html ├── tailwind.config.js ├── LICENSE ├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── eslint.config.js ├── public └── vite.svg ├── package.json ├── SECURITY.md ├── README.md ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md /src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/1.png -------------------------------------------------------------------------------- /src/assets/Yai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/Yai.png -------------------------------------------------------------------------------- /src/assets/yaicr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/yaicr.png -------------------------------------------------------------------------------- /src/assets/YAICropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/YAICropped.png -------------------------------------------------------------------------------- /src/assets/titlelogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/titlelogo.png -------------------------------------------------------------------------------- /src/assets/YapperAI logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/YapperAI logo.png -------------------------------------------------------------------------------- /src/assets/pixelcut-export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/pixelcut-export.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/1-removebg-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/1-removebg-preview.png -------------------------------------------------------------------------------- /src/assets/YapperAILogoTransparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/YapperAILogoTransparent.png -------------------------------------------------------------------------------- /src/assets/google-color-svgrepo-com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/google-color-svgrepo-com.png -------------------------------------------------------------------------------- /src/assets/YapperAII-removebg-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polaris-dev9/YAPPER-AI/HEAD/src/assets/YapperAII-removebg-preview.png -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [ 3 | { 4 | "source": "/(.*)", 5 | "destination": "/index.html" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /src/components/NotFound/NotFound.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function NotFound() { 4 | return ( 5 |
Page Not Found
6 | ) 7 | } 8 | 9 | export default NotFound -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Environment files 16 | .env 17 | *.local 18 | .env.* 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | .DS_Store 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | YapperAI 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Hanken+Grotesk:ital,wght@0,100..900;1,100..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap'); 2 | 3 | @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap'); 4 | 5 | @import url('https://fonts.googleapis.com/css2?family=New+Amsterdam&display=swap'); 6 | 7 | @tailwind base; 8 | @tailwind components; 9 | @tailwind utilities; -------------------------------------------------------------------------------- /src/components/Features/FeatureCard.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function FeatureCard({ title, description }) { 4 | return ( 5 |
6 |

{title}

7 |

{description}

8 |
9 | ) 10 | } 11 | 12 | export default FeatureCard -------------------------------------------------------------------------------- /src/components/Testimonials/TestimonialCard.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function TestimonialCard( { name, feedback } ) { 4 | return ( 5 |
6 |

"{feedback}"

7 |

{name}

8 |
9 | ) 10 | } 11 | 12 | export default TestimonialCard -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | const {nextui} = require("@nextui-org/react"); 2 | 3 | /** @type {import('tailwindcss').Config} */ 4 | export default { 5 | content: [ 6 | "./index.html", 7 | "./src/**/*.{js,ts,jsx,tsx}", 8 | "./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}", 9 | ], 10 | theme: { 11 | extend: { 12 | colors: { 13 | mainBackground: "#1a1a1a", 14 | }, 15 | fontFamily: { 16 | grotesk: ["Hanken Grotesk", "sans-serif"], 17 | outfit: ["Outfit", "sans-serif"], 18 | amster: ["New Amsterdam", "sans-serif"], 19 | } 20 | }, 21 | darkMode: "class", 22 | plugins: [nextui()], 23 | }, 24 | plugins: [], 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/components/Server/server.js: -------------------------------------------------------------------------------- 1 | // Import the functions you need from the SDKs you need 2 | import { initializeApp } from "firebase/app"; 3 | import { getAnalytics } from "firebase/analytics"; 4 | import { getAuth } from "firebase/auth"; 5 | 6 | const firebaseConfig = { 7 | apiKey: "AIzaSyB8P56LS_YnSotDJJsjPDjZtLqNiPQEOUo", 8 | authDomain: "yapper-ai-bot.firebaseapp.com", 9 | projectId: "yapper-ai-bot", 10 | storageBucket: "yapper-ai-bot.appspot.com", 11 | messagingSenderId: "982335835743", 12 | appId: "1:982335835743:web:027001abe6785eb96c95ea", 13 | measurementId: "G-8MWE049HKZ" 14 | }; 15 | 16 | // Initialize Firebase 17 | const app = initializeApp(firebaseConfig); 18 | const analytics = getAnalytics(app); 19 | const auth = getAuth(); 20 | 21 | export { auth} 22 | -------------------------------------------------------------------------------- /src/Layout.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import Header from "./components/Header/Header.jsx"; 3 | 4 | 5 | import { Outlet } from "react-router-dom"; 6 | import { Analytics } from "@vercel/analytics/react"; 7 | 8 | function Layout() { 9 | 10 | return ( 11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 |

Everything that Yapper AI says is made up or Maybe not...

19 |
20 | 21 |
22 | ); 23 | } 24 | 25 | export default Layout; 26 | -------------------------------------------------------------------------------- /src/components/BuildInfo/BuildInfo.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function BuildInfo() { 4 | return ( 5 |
6 |

7 | Built on Advanced Technology 8 |

9 |

10 | Powered by the cutting-edge{" "} 11 | 12 | Gemini-Flash-1.5 13 | {" "} 14 | model, Yapper AI brings to life engaging conversations 15 | using advanced prompting techniques. Experience 16 | markdown-rich responses with visually appealing 17 | highlights, making every conversation an interactive 18 | delight. 19 |

20 |
21 | ) 22 | } 23 | 24 | export default BuildInfo -------------------------------------------------------------------------------- /src/components/CallToAction/CallToAction.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function CallToAction() { 4 | const scrollToTop = () => { 5 | window.scrollTo({ 6 | top: 0, 7 | behavior: 'smooth', // smooth scroll effect 8 | }); 9 | }; 10 | return ( 11 |
12 |

13 | Ready to Chat? 14 |

15 |

16 | Choose your favorite personality and start your 17 | conversation today. 18 |

19 | 24 |
25 | ) 26 | } 27 | 28 | export default CallToAction -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Ganesh Sharma 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Bug Report 🐛" 3 | about: "Found something off? Let us know so we can fix it pronto!" 4 | title: "[BUG] Your snazzy title here" 5 | labels: [bug] 6 | assignees: '' 7 | --- 8 | 9 | ## 🛠️ Problem Statement 10 | **What's broken?** 11 | A clear and concise description of what the bug is. 12 | 13 | **Where did this happen?** 14 | Page/Component/Feature: `e.g., Chat with Desi Indian Personality` 15 | 16 | ## 🔄 Reproduction Steps 17 | Steps to reproduce the behavior: 18 | 1. Go to '...' 19 | 2. Click on '...' 20 | 3. Scroll down to '...' 21 | 4. See error 22 | 23 | ## 🤔 Expected Behavior 24 | What did you expect to happen? Be specific! 25 | 26 | ## 😵 Actual Behavior 27 | What actually happened? Screenshots welcome 📸! 28 | 29 | ## 💻 Environment Details 30 | - **Device/OS**: `e.g., iPhone 14, iOS 17.0` 31 | - **Browser/App**: `e.g., Chrome 120, Safari 17` 32 | - **Version of Yapper AI**: `e.g., 5.1.3` 33 | 34 | ## 📸 Screenshots or Logs 35 | Attach any screenshots or console logs that help illustrate the issue. 36 | 37 | ## 🧠 Additional Context 38 | Any other hints or context? Spill the tea 🫖! 39 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import react from 'eslint-plugin-react' 4 | import reactHooks from 'eslint-plugin-react-hooks' 5 | import reactRefresh from 'eslint-plugin-react-refresh' 6 | 7 | export default [ 8 | { ignores: ['dist'] }, 9 | { 10 | files: ['**/*.{js,jsx}'], 11 | languageOptions: { 12 | ecmaVersion: 2020, 13 | globals: globals.browser, 14 | parserOptions: { 15 | ecmaVersion: 'latest', 16 | ecmaFeatures: { jsx: true }, 17 | sourceType: 'module', 18 | }, 19 | }, 20 | settings: { react: { version: '18.3' } }, 21 | plugins: { 22 | react, 23 | 'react-hooks': reactHooks, 24 | 'react-refresh': reactRefresh, 25 | }, 26 | rules: { 27 | ...js.configs.recommended.rules, 28 | ...react.configs.recommended.rules, 29 | ...react.configs['jsx-runtime'].rules, 30 | ...reactHooks.configs.recommended.rules, 31 | 'react/jsx-no-target-blank': 'off', 32 | 'react-refresh/only-export-components': [ 33 | 'warn', 34 | { allowConstantExport: true }, 35 | ], 36 | }, 37 | }, 38 | ] 39 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import React from "react"; 3 | import { createRoot } from "react-dom/client"; 4 | 5 | import "./index.css"; 6 | import Layout from "./Layout.jsx"; 7 | import Home from "./components/Home/Home.jsx"; 8 | import { 9 | createBrowserRouter, 10 | createRoutesFromElements, 11 | Route, 12 | RouterProvider, 13 | } from "react-router-dom"; 14 | import NotFound from "./components/NotFound/NotFound.jsx"; 15 | import { NextUIProvider } from "@nextui-org/react"; 16 | 17 | import PrivateRoute from "./components/Private Route/PrivateRoute.jsx"; 18 | 19 | import SignUp from "./components/Sign Up/SignUp.jsx"; 20 | import { gitInfoLoader } from "./components/About/About.jsx"; 21 | 22 | 23 | 24 | 25 | const router = createBrowserRouter( 26 | createRoutesFromElements( 27 | }> 28 | 29 | }/> 30 | 31 | }/> 32 | 33 | }/> 34 | 35 | ) 36 | ); 37 | 38 | createRoot(document.getElementById("root")).render( 39 | 40 | 41 | 42 | 43 | 44 | ); 45 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Private Route/ReverseRoute.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { getAuth, onAuthStateChanged } from "firebase/auth"; 3 | import { Navigate, useNavigate } from "react-router-dom"; 4 | 5 | function ReverseRoute({children}) { 6 | 7 | const [uid, setUid] = useState(null) 8 | const [loading, setLoading] = useState(true) 9 | 10 | 11 | useEffect(() => { 12 | const auth = getAuth() 13 | const unSubscribe = onAuthStateChanged( 14 | auth, (user) => { 15 | if(user){ 16 | console.log(user) 17 | setUid(user.displayName) 18 | 19 | console.log("User is already Signed in with uid: ", uid); 20 | 21 | } 22 | else{ 23 | setUid(null) 24 | console.log("User is not Signed in") 25 | } 26 | setLoading(false) 27 | } 28 | ) 29 | return () => unSubscribe() 30 | },[uid]) 31 | 32 | if(loading){ 33 | return

Loading...

34 | } 35 | 36 | return uid != null ? : children ; 37 | 38 | } 39 | 40 | export default ReverseRoute; 41 | -------------------------------------------------------------------------------- /src/components/Private Route/PrivateRoute.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { getAuth, onAuthStateChanged } from "firebase/auth"; 3 | import { Navigate, useNavigate } from "react-router-dom"; 4 | 5 | function PrivateRoute({children}) { 6 | 7 | const [uid, setUid] = useState(null) 8 | const [loading, setLoading] = useState(true) 9 | 10 | 11 | useEffect(() => { 12 | const auth = getAuth() 13 | const unSubscribe = onAuthStateChanged( 14 | auth, (user) => { 15 | if(user){ 16 | console.log(user) 17 | setUid(user.displayName) 18 | 19 | console.log("User is already Signed in with uid: ", uid); 20 | 21 | } 22 | else{ 23 | setUid(null) 24 | console.log("User is not Signed in") 25 | } 26 | setLoading(false) 27 | } 28 | ) 29 | return () => unSubscribe() 30 | },[uid]) 31 | 32 | if(loading){ 33 | return

Loading...

34 | } 35 | 36 | return uid != null ? children : ; 37 | 38 | } 39 | 40 | export default PrivateRoute; 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yapperai", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@emotion/react": "^11.13.3", 14 | "@emotion/styled": "^11.13.0", 15 | "@google/generative-ai": "^0.17.1", 16 | "@mui/icons-material": "^6.0.2", 17 | "@mui/material": "^6.0.2", 18 | "@nextui-org/dropdown": "^2.1.29", 19 | "@nextui-org/react": "^2.4.6", 20 | "@vercel/analytics": "^1.4.1", 21 | "firebase": "^10.13.1", 22 | "framer-motion": "^11.5.4", 23 | "katex": "^0.16.11", 24 | "mermaid": "^11.2.0", 25 | "react": "^18.3.1", 26 | "react-dom": "^18.3.1", 27 | "react-markdown": "^9.0.1", 28 | "react-router-dom": "^6.26.1", 29 | "rehype-highlight": "^7.0.0", 30 | "rehype-katex": "^7.0.1", 31 | "remark": "^15.0.1", 32 | "remark-emoji": "^5.0.1", 33 | "remark-gfm": "^4.0.0", 34 | "remark-html": "^16.0.1", 35 | "remark-math": "^6.0.0", 36 | "remark-mermaid": "^0.2.0", 37 | "yapperai": "file:" 38 | }, 39 | "devDependencies": { 40 | "@eslint/js": "^9.9.0", 41 | "@types/react": "^18.3.3", 42 | "@types/react-dom": "^18.3.0", 43 | "@vitejs/plugin-react": "^4.3.1", 44 | "autoprefixer": "^10.4.20", 45 | "eslint": "^9.9.0", 46 | "eslint-plugin-react": "^7.35.0", 47 | "eslint-plugin-react-hooks": "^5.1.0-rc.0", 48 | "eslint-plugin-react-refresh": "^0.4.9", 49 | "globals": "^15.9.0", 50 | "postcss": "^8.4.45", 51 | "tailwindcss": "^3.4.10", 52 | "vite": "^5.4.1" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/components/Sign Up/SignUp.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React from "react"; 3 | 4 | import Hero from "../Hero/Hero.jsx"; 5 | import { Suspense } from "react"; 6 | import About from "../About/About.jsx"; 7 | 8 | const LazyFeatures = React.lazy(() => import("../Features/Features.jsx")) 9 | const LazyBuildInfo = React.lazy(() => import("../BuildInfo/BuildInfo.jsx")) 10 | const LazyTestimonials = React.lazy(() => import("../Testimonials/Testimonial.jsx")) 11 | const LazyCTA = React.lazy(() => import("../CallToAction/CallToAction.jsx")) 12 | 13 | function SignUp() { 14 | 15 | return ( 16 |
17 | 18 | 19 | {/* Home page */} 20 | 21 | 22 |
23 | {/* Features Section */} 24 | 25 | 26 | 27 | 28 | 29 | {/* Build Info Section */} 30 | 31 | 32 | 33 | 34 | {/* Testimonials Section */} 35 | 36 | 37 | 38 | 39 | {/* Call to Action */} 40 | 41 | 42 | 43 | 44 | {/* Developer Section */} 45 | 46 |
47 |
48 |
49 | ); 50 | } 51 | 52 | export default SignUp; 53 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | We actively support the following versions of Yapper AI with security updates: 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 5.1.x | :white_check_mark: | 10 | | 5.0.x | :x: | 11 | | 4.0.x | :white_check_mark: | 12 | | < 4.0 | :x: | 13 | 14 | If you're using an unsupported version, we recommend upgrading to a supported version to ensure you receive the latest security fixes. 15 | 16 | --- 17 | 18 | ## Reporting a Vulnerability 19 | 20 | We take security issues seriously and appreciate your efforts in responsibly disclosing vulnerabilities. If you discover a security vulnerability, please follow these steps: 21 | 22 | 1. **Contact Us**: 23 | Email us at [shashanklhr](mailto:shashanklhr@gmail.com) with a detailed description of the issue. Include: 24 | - Affected version(s). 25 | - Steps to reproduce the vulnerability. 26 | - Potential impact of the issue. 27 | 28 | 2. **Response Timeline**: 29 | - We aim to acknowledge your report within **48 hours**. 30 | - You can expect a detailed update within **5 business days**, outlining our assessment and next steps. 31 | 32 | 3. **What to Expect**: 33 | - If the issue is valid, we will work on a fix and credit you in our release notes, if desired. 34 | - If the issue is declined, we will provide an explanation for our decision. 35 | 36 | 4. **Responsible Disclosure**: 37 | Please refrain from publicly disclosing the vulnerability until we have resolved it and released a patch. 38 | 39 | --- 40 | 41 | ## Security Best Practices for Users 42 | 43 | To maintain a secure environment when using Yapper AI, we recommend: 44 | 45 | - Regularly updating to the latest version. 46 | - Using strong authentication methods (e.g., secure Firebase login). 47 | - Reporting any unusual behavior or potential security issues promptly. 48 | -------------------------------------------------------------------------------- /src/assets/google-color-svgrepo-com.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Google-color Created with Sketch. 7 | -------------------------------------------------------------------------------- /src/components/Testimonials/Testimonial.jsx: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from 'react' 2 | 3 | const LazyCard = React.lazy(() => import("./TestimonialCard.jsx")) 4 | 5 | function Testimonial() { 6 | return ( 7 |
8 |

9 | What Our Users Say 10 |

11 |
12 | 13 | 17 | 18 | 19 | 23 | 24 | 25 | 29 | 30 | 31 | 35 | 36 | 37 | 41 | 42 | 43 | 47 | 48 | 49 |
50 |
51 | ) 52 | } 53 | 54 | export default Testimonial -------------------------------------------------------------------------------- /src/components/Header/Header.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { getAuth, signOut } from "firebase/auth"; 3 | import { useNavigate } from "react-router-dom"; 4 | 5 | function Header() { 6 | const navigate = useNavigate() 7 | const currentUser = localStorage.getItem("userName"); 8 | const handleSignOut = () => { 9 | const auth = getAuth(); 10 | signOut(auth) 11 | .then(() => { 12 | console.log("sign out successfull"); 13 | localStorage.removeItem("userName") 14 | navigate('/signup') 15 | }) 16 | .catch((error) => { 17 | console.log("Error", error); 18 | }); 19 | }; 20 | 21 | return ( 22 |
23 |
24 |
25 | 26 |
YAI
27 |
28 |
29 |
30 |

31 | A certified degree holder in yappanese 32 |

33 | {currentUser ? ( 34 | <> 35 |
36 | {currentUser} 37 |
38 | 44 | 45 | ) : ( 46 |
47 | Sign In 48 |
49 | )} 50 | 51 | 52 |
53 |
54 | ); 55 | } 56 | 57 | export default Header; 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yapper AI 🤖 2 | 3 | Welcome to **Yapper AI** – an innovative chatbot that offers numerous companions to talk to, each with a unique personality based on current world trends. Whether you're looking for a friendly chat, intellectual discussion, or some lighthearted fun, Yapper AI has it all! 4 | 5 | 🚀 **[Yapper AI - Live App](https://yapper-ai.vercel.app/)** 6 | 7 | ## 📚 Overview 8 | 9 | **Yapper AI** is a modern, feature-rich chatbot web app built using ReactJS, TailwindCSS, and the powerful **Gemini Flash 1.5** model. The app features a wide range of personalities users can interact with, from the trending **Sigma Male** persona to a playful **Baby** companion. Each personality offers a unique conversational experience tailored to different moods and trends. 10 | 11 | This project is open-source, and we welcome developers to contribute to its ongoing development! 12 | 13 | ## 🎨 Features 14 | 15 | - **Personalized Chat Companions:** Multiple personalities based on modern trends such as Desi Indian, Caring Girlfriend, Anime Characters, and more. 16 | - **Advanced Markdown Rendering:** Complex markdown text is used to display beautifully formatted, highlighted chat content. 17 | - **Firebase Authentication:** Secure login and user management with Firebase integration. 18 | - **Responsive Design:** The app is fully responsive, providing a seamless experience across devices, powered by TailwindCSS. 19 | - **Open Source Contribution:** Yapper AI is open to contributions from developers who want to enhance its features and functionalities. 20 | 21 | ## 🛠️ Tech Stack 22 | 23 | - **Frontend:** ReactJS, TailwindCSS 24 | - **Backend Model:** Gemini Flash 1.5 (for chatbot personalities) 25 | - **Authentication:** Firebase 26 | - **Markdown Rendering:** React Markdown 27 | - **Deployment:** Vercel 28 | 29 | ## 🤝 Contributing 30 | 31 | We welcome contributions to Yapper AI! To get started: 32 | 33 | 1. Fork this repository 34 | 2. Create a new branch: 35 | ```bash 36 | git checkout -b feature/your-feature 37 | ``` 38 | 3. Commit your changes 39 | ```bash 40 | git commit -m "Add some features" 41 | ``` 42 | 4. Push to the branch: 43 | ```bash 44 | git push origin feature/your-feature 45 | ``` 46 | 5.Open a pull request 47 | 48 | please make sure your code adheres to our coding standards and is well documented. 49 | 50 | ## 📄 License 51 | 52 | This project is open source under the MIT License. Feel free to use it as you see fit. 53 | 54 | ## 🌐 Links 55 | 56 | - **Live App:** [Yapper AI](https://yapper-ai.vercel.app/) 57 | - **Github Repository URL:** [Yapper AI Github](https://github.com/Ganesh-Sharmaz/YapperAI) 58 | 59 | ## ✨ Contributors 60 | 61 | Thanks to all the amazing developers who have contributed to the project. 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/components/Features/Features.jsx: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from 'react' 2 | import FeatureCard from './FeatureCard' 3 | 4 | const LazyFCard = React.lazy(() => import('./FeatureCard.jsx')) 5 | 6 | function Features() { 7 | return ( 8 |
9 |

10 | Personalities that Speak to You 11 |

12 |
13 | 14 | 18 | 19 | 20 | 24 | 25 | 26 | 30 | 31 | 32 | 36 | 37 | 38 | 42 | 43 | 44 | 48 | 49 | 50 | 54 | 55 | 56 | 60 | 61 | 62 | 66 | 67 |
68 |
69 | ) 70 | } 71 | 72 | export default Features -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for considering contributing to Yapper AI! We welcome all contributions that help improve the project and create a better experience for users. By participating in this project, you agree to abide by our [Code of Conduct](CODE_OF_CONDUCT.md). 4 | 5 | ## How to Contribute 6 | 7 | ### Reporting Bugs 8 | If you find a bug, please: 9 | 1. **Search existing issues** to ensure it hasn’t already been reported. 10 | 2. Create a new issue with the following details: 11 | - **Title:** A clear and descriptive title. 12 | - **Description:** Steps to reproduce the bug, expected behavior, and actual behavior. 13 | - **Environment:** Browser, operating system, and any other relevant context. 14 | 15 | ### Suggesting Features 16 | We’re always looking for new ideas! To suggest a feature: 17 | 1. **Search existing issues** to avoid duplicates. 18 | 2. Open a new issue and include: 19 | - **Title:** A concise summary of the feature. 20 | - **Description:** A detailed explanation of the feature and its benefits. 21 | 22 | ### Improving Documentation 23 | - Found a typo or something unclear? Submit a pull request with your changes. 24 | - Documentation is located in the `/docs` directory. 25 | 26 | ### Submitting Code Contributions 27 | 28 | #### Prerequisites 29 | 1. Ensure you have Node.js and npm installed. 30 | 2. Fork the repository and clone it locally: 31 | ```bash 32 | git clone https://github.com/YOUR_USERNAME/YapperAI.git 33 | ``` 34 | 3. Install dependencies: 35 | ```bash 36 | npm install 37 | ``` 38 | 4. Create a new branch for your feature or fix: 39 | ```bash 40 | git checkout -b feature/your-feature 41 | ``` 42 | 43 | #### Development Workflow 44 | 1. Write clean, readable, and well-documented code. 45 | 2. Test your changes thoroughly. 46 | 3. Ensure your code follows our coding standards and passes linting: 47 | ```bash 48 | npm run lint 49 | ``` 50 | 4. Commit your changes: 51 | ```bash 52 | git commit -m "Add description of your changes" 53 | ``` 54 | 5. Push your branch to your fork: 55 | ```bash 56 | git push origin feature/your-feature 57 | ``` 58 | 6. Open a pull request (PR) to the `main` branch: 59 | - Provide a clear title and description of your changes. 60 | - Include any relevant issue references (e.g., "Closes #123"). 61 | 62 | #### Code Review Process 63 | - A maintainer will review your PR and provide feedback if needed. 64 | - Please address review comments promptly. 65 | - Once approved, your PR will be merged into the main branch. 66 | 67 | ## Coding Standards 68 | - Follow the **DRY** (Don’t Repeat Yourself) principle. 69 | - Write meaningful commit messages. 70 | - Use descriptive variable and function names. 71 | - Ensure components are reusable and modular. 72 | 73 | ## Issues and Help 74 | If you’re stuck, feel free to ask for help by commenting on an issue or tagging a maintainer in your pull request. 75 | 76 | Thank you for contributing to Yapper AI! 🚀 77 | 78 | -------------------------------------------------------------------------------- /src/components/About/About.jsx: -------------------------------------------------------------------------------- 1 | import { GitHub } from "@mui/icons-material"; 2 | import React from "react"; 3 | import { useLoaderData } from "react-router-dom"; 4 | 5 | function About() { 6 | const data = useLoaderData(); 7 | 8 | return ( 9 |
10 |
11 |

12 | Developer 13 |

14 |
15 | Developer Avatar 20 |
21 |

{data.name}

22 |
23 |

24 | MERN stack developer passionate about building 25 | interactive web applications. Creator of Yapper AI. 26 |

27 |
28 | 34 | 35 | 36 |
37 |
38 |

39 | I welcome contributions and feedback from fellow 40 | developers. 41 |

42 |
43 |

44 | Contribute here: {" "} 45 | 51 | Yapper AI Repository 52 | 53 |

54 |
55 |
56 |
57 |
58 |
59 | ); 60 | } 61 | 62 | export const gitInfoLoader = async () => { 63 | const response = await fetch("https://api.github.com/users/Ganesh-Sharmaz"); 64 | return response.json(); 65 | }; 66 | 67 | export default About; 68 | -------------------------------------------------------------------------------- /src/components/Hero/Hero.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { signInWithPopup, GoogleAuthProvider } from "firebase/auth"; 3 | import { auth } from "../Server/server.js"; 4 | import { useNavigate } from "react-router-dom"; 5 | import GoogleImg from '../../assets/google-color-svgrepo-com.png' 6 | 7 | function Hero() { 8 | const navigate = useNavigate(); 9 | 10 | const provider = new GoogleAuthProvider(); 11 | const handleSignIn = () => { 12 | signInWithPopup(auth, provider) 13 | .then((result) => { 14 | // This gives you a Google Access Token. You can use it to access the Google API. 15 | const credential = 16 | GoogleAuthProvider.credentialFromResult(result); 17 | const token = credential.accessToken; 18 | // The signed-in user info. 19 | const user = result.user; 20 | console.log("User: ", user); 21 | console.log("sign in successful"); 22 | 23 | if (user) { 24 | localStorage.setItem("userName", user.displayName); 25 | navigate("/"); 26 | } 27 | // IdP data available using getAdditionalUserInfo(result) 28 | // ... 29 | }) 30 | .catch((error) => { 31 | // Handle Errors here. 32 | const errorCode = error.code; 33 | const errorMessage = error.message; 34 | console.log(errorCode, errorMessage); 35 | const email = error.customData.email; 36 | // The AuthCredential type that was used. 37 | const credential = 38 | GoogleAuthProvider.credentialFromError(error); 39 | // ... 40 | }); 41 | }; 42 | 43 | return ( 44 |
45 |
46 |
47 |

YAPPER AI

48 |
49 |

50 | Your AI companion, with personalities that match your every 51 | mood! 52 |

53 |
54 |
55 |
56 |

Sign Up

57 |
58 |
62 | googleicon 67 |

Sign in with Google

68 |
69 |
70 |
71 | ); 72 | } 73 | 74 | export default Hero; 75 | -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | shashanklhr@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /src/components/Home/Home.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { GoogleGenerativeAI } from "@google/generative-ai"; 3 | import { useRef, useEffect, useState } from "react"; 4 | import { Send } from "@mui/icons-material"; 5 | import rehypeHighlight from "rehype-highlight"; 6 | import remarkGfm from "remark-gfm"; 7 | import "highlight.js/styles/github.css"; 8 | 9 | import "katex/dist/katex.min.css"; 10 | 11 | import { 12 | Dropdown, 13 | DropdownTrigger, 14 | DropdownMenu, 15 | DropdownItem, 16 | Button, 17 | } from "@nextui-org/react"; 18 | 19 | import ReactMarkdown from "react-markdown"; 20 | 21 | 22 | function Home() { 23 | console.log("Arrived at Homepage"); 24 | const [inputValue, setInputValue] = useState(""); 25 | 26 | const [chatHistory, setChatHistory] = useState([]); 27 | 28 | const [currentVoice, setCurrentVoice] = useState(0); 29 | 30 | const [activityIndex, setActivityIndex] = useState(0); 31 | 32 | const inputRef = useRef(null); 33 | const chatEndRef = useRef(null); 34 | const VoiceList = [ 35 | { person: "Desi", prompt: "Hinglish and sarcasm" }, 36 | { person: "Baby", prompt: "silly baby voice" }, 37 | { 38 | person: "intellectual", 39 | prompt: "english and help me with the problem", 40 | }, 41 | { person: "Girlfriend", prompt: "caring girlfriend voice" }, 42 | 43 | { 44 | person: "Royal", 45 | prompt: " talk in gardinose style and royal voice ", 46 | }, 47 | { person: "BrainRot", prompt: " funny brainrot" }, 48 | { 49 | person: "Real AI", 50 | prompt: "Hypothetical Evil AI", 51 | }, 52 | { 53 | person: "Anime", 54 | prompt: "voice of any random anime main character and provide the name of the main character", 55 | }, 56 | 57 | { person: "Sigma Male", prompt: "sigma male voice, like the top g" }, 58 | ]; 59 | 60 | useEffect(() => { 61 | chatEndRef.current?.scrollIntoView({ behavior: "smooth" }); 62 | }, [inputValue]); 63 | 64 | useEffect(() => { 65 | // Function to handle keypress event 66 | const handleKeyPress = (event) => { 67 | if (event.key === "/") { 68 | event.preventDefault(); // Prevent typing the '/' into the input field 69 | if (inputRef.current) { 70 | inputRef.current.focus(); // Focus the input field 71 | } 72 | } 73 | }; 74 | 75 | // Add event listener for keydown 76 | window.addEventListener("keydown", handleKeyPress); 77 | 78 | // Clean up the event listener on component unmount 79 | return () => { 80 | window.removeEventListener("keydown", handleKeyPress); 81 | }; 82 | }, []); 83 | 84 | const handleSubmit = async (e) => { 85 | e.preventDefault(); 86 | if (inputValue.trim !== "") { 87 | setChatHistory((prevHistory) => [ 88 | ...prevHistory, 89 | { 90 | type: "user", 91 | text: inputValue, 92 | }, 93 | ]); 94 | 95 | setInputValue(""); 96 | 97 | setChatHistory((prevHistory) => [ 98 | ...prevHistory, 99 | { 100 | type: "bot", 101 | text: "...", 102 | }, 103 | ]); 104 | 105 | try { 106 | const genAI = new GoogleGenerativeAI( 107 | import.meta.env.VITE_REACT_GEMINI_API 108 | ); 109 | const model = genAI.getGenerativeModel({ 110 | model: "gemini-1.5-flash", 111 | }); 112 | 113 | const prompt = `Give response in ${VoiceList[currentVoice].prompt} to the further message, ${inputValue}`; 114 | 115 | const chat = model.startChat({ 116 | history: [ 117 | { 118 | role: "user", 119 | parts: [{ text: "Hello" }], 120 | }, 121 | { 122 | role: "model", 123 | parts: [ 124 | { 125 | text: "Great to meet you. What would you like to know?", 126 | }, 127 | ], 128 | }, 129 | ], 130 | }); 131 | 132 | let result = await chat.sendMessage(prompt); 133 | console.log(result.response.text()); 134 | 135 | // const result = await model.generateContent(prompt); 136 | // console.log(result.response.text()); 137 | const textResponse = result.response.text(); 138 | setChatHistory((prevHistory) => 139 | prevHistory.map((msg) => 140 | msg.text === "..." 141 | ? { type: "bot", text: textResponse } 142 | : msg 143 | ) 144 | ); 145 | } catch (error) { 146 | console.error("Error while fetching the values", error); 147 | setChatHistory((prevHistory) => 148 | prevHistory.map((msg) => 149 | msg.text === "..." 150 | ? { type: "Enable to fetch request." } 151 | : msg 152 | ) 153 | ); 154 | } 155 | } 156 | }; 157 | 158 | useEffect(() => { 159 | chatEndRef.current?.scrollIntoView({ behavior: "smooth" }); 160 | }, [chatHistory]); 161 | 162 | const handleActive = (index) => { 163 | setActivityIndex(index); 164 | setCurrentVoice(index); 165 | }; 166 | 167 | const [selectedKeys, setSelectedKeys] = React.useState(new Set(["Desi"])); 168 | 169 | const selectedValue = React.useMemo( 170 | () => Array.from(selectedKeys).join(", ").replaceAll("_", " "), 171 | [selectedKeys] 172 | ); 173 | 174 | 175 | 176 | 177 | 178 | return ( 179 |
180 | {/* for big screens */} 181 |
182 | {VoiceList.map((voice, index) => ( 183 | 194 | ))} 195 |
196 | 197 | {/* for small screens */} 198 | 199 |
200 | 201 | 202 | 209 | 210 | 219 | {VoiceList.map((msg, index) => ( 220 | handleActive(index)} 227 | key={msg.person} 228 | > 229 | {msg.person} 230 | 231 | ))} 232 | 233 | 234 |
235 | 236 |
237 |
238 | {chatHistory.map((msg, index) => ( 239 | <> 240 |

248 | ( 254 |

258 | ), 259 | h2: (props) => ( 260 |

264 | ), 265 | h3: (props) => ( 266 |

270 | ), 271 | h4: (props) => ( 272 |

276 | ), 277 | h5: (props) => ( 278 |

282 | ), 283 | h6: (props) => ( 284 |
288 | ), 289 | 290 | // Bold and Italic 291 | strong: (props) => ( 292 | 296 | ), 297 | em: (props) => ( 298 | 302 | ), 303 | 304 | // Paragraph 305 | p: (props) => ( 306 |

310 | ), 311 | 312 | // Lists 313 | ul: (props) => ( 314 |

400 |
401 |
405 | { 412 | setInputValue(e.target.value); 413 | }} 414 | className=" placeholder:text-slate-300 bg-[#2c2b2b] w-full rounded-full focus:outline-none transition ease-in-out h-10 px-10 py-2 flex items-center justify-center" 415 | /> 416 | 417 | 420 |
421 |
422 |
423 | ); 424 | } 425 | 426 | export default Home; 427 | --------------------------------------------------------------------------------