├── .env.example ├── .eslintrc.json ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.yml ├── PR_TEMPLATE │ └── PULL_REQUEST_TEMPLATE.md └── workflows │ └── node.js.yml ├── .gitignore ├── README.md ├── components.json ├── next.config.mjs ├── package-lock.json ├── package.json ├── postcss.config.mjs ├── public └── f1.jpg ├── src ├── app │ ├── (auth) │ │ ├── login │ │ │ └── page.tsx │ │ └── signup │ │ │ └── page.tsx │ ├── (marketing) │ │ ├── about │ │ │ └── page.tsx │ │ ├── contact │ │ │ └── page.tsx │ │ ├── faq │ │ │ └── page.tsx │ │ ├── privacy │ │ │ └── page.tsx │ │ └── terms │ │ │ └── page.tsx │ ├── (pages) │ │ ├── [username] │ │ │ └── page.tsx │ │ ├── leaderboard │ │ │ └── page.tsx │ │ ├── leetcode-190 │ │ │ └── page.tsx │ │ ├── lobby │ │ │ └── page.tsx │ │ ├── playground │ │ │ └── page.tsx │ │ ├── profile │ │ │ └── page.tsx │ │ ├── status │ │ │ └── page.tsx │ │ └── subscription │ │ │ └── page.tsx │ ├── api │ │ ├── leaderboard │ │ │ └── route.ts │ │ ├── login │ │ │ └── route.ts │ │ ├── logout │ │ │ └── route.ts │ │ ├── orders │ │ │ ├── route.ts │ │ │ └── user │ │ │ │ └── route.ts │ │ ├── player-profile │ │ │ └── route.ts │ │ ├── profile │ │ │ └── route.ts │ │ ├── signup │ │ │ └── route.ts │ │ ├── store-result │ │ │ └── route.ts │ │ ├── verify-payment │ │ │ └── route.ts │ │ └── webhooks │ │ │ └── razorpay │ │ │ └── route.ts │ ├── favicon.ico │ ├── fonts │ │ ├── GeistMonoVF.woff │ │ └── GeistVF.woff │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── components │ ├── custom │ │ ├── AnimatedTooltip.tsx │ │ ├── Footer.tsx │ │ ├── Hero.tsx │ │ ├── HeroSection.tsx │ │ ├── ModeToggle.tsx │ │ └── Navbar.tsx │ ├── theme-providers.tsx │ └── ui │ │ ├── Spotlight.tsx │ │ ├── accordion.tsx │ │ ├── alert.tsx │ │ ├── animated-tooltip.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── checkbox.tsx │ │ ├── container-scroll-animation.tsx │ │ ├── dialog.tsx │ │ ├── dropdown-menu.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── progress.tsx │ │ ├── select.tsx │ │ ├── sheet.tsx │ │ ├── skeleton.tsx │ │ ├── table.tsx │ │ ├── textarea.tsx │ │ └── tooltip.tsx ├── data │ ├── pattern.ts │ └── sampleParagraphs.ts ├── dbconfig │ └── dbconfig.ts ├── lib │ ├── getDataFromToken.ts │ ├── ratelimit.ts │ └── utils.ts ├── models │ ├── order.model.ts │ └── user.model.ts └── store │ └── useStore.ts ├── tailwind.config.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | MONGODB_URL= 2 | TOKEN_SECRET= -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals", "next/typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: '🐛 Bug Report' 2 | description: 'Submit a bug report to help us improve' 3 | title: '🐛 Bug Report: ' 4 | labels: ['type: bug'] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: We value your time and effort to submit this bug report. 🙏 9 | - type: textarea 10 | id: description 11 | validations: 12 | required: true 13 | attributes: 14 | label: '📜 Description' 15 | description: 'A clear and concise description of what the bug is.' 16 | placeholder: 'It bugs out when ...' 17 | - type: textarea 18 | id: steps-to-reproduce 19 | validations: 20 | required: true 21 | attributes: 22 | label: '👟 Reproduction steps' 23 | description: 'How do you trigger this bug? Please walk us through it step by step.' 24 | placeholder: "1. Go to '...' 25 | 2. Click on '....' 26 | 3. Scroll down to '....' 27 | 4. See the error" 28 | - type: textarea 29 | id: expected-behavior 30 | validations: 31 | required: true 32 | attributes: 33 | label: '👍 Expected behavior' 34 | description: 'What did you think should happen?' 35 | placeholder: 'It should ...' 36 | - type: textarea 37 | id: actual-behavior 38 | validations: 39 | required: true 40 | attributes: 41 | label: '👎 Actual Behavior with Screenshots' 42 | description: 'What did actually happen? Add screenshots, if applicable.' 43 | placeholder: 'It actually ...' 44 | - type: dropdown 45 | id: os-version 46 | validations: 47 | required: true 48 | attributes: 49 | label: OS name 50 | description: In case of self-hosting or local installation mention the OS name. 51 | options: 52 | - Windows 53 | - Linux 54 | - MacOS 55 | - type: dropdown 56 | id: browser-name 57 | validations: 58 | required: true 59 | attributes: 60 | label: browser name 61 | description: In case of self-hosting or local installation mention the browser name. 62 | options: 63 | - Firefox 64 | - Chrome 65 | - Brave 66 | - Other 67 | 68 | - type: input 69 | id: npm-version 70 | validations: 71 | required: false 72 | attributes: 73 | label: npm version 74 | description: In case of self-hosting or local installation mention the npm version. 75 | placeholder: 7.0.0 76 | - type: input 77 | id: node-version 78 | validations: 79 | required: false 80 | attributes: 81 | label: node version 82 | description: In case of self-hosting or local installation mention the node version. 83 | placeholder: 20.0.0 84 | - type: textarea 85 | id: additional-context 86 | validations: 87 | required: false 88 | attributes: 89 | label: '📃 Provide any additional context for the Bug.' 90 | description: 'Add any other context about the problem here.' 91 | placeholder: 'It actually ...' 92 | - type: checkboxes 93 | id: no-duplicate-issues 94 | attributes: 95 | label: '👀 Have you spent some time to check if this bug has been raised before?' 96 | options: 97 | - label: "I checked and didn't find a similar issue" 98 | required: true 99 | - type: checkboxes 100 | id: read-code-of-conduct 101 | attributes: 102 | label: '🏢 Have you read the Contributing Guidelines?' 103 | options: 104 | - label: 'I have read the [Contributing Guidelines](https://github.com/code100x/job-board/blob/main/CONTRIBUTING.md)' 105 | required: true 106 | - type: dropdown 107 | attributes: 108 | label: Are you willing to submit PR? 109 | description: This is absolutely not required, but we are happy to guide you in the contribution process. 110 | options: 111 | - 'Yes I am willing to submit a PR!' -------------------------------------------------------------------------------- /.github/PR_TEMPLATE/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | 4 | 5 | ### Related Issue 6 | 7 | 8 | 9 | ### Changes Made 10 | 11 | 12 | 13 | ### Screenshots 14 | 15 | 16 | 17 | ### Checklist 18 | 19 | - [ ] I have tagged the issue in this PR. 20 | - [ ] I have attached necessary screenshots. 21 | - [ ] I have provided a short description of the PR. 22 | - [ ] I ran `yarn build` and build is successful 23 | - [ ] My code follows the style guidelines of this project. 24 | - [ ] I have added necessary documentation (if applicable) -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | name: Next.js Build 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Set up Node.js 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version: 18.x # You can change this to your preferred Node.js version 20 | 21 | - run: npm install 22 | 23 | - run: npm run build 24 | -------------------------------------------------------------------------------- /.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 | .env 31 | 32 | # vercel 33 | .vercel 34 | 35 | # typescript 36 | *.tsbuildinfo 37 | next-env.d.ts 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Type Arena 2 | 3 | **Type Arena** is a fast-paced multiplayer typing game that challenges your typing speed and accuracy. Compete with others in real-time to prove you're the fastest typist in the arena! 4 | 5 | ## Table of Contents 6 | - [Features](#features) 7 | - [Getting Started](#getting-started) 8 | - [Installation](#installation) 9 | - [How to Play](#how-to-play) 10 | - [Contributing](#contributing) 11 | - [Technologies Used](#technologies-used) 12 | - [Deployment](#deployment) 13 | 14 | 15 | ## Features 16 | 17 | - **Real-Time Multiplayer**: Play against other players in real-time typing matches. 18 | - **Live Scoreboard**: Track your rank and progress during live games. 19 | - **Typing Speed & Accuracy**: Monitor your Words Per Minute (WPM) and accuracy in every game. 20 | - **Leaderboard**: Compare your scores with players worldwide. 21 | - **Custom Game Rooms**: Create personalized game rooms with custom settings such as word length, game duration, and more. 22 | - **Mobile & Desktop Friendly**: Fully responsive design for both desktop and mobile users. 23 | - **Authentication**: Authentication system to signup, login, logout and reset password(to be done) 24 | 25 | ## to be added 26 | 27 | - **Profile**: Profile page to show all the matches played and stats 28 | - **Leaderboard**: Leaderboard page to show the top players and their stats 29 | - **Settings**: Settings page to change the game settings 30 | - **Achievements**: Achievements page to show the achievements and rewards to engaze user 31 | - **Shop**: Shop page to buy the premium features 🤔 32 | - **Friends**: Friends page to add friends and chat with them 33 | - **Chat**: Chat page to chat with other players 34 | - **Notifications**: Notifications page to show the notifications 35 | - 36 | 37 | ## Getting Started 38 | 39 | Follow the instructions below to set up and run Type Arena on your local machine. 40 | 41 | ### Prerequisites 42 | 43 | You will need to have the following installed on your system: 44 | 45 | - [Node.js](https://nodejs.org/) (v20 or newer) 46 | - [npm](https://www.npmjs.com/) (or Yarn, pnpm, or bun) 47 | - Git (recommended for cloning the repository) 48 | 49 | ### Installation 50 | 51 | 1. Clone the repository: 52 | 53 | ```bash 54 | git clone https://github.com/yourusername/type-arena.git 55 | ``` 56 | 57 | ```bash 58 | cd type-arena 59 | npm install 60 | npm run dev 61 | ``` 62 | 63 | Open your browser and navigate to http://localhost:3000 to access the game. 64 | 65 | ## How to Play 66 | 67 | 1. **Join or Create a Room**: Enter an existing game room or create a custom one with your preferred settings (e.g., word length, game duration). 68 | 2. **Start Typing**: Type the provided text as quickly and accurately as possible once the game begins. 69 | 3. **Live Scoreboard**: Track your typing speed (Words Per Minute) and accuracy during the game in real-time. 70 | 4. **Win the Game**: The player with the highest WPM and accuracy at the end of the match wins! 71 | 72 | ## Contributing 73 | 74 | We welcome contributions to enhance Type Arena! Here’s how you can contribute: 75 | 76 | 1. Fork the repository. 77 | 2. Create a new branch for your feature or fix: 78 | 79 | ```bash 80 | git checkout -b feature/YourFeatureName 81 | ``` 82 | 83 | commit the changes 84 | 85 | ```bash 86 | git commit -m "Add YourFeatureName" 87 | ``` 88 | 89 | 3. push to the brach 90 | ```bash 91 | git push origin feature/YourFeatureName 92 | ``` 93 | 4. Open a pull request, and we will review it. 94 | 95 | ## Technologies Used 96 | 97 | 1. Next.js - React-based framework for building the frontend. 98 | 99 | 2. Socket.io - Enables real-time, bidirectional communication between players. 100 | 101 | 3. Tailwind CSS - Utility-first CSS framework used for designing the UI. 102 | 4. React - JavaScript library for building user interfaces. 103 | 5. Vercel - Platform for deploying and hosting the application. 104 | 105 | ## Deployment 106 | 107 | for frontend deployment we are using vercel and for backend we are figuring out either free or cheap for as of now (for backend we have express and socket io server ) and for auth and all we are using next js api/ route.ts 108 | 109 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | } 20 | } -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | eslint: { 4 | // Warning: This allows production builds to successfully complete 5 | // even if your project has ESLint errors. 6 | ignoreDuringBuilds: true, 7 | }, 8 | images: { 9 | remotePatterns: [ 10 | { 11 | protocol: 'https', 12 | hostname: 'images.unsplash.com', 13 | }, 14 | ], 15 | }, 16 | }; 17 | 18 | export default nextConfig; 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typearena", 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 | "@radix-ui/react-accordion": "^1.2.1", 13 | "@radix-ui/react-avatar": "^1.1.2", 14 | "@radix-ui/react-checkbox": "^1.1.2", 15 | "@radix-ui/react-dialog": "^1.1.3", 16 | "@radix-ui/react-dropdown-menu": "^2.1.4", 17 | "@radix-ui/react-icons": "^1.3.0", 18 | "@radix-ui/react-label": "^2.1.0", 19 | "@radix-ui/react-progress": "^1.1.0", 20 | "@radix-ui/react-select": "^2.1.2", 21 | "@radix-ui/react-slot": "^1.1.0", 22 | "@radix-ui/react-tooltip": "^1.1.6", 23 | "@vercel/analytics": "^1.3.1", 24 | "axios": "^1.7.7", 25 | "bcryptjs": "^2.4.3", 26 | "class-variance-authority": "^0.7.0", 27 | "clsx": "^2.1.1", 28 | "framer-motion": "^11.15.0", 29 | "jsonwebtoken": "^9.0.2", 30 | "lucide-react": "^0.447.0", 31 | "mongoose": "^8.7.1", 32 | "next": "14.2.14", 33 | "next-themes": "^0.4.4", 34 | "razorpay": "^2.9.5", 35 | "react": "^18", 36 | "react-dom": "^18", 37 | "react-hot-toast": "^2.4.1", 38 | "socket.io-client": "^4.8.0", 39 | "tailwind-merge": "^2.5.5", 40 | "tailwindcss-animate": "^1.0.7", 41 | "zustand": "^5.0.0" 42 | }, 43 | "devDependencies": { 44 | "@types/bcryptjs": "^2.4.6", 45 | "@types/jsonwebtoken": "^9.0.7", 46 | "@types/node": "^20", 47 | "@types/react": "^18", 48 | "@types/react-dom": "^18", 49 | "eslint": "^8", 50 | "eslint-config-next": "14.2.14", 51 | "postcss": "^8", 52 | "tailwindcss": "^3.4.1", 53 | "typescript": "^5" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /public/f1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itzamanjain/TypeArena/69f4022cd8b2830bc16c0c3f897413f85a0b97f7/public/f1.jpg -------------------------------------------------------------------------------- /src/app/(auth)/login/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import Link from 'next/link' 4 | import { Button } from "@/components/ui/button" 5 | import { Input } from "@/components/ui/input" 6 | import { Label } from "@/components/ui/label" 7 | import { useState } from 'react' 8 | import axios from 'axios' 9 | import { useRouter } from 'next/navigation' 10 | import useAuthStore from '@/store/useStore' 11 | import toast, { Toaster } from 'react-hot-toast'; 12 | 13 | export default function LoginPage() { 14 | 15 | const router = useRouter(); 16 | const { login } = useAuthStore(); 17 | 18 | const [user, setUser] = useState({ 19 | email: '', 20 | password: '' 21 | }); 22 | 23 | const [loading, setLoading] = useState(false); 24 | 25 | const handleChange = (e: React.ChangeEvent) => { 26 | setUser({ 27 | ...user, 28 | [e.target.name]: e.target.value 29 | }); 30 | }; 31 | 32 | const handleSubmit = async (e: React.FormEvent) => { 33 | e.preventDefault(); 34 | setLoading(true); 35 | 36 | try { 37 | const response = await axios.post('/api/login', user); 38 | const userData = response.data.user; 39 | login(userData); 40 | toast.success('Logged in successfully'); 41 | router.push('/playground'); 42 | } catch (error: any) { 43 | toast.error(error.response.data?.message || 'Failed to login'); 44 | console.error("Error during login:", error); 45 | } finally { 46 | setLoading(false); // Set loading back to false after request completes 47 | } 48 | }; 49 | 50 | return ( 51 |
52 |
53 |
54 |

