├── .env.example ├── .eslintrc.json ├── .gitignore ├── README.md ├── Untitled-1.sh ├── bun.lockb ├── components.json ├── convex ├── README.md ├── _generated │ ├── api.d.ts │ ├── api.js │ ├── dataModel.d.ts │ ├── server.d.ts │ ├── server.js │ └── server.ts ├── auth.config.ts ├── auth.ts ├── emails.tsx ├── http.ts ├── payments.ts ├── schema.ts ├── stripe.ts ├── subscriptions.ts ├── tsconfig.json └── users.ts ├── create-pages.sh ├── create_mock_interviews_structure.sh ├── generate-pages.sh ├── generate_pages.sh ├── generate_structure.sh ├── next.config.js ├── next.config.mjs ├── package-lock.json ├── package.json ├── performance.knowledge.md ├── postcss.config.mjs ├── public ├── avatar.png ├── coming-soon-clip.mp4 ├── hero-lottie.json ├── logo-stacks │ ├── convex.svg │ ├── framer-motion.svg │ ├── github.svg │ ├── next-js.svg │ ├── shadcn-ui.svg │ ├── stripe.svg │ ├── tailwindcss.svg │ └── typescript.svg ├── logo.png ├── logo.svg ├── premium-kit-logo.png ├── products │ └── questions.json ├── questions.json ├── seo │ ├── apple-touch-icon.png │ └── favicon.ico ├── starter-kit-logo.png ├── thankyou.png └── thumbnail.png ├── src ├── app │ ├── auth │ │ └── page.tsx │ ├── community │ │ ├── events │ │ │ └── page.tsx │ │ ├── forums │ │ │ └── page.tsx │ │ ├── hackathons │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── meetups │ │ │ └── page.tsx │ │ ├── mentorship │ │ │ └── page.tsx │ │ └── success-stories │ │ │ └── page.tsx │ ├── company │ │ ├── about │ │ │ └── page.tsx │ │ ├── careers │ │ │ └── page.tsx │ │ ├── contact │ │ │ └── page.tsx │ │ ├── investors │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── partners │ │ │ └── page.tsx │ │ └── press │ │ │ └── page.tsx │ ├── disclosure │ │ └── page.tsx │ ├── globals.css │ ├── layout.tsx │ ├── loading.tsx │ ├── not-found.tsx │ ├── page.tsx │ ├── privacy-policy │ │ └── page.tsx │ ├── products │ │ ├── Practice-Tests │ │ │ └── page.tsx │ │ ├── ai-feedback │ │ │ └── page.tsx │ │ ├── interview-questions │ │ │ ├── page.tsx │ │ │ └── questionsData.tsx │ │ ├── layout.tsx │ │ ├── mock-interviews │ │ │ ├── page.tsx │ │ │ ├── schedule │ │ │ │ └── page.tsx │ │ │ ├── tips │ │ │ │ └── page.tsx │ │ │ └── visual-simulation │ │ │ │ └── page.tsx │ │ ├── resume-builder │ │ │ ├── create │ │ │ │ └── page.tsx │ │ │ ├── examples │ │ │ │ └── page.tsx │ │ │ ├── hire-resume-writer │ │ │ │ └── page.tsx │ │ │ ├── page.tsx │ │ │ └── tips │ │ │ │ └── page.tsx │ │ └── skills-analyzer │ │ │ └── page.tsx │ ├── resources │ │ ├── blog │ │ │ └── page.tsx │ │ ├── ebooks │ │ │ └── page.tsx │ │ ├── faq │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── newsletters │ │ │ └── page.tsx │ │ ├── tutorials │ │ │ └── page.tsx │ │ └── webinars │ │ │ └── page.tsx │ ├── services │ │ ├── consultation │ │ │ └── page.tsx │ │ ├── cv-revision │ │ │ └── page.tsx │ │ ├── interview-coaching │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── mock-tests │ │ │ └── page.tsx │ │ ├── personal-branding │ │ │ └── page.tsx │ │ └── salary-negotiation │ │ │ └── page.tsx │ └── thankyou │ │ └── page.tsx ├── components │ ├── AmbassadorCard.tsx │ ├── BuyButton.tsx │ ├── ChipBanner.tsx │ ├── ErrorBoundary.tsx │ ├── Footer.tsx │ ├── Header.tsx │ ├── Logo.tsx │ ├── LottiePlayer.tsx │ ├── MaxWidthWrapper.tsx │ ├── MobileMenu.new.tsx │ ├── MobileMenu.tsx │ ├── NavLink.tsx │ ├── animation │ │ ├── AnimatedHeading.tsx │ │ ├── CanvasCover.tsx │ │ └── Sparkles.tsx │ ├── components.knowledge.md │ ├── email-templates │ │ ├── AfterPurchasedEmail.tsx │ │ └── WaitlistWelcomeEmail.tsx │ └── ui │ │ ├── alert.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── confetti.tsx │ │ ├── dropdown-menu.tsx │ │ ├── form.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── progress.tsx │ │ ├── select.tsx │ │ ├── separator.tsx │ │ ├── sonner.tsx │ │ ├── tabs.tsx │ │ └── textarea.tsx ├── data │ └── questions.json ├── features │ ├── README.md │ ├── auth │ │ ├── api │ │ │ └── useCurrentUser.tsx │ │ ├── components │ │ │ ├── AuthScreen.tsx │ │ │ ├── SignInCard.tsx │ │ │ ├── SignUpCard.tsx │ │ │ ├── UserButton.tsx │ │ │ └── UserButtonLoading.tsx │ │ └── lib │ │ │ └── types.ts │ ├── landing-page │ │ └── components │ │ │ ├── banner-stacks │ │ │ └── BannerStacks.tsx │ │ │ ├── cta │ │ │ └── CTA.tsx │ │ │ ├── faq │ │ │ └── FAQ.tsx │ │ │ ├── features │ │ │ ├── CardBentoIcon.tsx │ │ │ ├── CardBentoWrapper.tsx │ │ │ ├── CornerBlur.tsx │ │ │ ├── Features.tsx │ │ │ ├── Highlights.tsx │ │ │ ├── RectangularBento.tsx │ │ │ ├── SquareBento1.tsx │ │ │ ├── SquareBento2.tsx │ │ │ ├── TowerBento.tsx │ │ │ └── features.knowledge.md │ │ │ ├── hero │ │ │ ├── Hero.tsx │ │ │ ├── LeftHero.tsx │ │ │ └── RightHero.tsx │ │ │ ├── how-to-use │ │ │ └── HowToUse.tsx │ │ │ ├── pricing │ │ │ └── Pricing.tsx │ │ │ ├── testimonials │ │ │ └── Testimonials.tsx │ │ │ └── time-comparison-table │ │ │ └── TimeComparisonTable.tsx │ ├── schema │ │ └── githubAccess.schema.ts │ └── subscribe-for-waitlist │ │ ├── api │ │ └── useSubscribe.ts │ │ ├── forms │ │ └── SubscriptionForm.tsx │ │ └── lib │ │ └── subscription.schema.ts ├── lib │ ├── analytics │ │ ├── Analytics.tsx │ │ └── MicrosoftClarity.tsx │ ├── generateMetadata.tsx │ └── utils.ts ├── middleware.ts └── providers │ └── ConvexAuthProvider.tsx ├── structure.txt ├── tailwind.config.ts ├── testing.knowledge.md └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # General 2 | HOSTING_URL=https://interviewmasterai.vercel.app 3 | 4 | # Convex 5 | # Replace with actual values in your local setup or production environment 6 | CONVEX_DEPLOYMENT=dev:energetic-sheep-707 7 | NEXT_PUBLIC_CONVEX_URL=https://energetic-sheep-707.convex.cloud 8 | 9 | # Analytics 10 | GA_ID="" # Google Analytics ID 11 | MC_ID="" # Mailchimp ID 12 | 13 | # Stripe 14 | # Replace with your actual Stripe URL endpoint 15 | STRIPE_URL_ENDPOINT=https://energetic-sheep-707.convex.site/stripe 16 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals", "next/typescript"], 3 | "rules": { 4 | // You can disable specific rules you don't want to trigger errors during build 5 | "no-unused-vars": "off", // Disable 'no-unused-vars' rule 6 | "react/react-in-jsx-scope": "off", // Disable 'react/react-in-jsx-scope' rule for React 17+ 7 | "jsx-a11y/anchor-is-valid": "warn" // Example: Change rule level to warning instead of error 8 | }, 9 | "overrides": [ 10 | { 11 | "files": ["*.ts", "*.tsx"], 12 | "rules": { 13 | "@typescript-eslint/no-unused-vars": "off", // Disable TypeScript-specific unused-vars check 14 | "@typescript-eslint/explicit-module-boundary-types": "off" // Disable requiring return types in functions 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | .env.local 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Setup Guide 2 | 3 | Hi Chris here 👋 4 | 5 | In this guide, I will walk you through the process of setting up your Premium Kit, including installation, Convex backend configuration, authentication, and Stripe integration. 6 | 7 | You can also find this in the [website documentation](https://www.devvault.dev/docs). 8 | 9 | ## Table of Contents 10 | - [Installation Guide](https://www.devvault.dev/docs/installation) 11 | - [Convex Setup](https://www.devvault.dev/docs/getting-started/convex-setup) 12 | - [Authentication Setup](https://www.devvault.dev/docs/getting-started/authentication-setup) 13 | - [Stripe Setup](https://www.devvault.dev/docs/getting-started/stripe-setup) 14 | 15 | ## Installation Guide 16 | 17 | After purchasing the kit, you'll receive an email with instructions to clone the repository. Follow these steps to get started: 18 | 19 | ```bash 20 | # Clone the repository 21 | git clone 22 | 23 | # Navigate to the project directory 24 | cd 25 | 26 | # Remove the original remote 27 | git remote remove origin 28 | 29 | # Create and configure your own repository 30 | # Add your new remote origin 31 | 32 | # Install dependencies 33 | npm i 34 | 35 | # Set up environment variables 36 | mv .env.example .env.local 37 | ``` 38 | 39 | ## Convex Setup 40 | 41 | Learn how to set up your backend server using Convex. 42 | 43 | **Important**: Complete the installation process before proceeding. 44 | 45 | 1. Navigate to the project directory and run: 46 | ```bash 47 | npx convex dev 48 | ``` 49 | 50 | 2. When prompted, select: 51 | - Option 1: "Create A New Project" 52 | - Enter your app name 53 | 54 | That's it! Your backend is now deployed. 55 | 56 | ## Authentication Setup 57 | 58 | ### Setting up Convex Auth 59 | 60 | 1. Install required dependencies: 61 | ```bash 62 | npm install @convex-dev/auth @auth/core@0.36.0 63 | ``` 64 | 65 | 2. Run the initial setup: 66 | ```bash 67 | npx @convex-dev/auth 68 | ``` 69 | When prompted about the URL of the local web server, simply press Enter. 70 | 71 | ### Configuring Google OAuth 72 | 73 | 1. Visit the [Google Cloud Console](https://console.cloud.google.com/) 74 | 75 | 2. **OAuth Consent Screen Setup**: 76 | - Enter your app name 77 | - Add your email in "User support email" 78 | - (Optional) Add your logo 79 | - Under "Authorized Domains", add: `https://name-name-123.convex.site` 80 | - Add your email in "Developer contact information" 81 | - Complete the setup by clicking "Save and Continue" 82 | 83 | 3. **Credentials Setup**: 84 | - Click "Create Credentials" → "OAuth client ID" 85 | - Select "Web application" 86 | - Configure the following: 87 | - Authorized JavaScript Origins: `http://localhost:3000` 88 | - Authorized Redirect URLs: `https://name-name-123.convex.site/api/auth/callback/google` 89 | - Click "Create" 90 | 91 | 4. **Configure Convex Environment**: 92 | - In your Convex project settings: 93 | - Add `AUTH_GOOGLE_ID` environment variable with your Google Client ID 94 | - Add `AUTH_GOOGLE_SECRET` environment variable with your Google Client Secret 95 | 96 | ## Stripe Setup 97 | 98 | 1. **Configure Stripe Secret Key**: 99 | - Create an account on [Stripe Dashboard](https://dashboard.stripe.com) 100 | - Navigate to Developers → API Keys 101 | - Copy the Secret key 102 | - Add to Convex Environment Variables as `STRIPE_API_KEY` 103 | 104 | 2. **Configure Publishable Key**: 105 | - Copy the Publishable key from Stripe dashboard 106 | - Add to Convex Environment Variables as `STRIPE_KEY` 107 | 108 | 3. **Set up Webhooks**: 109 | - Run in your terminal: 110 | ```bash 111 | npm run stripe:listen 112 | ``` 113 | - Copy the webhook signing secret (`whsec_81...`) 114 | - Add to Convex Environment Variables as `STRIPE_WEBHOOKS_SECRET` 115 | 116 | 4. **Enable Stripe Functions**: 117 | - Uncomment the functions in the `/convex` folder: 118 | - `payments` 119 | - `stripe` 120 | - `users` 121 | 122 | --- 123 | 124 | For more detailed information about how to use the tools we just installed, visit the [official documentation](https://www.devvault.dev/docs).# devvault-kit 125 | -------------------------------------------------------------------------------- /Untitled-1.sh: -------------------------------------------------------------------------------- 1 | https://interviewmasterai.vercel.app 2 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/bun.lockb -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "neutral", 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 | } -------------------------------------------------------------------------------- /convex/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to your Convex functions directory! 2 | 3 | Write your Convex functions here. 4 | See https://docs.convex.dev/functions for more. 5 | 6 | A query function that takes two arguments looks like: 7 | 8 | ```ts 9 | // functions.js 10 | import { query } from "./_generated/server"; 11 | import { v } from "convex/values"; 12 | 13 | export const myQueryFunction = query({ 14 | // Validators for arguments. 15 | args: { 16 | first: v.number(), 17 | second: v.string(), 18 | }, 19 | 20 | // Function implementation. 21 | handler: async (ctx, args) => { 22 | // Read the database as many times as you need here. 23 | // See https://docs.convex.dev/database/reading-data. 24 | const documents = await ctx.db.query("tablename").collect(); 25 | 26 | // Arguments passed from the client are properties of the args object. 27 | console.log(args.first, args.second); 28 | 29 | // Write arbitrary JavaScript here: filter, aggregate, build derived data, 30 | // remove non-public properties, or create new objects. 31 | return documents; 32 | }, 33 | }); 34 | ``` 35 | 36 | Using this query function in a React component looks like: 37 | 38 | ```ts 39 | const data = useQuery(api.functions.myQueryFunction, { 40 | first: 10, 41 | second: "hello", 42 | }); 43 | ``` 44 | 45 | A mutation function looks like: 46 | 47 | ```ts 48 | // functions.js 49 | import { mutation } from "./_generated/server"; 50 | import { v } from "convex/values"; 51 | 52 | export const myMutationFunction = mutation({ 53 | // Validators for arguments. 54 | args: { 55 | first: v.string(), 56 | second: v.string(), 57 | }, 58 | 59 | // Function implementation. 60 | handler: async (ctx, args) => { 61 | // Insert or modify documents in the database here. 62 | // Mutations can also read from the database like queries. 63 | // See https://docs.convex.dev/database/writing-data. 64 | const message = { body: args.first, author: args.second }; 65 | const id = await ctx.db.insert("messages", message); 66 | 67 | // Optionally, return a value from your mutation. 68 | return await ctx.db.get(id); 69 | }, 70 | }); 71 | ``` 72 | 73 | Using this mutation function in a React component looks like: 74 | 75 | ```ts 76 | const mutation = useMutation(api.functions.myMutationFunction); 77 | function handleButtonPress() { 78 | // fire and forget, the most common way to use mutations 79 | mutation({ first: "Hello!", second: "me" }); 80 | // OR 81 | // use the result once the mutation has completed 82 | mutation({ first: "Hello!", second: "me" }).then((result) => 83 | console.log(result), 84 | ); 85 | } 86 | ``` 87 | 88 | Use the Convex CLI to push your functions to a deployment. See everything 89 | the Convex CLI can do by running `npx convex -h` in your project root 90 | directory. To learn more, launch the docs with `npx convex docs`. 91 | -------------------------------------------------------------------------------- /convex/_generated/api.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /** 3 | * Generated `api` utility. 4 | * 5 | * THIS CODE IS AUTOMATICALLY GENERATED. 6 | * 7 | * To regenerate, run `npx convex dev`. 8 | * @module 9 | */ 10 | 11 | import type { 12 | ApiFromModules, 13 | FilterApi, 14 | FunctionReference, 15 | } from "convex/server"; 16 | import type * as auth from "../auth.js"; 17 | import type * as emails from "../emails.js"; 18 | import type * as http from "../http.js"; 19 | import type * as payments from "../payments.js"; 20 | import type * as stripe from "../stripe.js"; 21 | import type * as subscriptions from "../subscriptions.js"; 22 | import type * as users from "../users.js"; 23 | 24 | /** 25 | * A utility for referencing Convex functions in your app's API. 26 | * 27 | * Usage: 28 | * ```js 29 | * const myFunctionReference = api.myModule.myFunction; 30 | * ``` 31 | */ 32 | declare const fullApi: ApiFromModules<{ 33 | auth: typeof auth; 34 | emails: typeof emails; 35 | http: typeof http; 36 | payments: typeof payments; 37 | stripe: typeof stripe; 38 | subscriptions: typeof subscriptions; 39 | users: typeof users; 40 | }>; 41 | export declare const api: FilterApi< 42 | typeof fullApi, 43 | FunctionReference 44 | >; 45 | export declare const internal: FilterApi< 46 | typeof fullApi, 47 | FunctionReference 48 | >; 49 | import { api } from "../convex/_generated/api"; 50 | 51 | // Using a public function 52 | const result = await convex.query(api.users.getUser, { userId: "123" }); 53 | 54 | // Using an internal function (only within Convex functions) 55 | await ctx.runAction(internal.emails.sendEmail, { to: "user@example.com" }); 56 | -------------------------------------------------------------------------------- /convex/_generated/api.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /** 3 | * Generated `api` utility. 4 | * 5 | * THIS CODE IS AUTOMATICALLY GENERATED. 6 | * 7 | * To regenerate, run `npx convex dev`. 8 | * @module 9 | */ 10 | 11 | import { anyApi } from "convex/server"; 12 | 13 | /** 14 | * A utility for referencing Convex functions in your app's API. 15 | * 16 | * Usage: 17 | * ```js 18 | * const myFunctionReference = api.myModule.myFunction; 19 | * ``` 20 | */ 21 | export const api = anyApi; 22 | export const internal = anyApi; 23 | -------------------------------------------------------------------------------- /convex/_generated/dataModel.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /** 3 | * Generated data model types. 4 | * 5 | * THIS CODE IS AUTOMATICALLY GENERATED. 6 | * 7 | * To regenerate, run `npx convex dev`. 8 | * @module 9 | */ 10 | 11 | import type { 12 | DataModelFromSchemaDefinition, 13 | DocumentByName, 14 | TableNamesInDataModel, 15 | SystemTableNames, 16 | } from "convex/server"; 17 | import type { GenericId } from "convex/values"; 18 | import schema from "../schema.js"; 19 | 20 | /** 21 | * The names of all of your Convex tables. 22 | */ 23 | export type TableNames = TableNamesInDataModel; 24 | 25 | /** 26 | * The type of a document stored in Convex. 27 | * 28 | * @typeParam TableName - A string literal type of the table name (like "users"). 29 | */ 30 | export type Doc = DocumentByName< 31 | DataModel, 32 | TableName 33 | >; 34 | 35 | /** 36 | * An identifier for a document in Convex. 37 | * 38 | * Convex documents are uniquely identified by their `Id`, which is accessible 39 | * on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/using/document-ids). 40 | * 41 | * Documents can be loaded using `db.get(id)` in query and mutation functions. 42 | * 43 | * IDs are just strings at runtime, but this type can be used to distinguish them from other 44 | * strings when type checking. 45 | * 46 | * @typeParam TableName - A string literal type of the table name (like "users"). 47 | */ 48 | export type Id = 49 | GenericId; 50 | 51 | /** 52 | * A type describing your Convex data model. 53 | * 54 | * This type includes information about what tables you have, the type of 55 | * documents stored in those tables, and the indexes defined on them. 56 | * 57 | * This type is used to parameterize methods like `queryGeneric` and 58 | * `mutationGeneric` to make them type-safe. 59 | */ 60 | export type DataModel = DataModelFromSchemaDefinition; 61 | -------------------------------------------------------------------------------- /convex/_generated/server.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /** 3 | * Generated utilities for implementing server-side Convex query and mutation functions. 4 | * 5 | * THIS CODE IS AUTOMATICALLY GENERATED. 6 | * 7 | * To regenerate, run `npx convex dev`. 8 | * @module 9 | */ 10 | 11 | import { 12 | actionGeneric, 13 | httpActionGeneric, 14 | queryGeneric, 15 | mutationGeneric, 16 | internalActionGeneric, 17 | internalMutationGeneric, 18 | internalQueryGeneric, 19 | } from "convex/server"; 20 | 21 | /** 22 | * Define a query in this Convex app's public API. 23 | * 24 | * This function will be allowed to read your Convex database and will be accessible from the client. 25 | * 26 | * @param func - The query function. It receives a {@link QueryCtx} as its first argument. 27 | * @returns The wrapped query. Include this as an `export` to name it and make it accessible. 28 | */ 29 | export const query = queryGeneric; 30 | 31 | /** 32 | * Define a query that is only accessible from other Convex functions (but not from the client). 33 | * 34 | * This function will be allowed to read from your Convex database. It will not be accessible from the client. 35 | * 36 | * @param func - The query function. It receives a {@link QueryCtx} as its first argument. 37 | * @returns The wrapped query. Include this as an `export` to name it and make it accessible. 38 | */ 39 | export const internalQuery = internalQueryGeneric; 40 | 41 | /** 42 | * Define a mutation in this Convex app's public API. 43 | * 44 | * This function will be allowed to modify your Convex database and will be accessible from the client. 45 | * 46 | * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. 47 | * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. 48 | */ 49 | export const mutation = mutationGeneric; 50 | 51 | /** 52 | * Define a mutation that is only accessible from other Convex functions (but not from the client). 53 | * 54 | * This function will be allowed to modify your Convex database. It will not be accessible from the client. 55 | * 56 | * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. 57 | * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. 58 | */ 59 | export const internalMutation = internalMutationGeneric; 60 | 61 | /** 62 | * Define an action in this Convex app's public API. 63 | * 64 | * An action is a function which can execute any JavaScript code, including non-deterministic 65 | * code and code with side-effects, like calling third-party services. 66 | * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. 67 | * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. 68 | * 69 | * @param func - The action. It receives an {@link ActionCtx} as its first argument. 70 | * @returns The wrapped action. Include this as an `export` to name it and make it accessible. 71 | */ 72 | export const action = actionGeneric; 73 | 74 | /** 75 | * Define an action that is only accessible from other Convex functions (but not from the client). 76 | * 77 | * @param func - The function. It receives an {@link ActionCtx} as its first argument. 78 | * @returns The wrapped function. Include this as an `export` to name it and make it accessible. 79 | */ 80 | export const internalAction = internalActionGeneric; 81 | 82 | /** 83 | * Define a Convex HTTP action. 84 | * 85 | * @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object 86 | * as its second. 87 | * @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`. 88 | */ 89 | export const httpAction = httpActionGeneric; 90 | -------------------------------------------------------------------------------- /convex/_generated/server.ts: -------------------------------------------------------------------------------- 1 | // This is a placeholder for the httpRouter export. 2 | // Replace this with the actual implementation or import as needed. 3 | 4 | import { 5 | httpActionGeneric, 6 | GenericActionCtx, 7 | GenericDataModel, 8 | internalActionGeneric 9 | } from "convex/server"; 10 | 11 | export const httpRouter = (func: (ctx: GenericActionCtx, req: Request) => Promise) => { 12 | // Implement the logic for handling HTTP routes 13 | return httpActionGeneric(func); 14 | }; 15 | 16 | export const internalAction = internalActionGeneric; 17 | -------------------------------------------------------------------------------- /convex/auth.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | providers: [ 3 | { 4 | domain: process.env.CONVEX_SITE_URL, 5 | applicationID: "convex", 6 | }, 7 | ], 8 | }; 9 | -------------------------------------------------------------------------------- /convex/auth.ts: -------------------------------------------------------------------------------- 1 | import GitHub from "@auth/core/providers/github"; 2 | import Google from "@auth/core/providers/google"; 3 | import { DataModel } from "./_generated/dataModel"; 4 | import { convexAuth } from "@convex-dev/auth/server"; 5 | import { Password } from "@convex-dev/auth/providers/Password"; 6 | 7 | /** 8 | * Custom Password Authentication Configuration 9 | * Extends the base Password provider with custom profile fields 10 | * 11 | * @param params - Authentication parameters including email and name 12 | * @returns User profile object with default values 13 | */ 14 | const CustomPassword = Password({ 15 | profile(params) { 16 | return { 17 | email: params.email as string, 18 | name: params.name as string, 19 | selectedTemplate: "", // Template selection for starter kit 20 | hasPurchasedPremium: false, // Premium kit purchase status 21 | hasPurchasedStarter: false, // Starter kit purchase status 22 | } 23 | } 24 | }) 25 | 26 | /** 27 | * Authentication Configuration 28 | * Supports multiple authentication providers: 29 | * - GitHub OAuth 30 | * - Google OAuth 31 | * - Custom Password Authentication 32 | * 33 | * For additional providers, see: https://labs.convex.dev/auth-example 34 | */ 35 | export const { auth, signIn, signOut, store } = convexAuth({ 36 | providers: [GitHub, Google, CustomPassword], 37 | }); -------------------------------------------------------------------------------- /convex/emails.tsx: -------------------------------------------------------------------------------- 1 | import { Resend } from "resend"; 2 | import { v } from "convex/values"; 3 | import { internalAction } from "./_generated/server"; 4 | import { AfterPurchasedEmail } from '../src/components/email-templates/AfterPurchasedEmail'; 5 | import { WaitlistWelcomeEmail } from "../src/components/email-templates/WaitlistWelcomeEmail"; 6 | 7 | // TODO: Uncomment this after you have grab your Resend API key 8 | 9 | // const resend = new Resend(process.env.RESEND_API!); 10 | // const url = process.env.BASE_URL! 11 | 12 | 13 | // export const sendEmail = internalAction({ 14 | // args: { email: v.string() }, 15 | // handler: async (_, { email }) => { 16 | 17 | // // TODO: This email template will be used when a user subscribes to your waitlist 18 | // const { data, error } = await resend.emails.send({ 19 | // from: 'DevVault Crew ', // [Company Name] 20 | // to: [email], 21 | // subject: 'Welcome to the DevVault Crew! 🚀', 22 | // react: , // Use the rendered HTML content 23 | // }); 24 | 25 | // if (error) { 26 | // throw new Error(error.message); 27 | // } 28 | 29 | // return data; 30 | // } 31 | // }); 32 | 33 | // export const sendEmailAfterPurchase = internalAction({ 34 | // args: { 35 | // email: v.string(), 36 | // stripeId: v.string(), 37 | // totalPrice: v.number(), 38 | // dateOfPurchased: v.string(), 39 | // kit: v.union(v.literal("Starter Kit"), v.literal("Premium Kit")) 40 | // }, 41 | // handler: async (_, { 42 | // kit, 43 | // email, 44 | // stripeId, 45 | // totalPrice, 46 | // dateOfPurchased 47 | // }) => { 48 | 49 | // // TODO: This email template will be used when a user purchased your product 50 | // const { data, error } = await resend.emails.send({ 51 | // from: 'DevVault Crew ', 52 | // to: [email], 53 | // subject: 'Thank you for your purchase! 🚀', 54 | // react: , 61 | // }); 62 | 63 | // if (error) { 64 | // throw new Error(error.message); 65 | // } 66 | 67 | // return data; 68 | // } 69 | // }) -------------------------------------------------------------------------------- /convex/http.ts: -------------------------------------------------------------------------------- 1 | import { httpRouter } from "./_generated/server"; 2 | import { internal } from "./_generated/api"; 3 | 4 | const http = httpRouter(); 5 | 6 | http.route({ 7 | path: "/stripe", 8 | method: "POST", 9 | handler: async (ctx, request) => { 10 | const signature = request.headers.get("stripe-signature") as string; 11 | const res = await ctx.runAction(internal.stripe.fulfill, { 12 | signature, 13 | payload: await request.text() 14 | }); 15 | if (res.success) { 16 | return new Response(null, { 17 | status: 200, 18 | }) 19 | } else { 20 | return new Response("Webhook Error", { 21 | status: 400 22 | }) 23 | } 24 | } 25 | }); 26 | 27 | export default http; 28 | 29 | -------------------------------------------------------------------------------- /convex/payments.ts: -------------------------------------------------------------------------------- 1 | import { v } from "convex/values"; 2 | import { PRODUCT_TYPE } from "./schema"; 3 | import { internalMutation } from "./_generated/server"; 4 | 5 | // You can customize it based on your needs 6 | export const createPayment = internalMutation({ 7 | args: { 8 | amount: v.number(), 9 | userId: v.id("users"), 10 | productType: PRODUCT_TYPE, 11 | stripePaymentStatus: v.string(), 12 | stripePaymentIntentId: v.string(), 13 | }, 14 | handler: async (ctx, { 15 | amount, 16 | userId, 17 | productType, 18 | stripePaymentStatus, 19 | stripePaymentIntentId 20 | }) => { 21 | // TODO: If you decided to change this make sure to replace your schema 22 | await ctx.db.insert("payments", { 23 | amount, 24 | userId, 25 | productType, 26 | stripePaymentStatus, 27 | stripePaymentIntentId 28 | }); 29 | } 30 | }) -------------------------------------------------------------------------------- /convex/schema.ts: -------------------------------------------------------------------------------- 1 | import { v } from "convex/values"; 2 | import { authTables } from "@convex-dev/auth/server"; 3 | import { defineSchema, defineTable } from "convex/server"; 4 | 5 | export const PRODUCT_TYPE = v.union(v.literal("Starter Kit"), v.literal("Premium Kit")); 6 | 7 | const schema = defineSchema({ 8 | ...authTables, 9 | users: defineTable({ 10 | name: v.optional(v.string()), 11 | image: v.optional(v.string()), 12 | email: v.optional(v.string()), 13 | phone: v.optional(v.string()), 14 | isAnonymous: v.optional(v.boolean()), 15 | selectedTemplate: v.optional(v.string()), 16 | hasPurchasedPremium: v.optional(v.boolean()), 17 | hasPurchasedStarter: v.optional(v.boolean()), 18 | emailVerificationTime: v.optional(v.number()), 19 | phoneVerificationTime: v.optional(v.number()), 20 | }).index("email", ["email"]), 21 | 22 | payments: defineTable({ 23 | amount: v.number(), 24 | userId: v.id("users"), 25 | productType: PRODUCT_TYPE, 26 | stripePaymentStatus: v.string(), 27 | stripePaymentIntentId: v.string(), 28 | }).index("userId", ["userId"]), 29 | 30 | subscriptions: defineTable({ 31 | email: v.string() 32 | }) 33 | }); 34 | 35 | 36 | 37 | export default schema; -------------------------------------------------------------------------------- /convex/subscriptions.ts: -------------------------------------------------------------------------------- 1 | import { v } from "convex/values"; 2 | import { mutation } from "./_generated/server"; 3 | import { internal } from "./_generated/api"; 4 | 5 | // TODO: Uncomment this when you have activated your Resend account and grab your API key 6 | 7 | // // This is for susbscribing your users to waitlist or can be used for newsletter too 8 | // export const subscribe = mutation({ 9 | // args: { email: v.string() }, 10 | // handler: async (ctx, { email }) => { 11 | // if (!email) { 12 | // throw new Error("Please enter an email"); 13 | // }; 14 | 15 | // if (!email.includes("@")) { 16 | // throw new Error("Invalid email"); 17 | // } 18 | 19 | // // Collect all emails 20 | // const emails = await ctx.db.query("subscriptions").collect(); 21 | 22 | // // Check if email entered is already existed 23 | // const existingEmail = emails.find((e) => e.email === email) 24 | 25 | // // Return the existing email without duplicating the exisitng email 26 | // if (existingEmail) { 27 | // return { 28 | // message: "Already subscribed", 29 | // id: existingEmail._id 30 | // } 31 | // } 32 | 33 | // const id = await ctx.db.insert("subscriptions", { email }); 34 | // if (id) { 35 | // await ctx.scheduler.runAfter(5, internal.emails.sendEmail, { 36 | // email 37 | // }); 38 | // } 39 | 40 | 41 | // return { 42 | // message: "Subscribed successfully", 43 | // id: id 44 | // }; 45 | // } 46 | // }) -------------------------------------------------------------------------------- /convex/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | /* This TypeScript project config describes the environment that 3 | * Convex functions run in and is used to typecheck them. 4 | * You can modify it, but some settings required to use Convex. 5 | */ 6 | "compilerOptions": { 7 | /* These settings are not required by Convex and can be modified. */ 8 | "allowJs": true, 9 | "strict": true, 10 | "moduleResolution": "Bundler", 11 | "jsx": "react-jsx", 12 | "skipLibCheck": true, 13 | "allowSyntheticDefaultImports": true, 14 | 15 | /* These compiler options are required by Convex */ 16 | "target": "ESNext", 17 | "lib": ["ES2021", "dom"], 18 | "forceConsistentCasingInFileNames": true, 19 | "module": "ESNext", 20 | "isolatedModules": true, 21 | "noEmit": true 22 | }, 23 | "include": ["./**/*"], 24 | "exclude": ["./_generated"] 25 | } -------------------------------------------------------------------------------- /convex/users.ts: -------------------------------------------------------------------------------- 1 | import { v } from "convex/values"; 2 | import { PRODUCT_TYPE } from "./schema"; 3 | import { getAuthUserId } from "@convex-dev/auth/server"; 4 | import { internalMutation, query } from "./_generated/server"; 5 | 6 | /** 7 | * Query current authenticated user's data 8 | * 9 | * @returns User object if authenticated, null otherwise 10 | * @example 11 | * ```ts 12 | * const user = await ctx.db.query(api.users.currentUser); 13 | * if (!user) { 14 | * // Handle unauthenticated state 15 | * } 16 | * ``` 17 | */ 18 | export const currentUser = query({ 19 | handler: async (ctx, _args) => { 20 | const userId = await getAuthUserId(ctx); 21 | if (userId === null) return null; 22 | return await ctx.db.get(userId) 23 | } 24 | }); 25 | 26 | /** 27 | * Update user details after successful purchase 28 | * Internal mutation called by stripe webhook handler 29 | * 30 | * @param userId - User's ID 31 | * @param productType - Type of product purchased (Premium/Starter Kit) 32 | * @param selectedTemplate - Optional template selection for Starter Kit 33 | * 34 | * @returns Updated user ID 35 | */ 36 | export const updateUserAfterPurchase = internalMutation({ 37 | args: { 38 | userId: v.id("users"), 39 | productType: PRODUCT_TYPE, 40 | selectedTemplate: v.optional(v.string()), 41 | }, 42 | handler: async (ctx, { 43 | userId, 44 | productType, 45 | selectedTemplate, 46 | }) => { 47 | const updates: any = {}; 48 | if (productType === "Premium Kit") { 49 | updates.hasPurchasedPremium = true; 50 | } else if (productType === "Starter Kit") { 51 | updates.hasPurchasedStarter = true; 52 | if (selectedTemplate) { 53 | updates.selectedTemplate = selectedTemplate; 54 | } 55 | }; 56 | 57 | await ctx.db.patch(userId, updates) 58 | return userId; 59 | } 60 | }) -------------------------------------------------------------------------------- /create-pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Base directory for pages 4 | BASE_DIR="D:/my programs/devvault-kit/src/pages" 5 | 6 | # Function to create a file with default content 7 | create_file() { 8 | local file_path="$1" 9 | local content="$2" 10 | mkdir -p "$(dirname "$file_path")" # Create the directory if it doesn't exist 11 | echo "$content" > "$file_path" # Write the content to the file 12 | } 13 | 14 | # Default content for all pages 15 | DEFAULT_CONTENT="import React from 'react'; 16 | 17 | const Page = () => { 18 | return ( 19 |
20 |

