├── Backend ├── README.md ├── .dockerignore ├── .env ├── testEnv.txt ├── src │ ├── index.js │ ├── utils │ │ ├── ApiResponse.js │ │ └── ApiError.js │ ├── models │ │ ├── skill.model.js │ │ ├── project.model.js │ │ ├── experience.model.js │ │ ├── education.model.js │ │ ├── user.model.js │ │ └── resume.model.js │ ├── routes │ │ ├── user.routes.js │ │ └── resume.routes.js │ ├── db │ │ └── index.js │ ├── app.js │ ├── middleware │ │ └── auth.js │ └── controller │ │ ├── user.controller.js │ │ └── resume.controller.js ├── Dockerfile ├── docker-compose.yml └── package.json ├── Frontend ├── src │ ├── pages │ │ ├── auth │ │ │ ├── index.js │ │ │ ├── Sign-In │ │ │ │ └── SignInPage.jsx │ │ │ └── customAuth │ │ │ │ └── AuthPage.jsx │ │ ├── dashboard │ │ │ ├── edit-resume │ │ │ │ ├── components │ │ │ │ │ ├── preview-components │ │ │ │ │ │ ├── SummaryPreview.jsx │ │ │ │ │ │ ├── SkillsPreview.jsx │ │ │ │ │ │ ├── PersonalDeatailPreview.jsx │ │ │ │ │ │ ├── ProjectPreview.jsx │ │ │ │ │ │ ├── EducationalPreview.jsx │ │ │ │ │ │ └── ExperiencePreview.jsx │ │ │ │ │ ├── PreviewPage.jsx │ │ │ │ │ ├── ThemeColor.jsx │ │ │ │ │ ├── ResumeForm.jsx │ │ │ │ │ └── form-components │ │ │ │ │ │ ├── Skills.jsx │ │ │ │ │ │ ├── PersonalDetails.jsx │ │ │ │ │ │ ├── Project.jsx │ │ │ │ │ │ ├── Education.jsx │ │ │ │ │ │ ├── Summary.jsx │ │ │ │ │ │ └── Experience.jsx │ │ │ │ └── [resume_id] │ │ │ │ │ └── EditResume.jsx │ │ │ ├── Dashboard.jsx │ │ │ ├── view-resume │ │ │ │ └── [resume_id] │ │ │ │ │ └── ViewResume.jsx │ │ │ └── components │ │ │ │ ├── AddResume.jsx │ │ │ │ └── ResumeCard.jsx │ │ └── home │ │ │ └── HomePage.jsx │ ├── assets │ │ ├── heroSnapshot.png │ │ └── react.svg │ ├── lib │ │ └── utils.js │ ├── config │ │ └── config.js │ ├── features │ │ ├── user │ │ │ └── userFeatures.js │ │ └── resume │ │ │ └── resumeFeatures.js │ ├── store │ │ └── store.js │ ├── components │ │ ├── ui │ │ │ ├── textarea.jsx │ │ │ ├── input.jsx │ │ │ ├── sonner.jsx │ │ │ ├── popover.jsx │ │ │ ├── button.jsx │ │ │ ├── alert-dialog.jsx │ │ │ └── dialog.jsx │ │ └── custom │ │ │ ├── Header.jsx │ │ │ ├── SimpeRichTextEditor.jsx │ │ │ └── RichTextEditor.jsx │ ├── Services │ │ ├── AiModel.js │ │ ├── login.js │ │ ├── GlobalApi.js │ │ └── resumeAPI.js │ ├── App.jsx │ ├── main.jsx │ └── index.css ├── .env.local ├── postcss.config.js ├── envTest.txt ├── jsconfig.json ├── vite.config.js ├── components.json ├── index.html ├── README.md ├── public │ ├── logo.svg │ └── vite.svg ├── .eslintrc.cjs ├── package.json ├── tailwind.config.js └── data │ └── dummy.js └── README.md /Backend/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shauryaverma03/AI-Resume-Builder/HEAD/Backend/README.md -------------------------------------------------------------------------------- /Backend/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | npm-debug.log 4 | .DS_Store 5 | .env 6 | -------------------------------------------------------------------------------- /Frontend/src/pages/auth/index.js: -------------------------------------------------------------------------------- 1 | import SignInPage from "./Sign-In/SignInPage"; 2 | 3 | export { SignInPage} 4 | -------------------------------------------------------------------------------- /Frontend/.env.local: -------------------------------------------------------------------------------- 1 | VITE_GEMENI_API_KEY=AIzaSyA8g7EEqOIdv5Q4qQLZNh7aUiF1GvIee1c 2 | VITE_APP_URL=http://localhost:5001/ -------------------------------------------------------------------------------- /Frontend/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /Frontend/src/assets/heroSnapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shauryaverma03/AI-Resume-Builder/HEAD/Frontend/src/assets/heroSnapshot.png -------------------------------------------------------------------------------- /Frontend/envTest.txt: -------------------------------------------------------------------------------- 1 | Rename This File to .env.local 2 | VITE_GEMENI_API_KEY={Create Your Own Gemeni API Key} 3 | VITE_APP_URL=http://localhost:5001/ -------------------------------------------------------------------------------- /Frontend/src/lib/utils.js: -------------------------------------------------------------------------------- 1 | import { clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /Backend/.env: -------------------------------------------------------------------------------- 1 | MONGODB_URI=mongodb://127.0.0.1:27017/ai-resume-builder 2 | PORT=5001 3 | JWT_SECRET_KEY=your-secret-key 4 | JWT_SECRET_EXPIRES_IN="1d" 5 | NODE_ENV=Dev 6 | ALLOWED_SITE=http://localhost:5173 -------------------------------------------------------------------------------- /Frontend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // ... 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": [ 7 | "./src/*" 8 | ] 9 | } 10 | // ... 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Frontend/src/pages/dashboard/edit-resume/components/preview-components/SummaryPreview.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function SummeryPreview({resumeInfo}) { 4 | return ( 5 |