Welcome back

55 |

Log in to your account

56 |
57 |
58 |
59 |
60 | 61 | 71 |
72 |
73 | 74 | 83 |
84 |
85 |
86 |
87 | 93 | 96 |
97 |
98 | 99 | Forgot your password? 100 | 101 |
102 |
103 | 106 |
107 |
108 |

109 | Don't have an account?{' '} 110 | 111 | Sign up 112 | 113 |

114 |
115 |
116 | 120 |
121 | ); 122 | } 123 | -------------------------------------------------------------------------------- /src/app/(auth)/signup/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import Link from 'next/link' 3 | import { Button } from "@/components/ui/button" 4 | import { Input } from "@/components/ui/input" 5 | import { Label } from "@/components/ui/label" 6 | import axios from 'axios' 7 | import { useState } from 'react' 8 | import { useRouter } from 'next/navigation' 9 | import toast, { Toaster } from 'react-hot-toast' 10 | 11 | export default function SignupPage() { 12 | 13 | const router = useRouter(); 14 | 15 | const [user, setUser] = useState({ 16 | fullname: '', 17 | username: '', 18 | email: '', 19 | password: '' 20 | }) 21 | const [loading, setLoading] = useState(false); 22 | 23 | const handleChange = (e: React.ChangeEvent) => { 24 | setUser({ 25 | ...user, 26 | [e.target.name]: e.target.value 27 | }) 28 | } 29 | 30 | const handleSubmit = async (e: React.FormEvent) => { 31 | e.preventDefault(); // Prevent form from refreshing the page 32 | try { 33 | setLoading(true); 34 | const response = await axios.post('/api/signup', user); 35 | console.log(response.data); 36 | toast.success('Account created successfully'); 37 | router.push('/login'); 38 | 39 | } catch (error: any) { 40 | toast.error(error.response.data?.message || 'Failed to create account'); 41 | console.log("Error while signing up:", error); 42 | }finally{ 43 | setLoading(false); 44 | } 45 | } 46 | 47 | return ( 48 |
49 |
50 |
51 |

Create an account

52 |

Sign up to get started

53 |
54 |
55 |
56 |
57 | 58 | 59 |
60 |
61 | 62 | 63 |
64 |
65 | 66 | 67 |
68 |
69 | 70 | 71 |
72 |
73 | 76 |
77 |
78 |

79 | Already have an account?{' '} 80 | 81 | Log in 82 | 83 |

84 |
85 |
86 | 90 |
91 | ) 92 | } 93 | -------------------------------------------------------------------------------- /src/app/(marketing)/about/page.tsx: -------------------------------------------------------------------------------- 1 | 2 | export default function AboutPage() { 3 | return ( 4 |
5 | 6 |
7 |

About TypeArena

8 |
9 |

10 | TypeArena is a cutting-edge platform designed to help individuals improve their typing skills through engaging challenges and competitions. Our mission is to make typing practice fun, social, and rewarding. 11 |

12 |

13 | Founded in Oct 2024, TypeArena has quickly grown to become a favorite among typing enthusiasts, students, and professionals looking to enhance their keyboard proficiency. Our team of dedicated developers and typing experts work tirelessly to create new challenges, improve user experience, and foster a supportive community. 14 |

15 |

16 | At TypeArena, we believe that strong typing skills are essential in today's digital world. Whether you're a beginner looking to increase your typing speed or an expert aiming to break records, TypeArena offers a range of features to help you achieve your goals. 17 |

18 |

Our Features

19 |
    20 |
  • Real-time multiplayer typing races
  • 21 |
  • Personalized practice sessions
  • 22 |
  • Daily challenges and leaderboards
  • 23 |
  • Detailed performance analytics
  • 24 |
  • Typing games and themed challenges
  • 25 |
26 |
27 |
28 | 29 |
30 | ) 31 | } -------------------------------------------------------------------------------- /src/app/(marketing)/contact/page.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@/components/ui/button" 2 | import { Input } from "@/components/ui/input" 3 | import { Textarea } from "@/components/ui/textarea" 4 | import { Label } from "@/components/ui/label" 5 | 6 | export default function ContactPage() { 7 | return ( 8 |
9 | 10 |
11 |

Contact Us

12 |
13 |

14 | Have a question or feedback? We'd love to hear from you. Fill out the form below and we'll get back to you as soon as possible. 15 |

16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 |
26 | 27 | 28 |
29 |
30 | 31 |