This is the page

21 |
22 | ); 23 | }; 24 | 25 | export default Page; 26 | " 27 | 28 | # Array of folder-file mappings 29 | declare -A files=( 30 | # Top-level pages 31 | ["$BASE_DIR/index.tsx"]="$DEFAULT_CONTENT" 32 | 33 | # About section 34 | ["$BASE_DIR/about/index.tsx"]="$DEFAULT_CONTENT" 35 | 36 | # Blog section 37 | ["$BASE_DIR/blog/index.tsx"]="$DEFAULT_CONTENT" 38 | 39 | # Careers section 40 | ["$BASE_DIR/careers/index.tsx"]="$DEFAULT_CONTENT" 41 | 42 | # Community section 43 | ["$BASE_DIR/community/forums.tsx"]="$DEFAULT_CONTENT" 44 | ["$BASE_DIR/community/events.tsx"]="$DEFAULT_CONTENT" 45 | ["$BASE_DIR/community/mentorship.tsx"]="$DEFAULT_CONTENT" 46 | ["$BASE_DIR/community/success-stories.tsx"]="$DEFAULT_CONTENT" 47 | ["$BASE_DIR/community/meetups.tsx"]="$DEFAULT_CONTENT" 48 | ["$BASE_DIR/community/hackathons.tsx"]="$DEFAULT_CONTENT" 49 | 50 | # Consultation section 51 | ["$BASE_DIR/consultation/index.tsx"]="$DEFAULT_CONTENT" 52 | 53 | # Contact section 54 | ["$BASE_DIR/contact/index.tsx"]="$DEFAULT_CONTENT" 55 | 56 | # Ebooks section 57 | ["$BASE_DIR/ebooks/index.tsx"]="$DEFAULT_CONTENT" 58 | 59 | # FAQ section 60 | ["$BASE_DIR/faq/index.tsx"]="$DEFAULT_CONTENT" 61 | 62 | # Investors section 63 | ["$BASE_DIR/investors/index.tsx"]="$DEFAULT_CONTENT" 64 | 65 | # Products section 66 | ["$BASE_DIR/job-tracker/index.tsx"]="$DEFAULT_CONTENT" 67 | ["$BASE_DIR/mock-interviews/index.tsx"]="$DEFAULT_CONTENT" 68 | ["$BASE_DIR/portfolio-builder/index.tsx"]="$DEFAULT_CONTENT" 69 | ["$BASE_DIR/resume-builder/index.tsx"]="$DEFAULT_CONTENT" 70 | ["$BASE_DIR/skills-analyzer/index.tsx"]="$DEFAULT_CONTENT" 71 | 72 | # Salary Negotiation section 73 | ["$BASE_DIR/salary-negotiation/index.tsx"]="$DEFAULT_CONTENT" 74 | 75 | # Tutorials section 76 | ["$BASE_DIR/tutorials/index.tsx"]="$DEFAULT_CONTENT" 77 | 78 | # Webinars section 79 | ["$BASE_DIR/webinars/index.tsx"]="$DEFAULT_CONTENT" 80 | ) 81 | 82 | # Loop through the array and create files 83 | for file_path in "${!files[@]}"; do 84 | create_file "$file_path" "${files[$file_path]}" 85 | echo "Created $file_path" 86 | done 87 | 88 | echo "All files and directories created successfully!" 89 | -------------------------------------------------------------------------------- /create_mock_interviews_structure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Base directory where the mock-interviews folder should be created 4 | base_dir="src/app/products/mock-interviews" 5 | 6 | # Check if the base directory exists, if not, create it 7 | if [ ! -d "$base_dir" ]; then 8 | mkdir -p "$base_dir" 9 | echo "Created directory: $base_dir" 10 | else 11 | echo "Directory $base_dir already exists. Skipping creation." 12 | fi 13 | 14 | # Create components directory and files 15 | components_dir="$base_dir/components" 16 | if [ ! -d "$components_dir" ]; then 17 | mkdir -p "$components_dir" 18 | echo "Created directory: $components_dir" 19 | else 20 | echo "Directory $components_dir already exists. Skipping creation." 21 | fi 22 | 23 | declare -a component_files=("Header.tsx" "QuestionList.tsx" "SelectedQuestion.tsx" "LiveRecorder.tsx" "FeedbackSection.tsx" "Button.tsx" "ThemeProvider.tsx") 24 | 25 | for file in "${component_files[@]}"; do 26 | if [ ! -f "$components_dir/$file" ]; then 27 | touch "$components_dir/$file" 28 | echo "Created file: $components_dir/$file" 29 | else 30 | echo "File $components_dir/$file already exists. Skipping creation." 31 | fi 32 | done 33 | 34 | # Create data directory and files 35 | data_dir="$base_dir/data" 36 | if [ ! -d "$data_dir" ]; then 37 | mkdir -p "$data_dir" 38 | echo "Created directory: $data_dir" 39 | else 40 | echo "Directory $data_dir already exists. Skipping creation." 41 | fi 42 | 43 | declare -a data_files=("questions.json" "theme.json") 44 | 45 | for file in "${data_files[@]}"; do 46 | if [ ! -f "$data_dir/$file" ]; then 47 | touch "$data_dir/$file" 48 | echo "Created file: $data_dir/$file" 49 | else 50 | echo "File $data_dir/$file already exists. Skipping creation." 51 | fi 52 | done 53 | 54 | # Create styles directory and files 55 | styles_dir="$base_dir/styles" 56 | if [ ! -d "$styles_dir" ]; then 57 | mkdir -p "$styles_dir" 58 | echo "Created directory: $styles_dir" 59 | else 60 | echo "Directory $styles_dir already exists. Skipping creation." 61 | fi 62 | 63 | declare -a style_files=("globals.css" "interviewPage.module.css") 64 | 65 | for file in "${style_files[@]}"; do 66 | if [ ! -f "$styles_dir/$file" ]; then 67 | touch "$styles_dir/$file" 68 | echo "Created file: $styles_dir/$file" 69 | else 70 | echo "File $styles_dir/$file already exists. Skipping creation." 71 | fi 72 | done 73 | 74 | # Create the main page file 75 | if [ ! -f "$base_dir/page.tsx" ]; then 76 | touch "$base_dir/page.tsx" 77 | echo "Created file: $base_dir/page.tsx" 78 | else 79 | echo "File $base_dir/page.tsx already exists. Skipping creation." 80 | fi 81 | 82 | # Create MockInterviewDetails page file 83 | if [ ! -f "$base_dir/MockInterviewDetails.tsx" ]; then 84 | touch "$base_dir/MockInterviewDetails.tsx" 85 | echo "Created file: $base_dir/MockInterviewDetails.tsx" 86 | else 87 | echo "File $base_dir/MockInterviewDetails.tsx already exists. Skipping creation." 88 | fi 89 | 90 | # Create utils directory and files 91 | utils_dir="$base_dir/utils" 92 | if [ ! -d "$utils_dir" ]; then 93 | mkdir -p "$utils_dir" 94 | echo "Created directory: $utils_dir" 95 | else 96 | echo "Directory $utils_dir already exists. Skipping creation." 97 | fi 98 | 99 | declare -a utils_files=("formatFeedback.ts" "apiHandler.ts") 100 | 101 | for file in "${utils_files[@]}"; do 102 | if [ ! -f "$utils_dir/$file" ]; then 103 | touch "$utils_dir/$file" 104 | echo "Created file: $utils_dir/$file" 105 | else 106 | echo "File $utils_dir/$file already exists. Skipping creation." 107 | fi 108 | done 109 | 110 | # Create README.md file 111 | if [ ! -f "$base_dir/README.md" ]; then 112 | touch "$base_dir/README.md" 113 | echo "Created file: $base_dir/README.md" 114 | else 115 | echo "File $base_dir/README.md already exists. Skipping creation." 116 | fi 117 | 118 | echo "File structure generation complete!" 119 | -------------------------------------------------------------------------------- /generate-pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Define the base path where your pages folder exists 4 | BASE_PATH="C:/Users/humes/OneDrive/Documents/GitHub/interviewmaster.ai_next.js/src/app/pages" 5 | 6 | # Create the directories if they don't already exist 7 | mkdir -p "$BASE_PATH/products" "$BASE_PATH/services" "$BASE_PATH/company" "$BASE_PATH/community" "$BASE_PATH/resources" 8 | 9 | # Create .tsx files for each page under the respective directories 10 | 11 | # Products Pages 12 | touch "$BASE_PATH/products/resume-builder.tsx" 13 | touch "$BASE_PATH/products/interview-prep.tsx" 14 | touch "$BASE_PATH/products/ai-mock-interviews.tsx" 15 | touch "$BASE_PATH/products/skill-assessment.tsx" 16 | touch "$BASE_PATH/products/job-tracker.tsx" 17 | 18 | # Services Pages 19 | touch "$BASE_PATH/services/coaching.tsx" 20 | touch "$BASE_PATH/services/career-counselling.tsx" 21 | touch "$BASE_PATH/services/resume-review.tsx" 22 | touch "$BASE_PATH/services/mock-interviews.tsx" 23 | touch "$BASE_PATH/services/skill-workshops.tsx" 24 | 25 | # Company Pages 26 | touch "$BASE_PATH/company/about.tsx" 27 | touch "$BASE_PATH/company/careers.tsx" 28 | touch "$BASE_PATH/company/team.tsx" 29 | touch "$BASE_PATH/company/contact.tsx" 30 | touch "$BASE_PATH/company/press.tsx" 31 | 32 | # Community Pages 33 | touch "$BASE_PATH/community/forums.tsx" 34 | touch "$BASE_PATH/community/events.tsx" 35 | touch "$BASE_PATH/community/success-stories.tsx" 36 | touch "$BASE_PATH/community/volunteer.tsx" 37 | touch "$BASE_PATH/community/ambassadors.tsx" 38 | 39 | # Resources Pages 40 | touch "$BASE_PATH/resources/docs.tsx" 41 | touch "$BASE_PATH/resources/blog.tsx" 42 | touch "$BASE_PATH/resources/faqs.tsx" 43 | touch "$BASE_PATH/resources/case-studies.tsx" 44 | touch "$BASE_PATH/resources/help-center.tsx" 45 | 46 | # Add a basic template to each .tsx file 47 | for file in "$BASE_PATH"/*/*/*.tsx; do 48 | echo "import React from 'react';" > "$file" 49 | echo "" >> "$file" 50 | echo "const $(basename "$file" .tsx) = () => {" >> "$file" 51 | echo " return (" >> "$file" 52 | echo "
" >> "$file" 53 | echo "

$(basename "$file" .tsx)

" >> "$file" 54 | echo "

Welcome to the $(basename "$file" .tsx) page.

" >> "$file" 55 | echo "
" >> "$file" 56 | echo " );" >> "$file" 57 | echo "};" >> "$file" 58 | echo "" >> "$file" 59 | echo "export default $(basename "$file" .tsx);" >> "$file" 60 | done 61 | 62 | echo "File structure and template code generated successfully!" 63 | -------------------------------------------------------------------------------- /generate_pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Define the base directory (adjust as necessary) 4 | BASE_DIR="./src/pages" 5 | 6 | # Create an associative array to map titles to their corresponding links 7 | declare -A NAVIGATION_MENUS=( 8 | ["Products"]="/resume-builder /mock-interviews /ai-feedback /skills-analyzer /job-tracker /portfolio-builder" 9 | ["Services"]="/consultation /cv-revision /mock-tests /interview-coaching /personal-branding /salary-negotiation" 10 | ["Resources"]="/blog /faq /ebooks /tutorials /webinars /newsletters" 11 | ["Community"]="/forums /events /mentorship /success-stories /meetups /hackathons" 12 | ["Company"]="/about /careers /partners /contact /press /investors" 13 | ) 14 | 15 | # Create files and folders based on the navigation structure 16 | echo "Creating files and folders inside $BASE_DIR..." 17 | 18 | for category in "${!NAVIGATION_MENUS[@]}"; do 19 | # Get the list of links for the current category 20 | links="${NAVIGATION_MENUS[$category]}" 21 | 22 | for link in $links; do 23 | # Convert the link to a directory path 24 | folder="$BASE_DIR${link}" 25 | 26 | # Create the directory if it doesn't exist 27 | mkdir -p "$folder" 28 | 29 | # Create the index.tsx file inside the directory 30 | file="$folder/index.tsx" 31 | 32 | # Add boilerplate content to the file 33 | cat > "$file" < { 37 | return ( 38 |
39 |