6 | {resumeInfo?.summary} 7 |

8 | ) 9 | } 10 | 11 | export default SummeryPreview -------------------------------------------------------------------------------- /Backend/testEnv.txt: -------------------------------------------------------------------------------- 1 | Rename this file to .env 2 | 3 | MONGODB_URI={Create Your MongoDB URI And Use it You can use this if you are using Docker mongodb://localhost:27017/} 4 | PORT=5001 5 | JWT_SECRET_KEY={Some Random String for Authentication} 6 | JWT_SECRET_EXPIRES_IN="1d" 7 | NODE_ENV=Dev 8 | ALLOWED_SITE=http://localhost:5173 -------------------------------------------------------------------------------- /Frontend/vite.config.js: -------------------------------------------------------------------------------- 1 | import path from "path" 2 | import react from "@vitejs/plugin-react" 3 | import { defineConfig } from "vite" 4 | 5 | export default defineConfig({ 6 | plugins: [react()], 7 | resolve: { 8 | alias: { 9 | "@": path.resolve(__dirname, "./src"), 10 | }, 11 | }, 12 | }) 13 | -------------------------------------------------------------------------------- /Frontend/src/pages/auth/Sign-In/SignInPage.jsx: -------------------------------------------------------------------------------- 1 | import { SignIn } from '@clerk/clerk-react' 2 | import React from 'react' 3 | 4 | function SignInPage() { 5 | return ( 6 |
7 | 8 |
9 | ) 10 | } 11 | 12 | export default SignInPage -------------------------------------------------------------------------------- /Backend/src/index.js: -------------------------------------------------------------------------------- 1 | import app from "./app.js"; 2 | import { connectDB } from "./db/index.js"; 3 | import { config } from "dotenv"; 4 | config(); 5 | 6 | connectDB().then(() => { 7 | app.listen(process.env.PORT, () => { 8 | console.log("Server is running on http://localhost:" + process.env.PORT); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /Frontend/src/config/config.js: -------------------------------------------------------------------------------- 1 | const AUTH_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY; 2 | const API_KEY = import.meta.env.VITE_STRAPI_API_KEY; 3 | const GEMENI_API_KEY = import.meta.env.VITE_GEMENI_API_KEY; 4 | const VITE_APP_URL = import.meta.env.VITE_APP_URL; 5 | 6 | export { AUTH_KEY, API_KEY, GEMENI_API_KEY,VITE_APP_URL }; 7 | -------------------------------------------------------------------------------- /Backend/src/utils/ApiResponse.js: -------------------------------------------------------------------------------- 1 | class ApiResponse { 2 | constructor(statusCode, data, message = "Something Went wrong") { 3 | this.statusCode = statusCode; 4 | this.data = data; 5 | this.message = message; 6 | this.success = statusCode < 400; 7 | } 8 | } 9 | 10 | export { ApiResponse }; 11 | -------------------------------------------------------------------------------- /Backend/src/models/skill.model.js: -------------------------------------------------------------------------------- 1 | // models/Skill.js 2 | import mongoose from 'mongoose'; 3 | 4 | const { Schema } = mongoose; 5 | 6 | const skillSchema = new Schema({ 7 | name: { 8 | type: String 9 | }, 10 | rating: { 11 | type: Number 12 | } 13 | }, { _id: false }); 14 | 15 | export default skillSchema; 16 | -------------------------------------------------------------------------------- /Backend/src/models/project.model.js: -------------------------------------------------------------------------------- 1 | // models/Project.js 2 | import mongoose from 'mongoose'; 3 | 4 | const { Schema } = mongoose; 5 | 6 | const projectSchema = new Schema({ 7 | projectName: { 8 | type: String 9 | }, 10 | techStack: { 11 | type: [String] 12 | }, 13 | projectSummary: { 14 | type: String 15 | } 16 | }, { _id: false }); 17 | 18 | export default projectSchema; 19 | -------------------------------------------------------------------------------- /Frontend/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": false, 5 | "tsx": false, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /Frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | AI Resume Builder 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Frontend/README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /Frontend/src/features/user/userFeatures.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | const initialState = { 4 | userData: "", 5 | }; 6 | 7 | export const userSlice = createSlice({ 8 | name: "editUser", 9 | initialState, 10 | reducers: { 11 | addUserData: (state, action) => { 12 | state.userData = action.payload; 13 | }, 14 | }, 15 | }); 16 | 17 | export const { addUserData } = userSlice.actions; 18 | 19 | export default userSlice.reducer; 20 | -------------------------------------------------------------------------------- /Frontend/src/store/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from "@reduxjs/toolkit"; 2 | import resumeReducers from "../features/resume/resumeFeatures"; 3 | import userReducers from "../features/user/userFeatures"; 4 | 5 | export const resumeStore = configureStore({ 6 | reducer: { 7 | editResume: resumeReducers, 8 | editUser: userReducers, 9 | }, 10 | }); 11 | 12 | export const userStore = configureStore({ 13 | reducer: { 14 | editUser: userReducers, 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /Backend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the same Node.js version as your local machine 2 | FROM node:20-bullseye 3 | 4 | # Set working directory 5 | WORKDIR /app 6 | 7 | # Copy only package.json and package-lock.json first (for better caching) 8 | COPY package*.json ./ 9 | 10 | # Install dependencies 11 | RUN npm install 12 | 13 | # Now copy the rest of the application files 14 | COPY . . 15 | 16 | # Expose port 17 | EXPOSE 5001 18 | 19 | # Start the server 20 | CMD ["node", "src/index.js"] 21 | -------------------------------------------------------------------------------- /Backend/src/routes/user.routes.js: -------------------------------------------------------------------------------- 1 | import { 2 | start, 3 | loginUser, 4 | logoutUser, 5 | registerUser, 6 | } from "../controller/user.controller.js"; 7 | import { Router } from "express"; 8 | import { isUserAvailable } from "../middleware/auth.js"; 9 | 10 | const router = Router(); 11 | 12 | router.get("/", isUserAvailable, start); 13 | router.post("/register", registerUser); 14 | router.post("/login", loginUser); 15 | router.get("/logout", isUserAvailable, logoutUser); 16 | 17 | export default router; 18 | -------------------------------------------------------------------------------- /Backend/src/db/index.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | import { ApiError } from "../utils/ApiError.js"; 3 | 4 | const connectDB = async () => { 5 | try { 6 | const conn = await mongoose.connect(process.env.MONGODB_URI, { 7 | dbName: "ai_resume_builder", 8 | }); 9 | 10 | console.log(`MongoDB Connected: ${conn.connection.host}`); 11 | return conn; 12 | } catch (err) { 13 | throw new ApiError(500, "Database connection failed", [], err.stack); 14 | } 15 | }; 16 | 17 | export { connectDB }; 18 | -------------------------------------------------------------------------------- /Backend/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | backend: 5 | build: . 6 | container_name: ai-resume-builder-backend 7 | ports: 8 | - "5001:5001" 9 | env_file: 10 | - .env 11 | depends_on: 12 | - mongodb 13 | command: ["node", "src/index.js"] 14 | 15 | mongodb: 16 | image: mongo:latest 17 | container_name: ai-resume-builder-db 18 | ports: 19 | - "27017:27017" 20 | volumes: 21 | - mongo_data:/data/db 22 | 23 | volumes: 24 | mongo_data: 25 | -------------------------------------------------------------------------------- /Frontend/src/features/resume/resumeFeatures.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | const initialState = { 4 | resumeData:"" 5 | }; 6 | export const resumeSlice = createSlice({ 7 | name: "editResume", 8 | initialState, 9 | reducers: { 10 | addResumeData: (state, action) => { 11 | state.resumeData = action.payload; 12 | }, 13 | }, 14 | }); 15 | 16 | // Action creators are generated for each case reducer function 17 | export const { addResumeData } = resumeSlice.actions; 18 | 19 | export default resumeSlice.reducer; 20 | -------------------------------------------------------------------------------- /Backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "type": "module", 6 | "scripts": { 7 | "start": "node src/index.js", 8 | "dev": "nodemon src/index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "description": "", 14 | "dependencies": { 15 | "bcrypt": "^5.1.1", 16 | "cookie-parser": "^1.4.6", 17 | "cors": "^2.8.5", 18 | "dotenv": "^16.4.5", 19 | "express": "^4.19.2", 20 | "jsonwebtoken": "^9.0.2", 21 | "mongoose": "^8.5.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Frontend/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 13 | -------------------------------------------------------------------------------- /Backend/src/models/experience.model.js: -------------------------------------------------------------------------------- 1 | // models/Experience.js 2 | import mongoose from 'mongoose'; 3 | 4 | const { Schema } = mongoose; 5 | 6 | const experienceSchema = new Schema({ 7 | title: { 8 | type: String 9 | }, 10 | companyName: { 11 | type: String 12 | }, 13 | city: { 14 | type: String 15 | }, 16 | state: { 17 | type: String 18 | }, 19 | startDate: { 20 | type: Date 21 | }, 22 | endDate: { 23 | type: Date 24 | }, 25 | currentlyWorking: { 26 | type: Boolean 27 | }, 28 | workSummary: { 29 | type: String 30 | } 31 | }, { _id: false }); 32 | 33 | export default experienceSchema; 34 | -------------------------------------------------------------------------------- /Frontend/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /Backend/src/app.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import cookieParser from "cookie-parser"; 3 | import userRouter from "./routes/user.routes.js"; 4 | import resumeRouter from "./routes/resume.routes.js"; 5 | import cors from "cors"; 6 | import { config } from "dotenv"; 7 | config(); 8 | 9 | const app = express(); 10 | app.use(express.json()); 11 | app.use(express.urlencoded({ extended: true })); 12 | app.use(cookieParser()); 13 | 14 | 15 | const corsOptions = { 16 | origin: [process.env.ALLOWED_SITE], 17 | credentials: true 18 | }; 19 | 20 | app.use(cors(corsOptions)); 21 | 22 | app.use("/api/users", userRouter); 23 | app.use("/api/resumes", resumeRouter); 24 | 25 | export default app; 26 | -------------------------------------------------------------------------------- /Frontend/src/components/ui/textarea.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Textarea = React.forwardRef(({ className, ...props }, ref) => { 6 | return ( 7 | (