${link:1} Page

40 |

Welcome to the ${link:1} page.

41 |
42 | ); 43 | }; 44 | 45 | export default Page; 46 | EOF 47 | 48 | echo "Created $file" 49 | done 50 | done 51 | 52 | echo "All files and folders have been created successfully!" 53 | -------------------------------------------------------------------------------- /generate_structure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Base directory 4 | BASE_DIR="C:/Users/humes/OneDrive/Documents/GitHub/interviewmaster.ai_next.js/src/app" 5 | 6 | # Create directories and files 7 | mkdir -p "$BASE_DIR" && cd "$BASE_DIR" 8 | 9 | # Define an associative array of paths 10 | declare -A STRUCTURE=( 11 | # Root level 12 | ["layout.tsx"]="" 13 | ["page.tsx"]="" 14 | 15 | # Products 16 | ["products/layout.tsx"]="" 17 | ["products/page.tsx"]="" 18 | ["products/resume-builder/page.tsx"]="" 19 | ["products/interview-prep/page.tsx"]="" 20 | ["products/ai-mock-interviews/page.tsx"]="" 21 | ["products/skill-assessment/page.tsx"]="" 22 | ["products/job-tracker/page.tsx"]="" 23 | 24 | # Services 25 | ["services/layout.tsx"]="" 26 | ["services/page.tsx"]="" 27 | ["services/coaching/page.tsx"]="" 28 | ["services/career-counselling/page.tsx"]="" 29 | ["services/resume-review/page.tsx"]="" 30 | ["services/mock-interviews/page.tsx"]="" 31 | ["services/skill-workshops/page.tsx"]="" 32 | 33 | # Company 34 | ["company/layout.tsx"]="" 35 | ["company/page.tsx"]="" 36 | ["company/about/page.tsx"]="" 37 | ["company/careers/page.tsx"]="" 38 | ["company/team/page.tsx"]="" 39 | ["company/contact/page.tsx"]="" 40 | ["company/press/page.tsx"]="" 41 | 42 | # Community 43 | ["community/layout.tsx"]="" 44 | ["community/page.tsx"]="" 45 | ["community/forums/page.tsx"]="" 46 | ["community/events/page.tsx"]="" 47 | ["community/success-stories/page.tsx"]="" 48 | ["community/volunteer/page.tsx"]="" 49 | ["community/ambassadors/page.tsx"]="" 50 | 51 | # Resources 52 | ["resources/layout.tsx"]="" 53 | ["resources/page.tsx"]="" 54 | ["resources/docs/page.tsx"]="" 55 | ["resources/blog/page.tsx"]="" 56 | ["resources/faqs/page.tsx"]="" 57 | ["resources/case-studies/page.tsx"]="" 58 | ["resources/help-center/page.tsx"]="" 59 | ) 60 | 61 | # Create the directory structure and files 62 | for path in "${!STRUCTURE[@]}"; do 63 | mkdir -p "$(dirname "$path")" 64 | touch "$path" 65 | done 66 | 67 | echo "File structure generated successfully in $BASE_DIR" 68 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | module.exports = { 3 | reactStrictMode: true, // Enable strict mode for better development experience 4 | 5 | pageExtensions: ['tsx', 'ts', 'jsx', 'js'], // Ensure Next.js recognizes TypeScript and JSX files 6 | 7 | // Setup redirects 8 | async redirects() { 9 | return [ 10 | { 11 | source: '/old-route', // Old URL 12 | destination: '/new-route', // New URL 13 | permanent: true, // Permanent redirect 14 | }, 15 | ]; 16 | }, 17 | 18 | // Experimental settings with valid structure for Turbopack 19 | experimental: { 20 | turbo: { 21 | rules: { 22 | '*.mdx': ['mdx-loader'] 23 | }, 24 | }, 25 | }, 26 | 27 | 28 | eslint: { 29 | ignoreDuringBuilds: true, // Ensure ESLint warnings don't block the build 30 | }, 31 | 32 | env: { 33 | NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL, 34 | CONVEX_DEPLOYMENT: process.env.CONVEX_DEPLOYMENT, 35 | STRIPE_URL_ENDPOINT: process.env.STRIPE_URL_ENDPOINT, 36 | GA_ID: process.env.GA_ID, 37 | MC_ID: process.env.MC_ID, 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | env: { 4 | MC_ID: process.env.MC_ID, 5 | GA_ID: process.env.GA_ID, 6 | HOSTING_URL: process.env.HOSTING_URL, 7 | STRIPE_URL_ENDPOINT: process.env.STRIPE_URL_ENDPOINT 8 | } 9 | }; 10 | 11 | export default nextConfig; 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dev-vault", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev --turbo", 7 | "lint": "next lint", 8 | "build": "next build", 9 | "start": "next start", 10 | "stripe:trigger": "stripe trigger payment_intent.succeeded", 11 | "stripe:listen": "stripe listen --forward-to https://energetic-sheep-707.convex.site/stripe" 12 | }, 13 | "dependencies": { 14 | "@auth/core": "^0.36.0", 15 | "@convex-dev/auth": "^0.0.71", 16 | "@hookform/resolvers": "^3.9.0", 17 | "@lottiefiles/dotlottie-react": "^0.9.1", 18 | "@next/third-parties": "^14.2.15", 19 | "@radix-ui/react-avatar": "^1.1.1", 20 | "@radix-ui/react-dropdown-menu": "^2.1.2", 21 | "@radix-ui/react-label": "^2.1.0", 22 | "@radix-ui/react-separator": "^1.1.0", 23 | "@radix-ui/react-slot": "^1.1.0", 24 | "@react-email/components": "^0.0.25", 25 | "@react-pdf/renderer": "^4.1.5", 26 | "@stripe/react-stripe-js": "^2.8.1", 27 | "@stripe/stripe-js": "^4.8.0", 28 | "@tensorflow-models/face-landmarks-detection": "^1.0.6", 29 | "@tensorflow/tfjs": "^4.22.0", 30 | "@tsparticles/engine": "^3.5.0", 31 | "@tsparticles/react": "^3.0.0", 32 | "@tsparticles/slim": "^3.5.0", 33 | "@vercel/analytics": "^1.4.1", 34 | "@vercel/speed-insights": "^1.1.0", 35 | "axios": "^1.7.8", 36 | "bootstrap": "^5.3.3", 37 | "class-variance-authority": "^0.7.0", 38 | "clsx": "^2.1.1", 39 | "convex": "^1.16.4", 40 | "docx": "^9.1.0", 41 | "file-saver": "^2.0.5", 42 | "framer-motion": "^11.11.4", 43 | "jspdf": "^2.5.2", 44 | "lucide-react": "^0.447.0", 45 | "next": "14.1.0", 46 | "next-themes": "^0.3.0", 47 | "nextjs-toploader": "^3.7.15", 48 | "react": "^18.2.8", 49 | "react-bootstrap": "^2.10.6", 50 | "react-datepicker": "^7.5.0", 51 | "react-dom": "^18.2.8", 52 | "react-hook-form": "^7.53.0", 53 | "react-icons": "^5.3.0", 54 | "react-intersection-observer": "^9.13.1", 55 | "react-to-pdf": "^1.0.1", 56 | "react-to-print": "^3.0.2", 57 | "react-use-measure": "^2.1.1", 58 | "react-video-recorder": "^3.19.4", 59 | "resend": "^4.0.0", 60 | "sonner": "^1.5.0", 61 | "stripe": "^17.2.0", 62 | "tailwind-merge": "^2.5.3", 63 | "tailwindcss-animate": "^1.0.7", 64 | "zod": "^3.23.8" 65 | }, 66 | "devDependencies": { 67 | "@types/node": "^20", 68 | "@types/react": "^18", 69 | "@types/react-dom": "^18", 70 | "eslint": "^8", 71 | "eslint-config-next": "15.0.1", 72 | "postcss": "^8", 73 | "tailwindcss": "^3.4.1", 74 | "typescript": "^5" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /performance.knowledge.md: -------------------------------------------------------------------------------- 1 | # Performance Optimization Guidelines 2 | 3 | ## Build Performance 4 | - Use `swcMinify` in Next.js config for faster minification 5 | - Enable compiler optimizations in production 6 | - Optimize Tailwind content paths to reduce CSS compilation time 7 | - Use path aliases for imports to reduce resolution time 8 | 9 | ## Runtime Performance 10 | - Lazy load components that are not needed immediately 11 | - Use `React.memo` for components that receive the same props frequently 12 | - Implement proper code splitting using dynamic imports 13 | - Minimize JavaScript bundle size 14 | 15 | ## Common Issues 16 | - Long compilation times often caused by: 17 | - Large CSS files from unoptimized Tailwind usage 18 | - Unnecessary file scanning in content paths 19 | - Development mode React warnings and checks 20 | - Unoptimized image processing 21 | 22 | ## Best Practices 23 | - Keep dependencies up to date 24 | - Use production builds for deployment 25 | - Implement proper caching strategies 26 | - Monitor bundle sizes regularly 27 | -------------------------------------------------------------------------------- /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/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/avatar.png -------------------------------------------------------------------------------- /public/coming-soon-clip.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/coming-soon-clip.mp4 -------------------------------------------------------------------------------- /public/logo-stacks/convex.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /public/logo-stacks/framer-motion.svg: -------------------------------------------------------------------------------- 1 | 2 | Framer 3 | 4 | -------------------------------------------------------------------------------- /public/logo-stacks/github.svg: -------------------------------------------------------------------------------- 1 | GitHub -------------------------------------------------------------------------------- /public/logo-stacks/next-js.svg: -------------------------------------------------------------------------------- 1 | 2 | Next.js 3 | 5 | -------------------------------------------------------------------------------- /public/logo-stacks/shadcn-ui.svg: -------------------------------------------------------------------------------- 1 | 2 | shadcn/ui 3 | 5 | -------------------------------------------------------------------------------- /public/logo-stacks/stripe.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /public/logo-stacks/tailwindcss.svg: -------------------------------------------------------------------------------- 1 | 2 | Tailwind CSS 3 | 5 | -------------------------------------------------------------------------------- /public/logo-stacks/typescript.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/logo.png -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/premium-kit-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/premium-kit-logo.png -------------------------------------------------------------------------------- /public/questions.json: -------------------------------------------------------------------------------- 1 | { 2 | "questions": [ 3 | { "question": "Tell me about yourself." }, 4 | { "question": "Why do you want to work at this company?" }, 5 | { "question": "What are your strengths and weaknesses?" }, 6 | { "question": "Where do you see yourself in five years?" }, 7 | { "question": "Describe a difficult situation you faced and how you handled it." }, 8 | { "question": "Why did you leave your last job?" }, 9 | { "question": "What do you know about our company?" }, 10 | { "question": "How do you handle stress and pressure?" }, 11 | { "question": "What is your greatest achievement?" }, 12 | { "question": "Tell me about a time you worked in a team." }, 13 | { "question": "What are your long-term career goals?" }, 14 | { "question": "How do you prioritize your work?" }, 15 | { "question": "What motivates you?" }, 16 | { "question": "How do you deal with failure?" }, 17 | { "question": "Do you prefer working alone or in a team?" }, 18 | { "question": "What makes you unique?" }, 19 | { "question": "How do you handle feedback?" }, 20 | { "question": "Tell me about a time you showed leadership." }, 21 | { "question": "What would you do in the first 90 days of this role?" }, 22 | { "question": "Why should we hire you?" } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /public/seo/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/seo/apple-touch-icon.png -------------------------------------------------------------------------------- /public/seo/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/seo/favicon.ico -------------------------------------------------------------------------------- /public/starter-kit-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/starter-kit-logo.png -------------------------------------------------------------------------------- /public/thankyou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/thankyou.png -------------------------------------------------------------------------------- /public/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/achris-alonzo30/devvault-kit/20ca200cfd0af9617600dccdf82ab09757dc259e/public/thumbnail.png -------------------------------------------------------------------------------- /src/app/auth/page.tsx: -------------------------------------------------------------------------------- 1 | import { AuthScreen } from "@/features/auth/components/AuthScreen"; 2 | 3 | export default function AuthPage() { 4 | return 5 | } -------------------------------------------------------------------------------- /src/app/community/events/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { FaCalendarAlt, FaMapMarkerAlt, FaClock } from "react-icons/fa"; 4 | import Image from "next/image"; // Importing Image component from next/image 5 | 6 | const events = [ 7 | { 8 | id: 1, 9 | title: "Tech Innovators Meetup", 10 | date: "December 10, 2024", 11 | time: "3:00 PM - 6:00 PM", 12 | location: "Tech Park, New York", 13 | description: "Join industry leaders and innovators in a networking and idea-sharing event.", 14 | image: "/images/tech-meetup.jpg", 15 | }, 16 | { 17 | id: 2, 18 | title: "AI Hackathon 2025", 19 | date: "January 20, 2025", 20 | time: "9:00 AM - 9:00 PM", 21 | location: "Virtual", 22 | description: "Compete with the best minds in AI and machine learning to solve real-world challenges.", 23 | image: "/images/ai-hackathon.jpg", 24 | }, 25 | { 26 | id: 3, 27 | title: "Career Growth Workshop", 28 | date: "February 5, 2025", 29 | time: "11:00 AM - 4:00 PM", 30 | location: "Downtown Conference Center, San Francisco", 31 | description: "A workshop designed to help professionals plan and accelerate their career growth.", 32 | image: "/images/career-workshop.jpg", 33 | }, 34 | ]; 35 | 36 | export default function Events() { 37 | return ( 38 |
39 |

Upcoming Events

40 |

41 | Stay updated with the latest community events, workshops, and hackathons. 42 |

43 | 44 |
45 | {events.map((event) => ( 46 |
50 | {event.title} 57 |
58 |

{event.title}

59 |
60 | 61 | {event.date} 62 | 63 | {event.time} 64 |
65 |
66 | 67 | {event.location} 68 |
69 |

{event.description}

70 | 73 |
74 |
75 | ))} 76 |
77 |
78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /src/app/community/layout.tsx: -------------------------------------------------------------------------------- 1 | import "../globals.css"; 2 | import { cn } from "@/lib/utils"; 3 | import { Noto_Sans } from "next/font/google"; 4 | import { Analytics } from "@/lib/analytics/Analytics"; 5 | import { generateMetadata } from "@/lib/generateMetadata"; 6 | import { ConvexClientProvider } from "@/providers/ConvexAuthProvider"; 7 | import { ConvexAuthNextjsServerProvider } from "@convex-dev/auth/nextjs/server"; 8 | 9 | import NextTopLoader from "nextjs-toploader"; 10 | import { Header } from "@/components/Header"; 11 | import { Footer } from "@/components/Footer"; 12 | import { Toaster } from "@/components/ui/sonner"; 13 | 14 | const font = Noto_Sans({ weight: ["400", "700"], subsets: ["latin"] }); 15 | 16 | export const metadata = generateMetadata(); 17 | 18 | export default function CommunityLayout({ 19 | children, 20 | }: Readonly<{ children: React.ReactNode }>) { 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | {/* Header for Community Page */} 29 |
30 | {/* Main content for community section */} 31 |
32 | {children} 33 |
34 | {/* Footer for Community Page */} 35 |