sarojit049/vaultofcode

β˜… 0Forks 0JavaScriptGitHub β†—Compare

README

VaultofCodes

A modern full-stack EdTech and SaaS platform built with the MERN stack, featuring an interactive company homepage, a complete About Us experience, and a dynamic Career Portal powered live by Google Sheets.


πŸ“Έ Screenshots

Homepage Hero

Homepage Hero

Programs Section

Programs

SaaS Products

SaaS Products

Statistics & Community

Statistics & Community

About Page

About Page

Career Portal

Career Portal

Career Details

Career Details

Search & Filter

Search Filter

Login

Login

Register

Register

Dashboard

Dashboard

Mobile β€” Homepage

Mobile Homepage

Mobile β€” Career Portal

Mobile Careers


πŸš€ Features

Homepage

  • Interactive animated hero with particle/star background
  • Animated CTA buttons (Explore Programs, Explore Software, View Careers)
  • Trust stats bar (50,000+ Learners, 100+ Programs, 10,000+ Projects, 50+ Workshops)
  • What We Do section with icon-driven service cards
  • Featured Programs section with animated program cards
  • Software / SaaS Ecosystem section showcasing VaultofCodes products
  • Why Us section with differentiator highlights
  • How It Works step-by-step guide
  • Community / Student testimonials section
  • Final CTA section
  • Responsive navigation with mobile hamburger menu & slide-in drawer

About Us

  • Company hero with gradient headline
  • Our Story narrative section
  • Mission & Vision cards
  • Team section with member cards
  • Company timeline
  • Final CTA linking to Careers

Career Portal

  • Dynamic job and internship listings fetched live from Google Sheets via Google Apps Script
  • Tab filtering: All Opportunities / Jobs / Internships
  • Real-time search across title, department, and skills (debounced)
  • Department, Work Mode, and Location dropdown filters
  • Combinable filters (e.g. Internship + Development + Remote)
  • Featured opportunity badges
  • Opportunity detail page (/careers/:id) with title, type, department, location, mode, experience, duration, skills, description, deadline, and direct Apply Now link
  • Apply Now uses the applyLink from Google Sheets (not hard-coded)
  • Active / Closed status handling (Closed opportunities hidden from listing)
  • Loading skeleton UI while fetching
  • Full error state with Retry button if API is unreachable
  • Empty state for no results or no search matches
  • Local sample data fallback for development only (controlled by ALLOW_CAREER_FALLBACK=true)

Authentication

  • User registration (/register) with full-name, email, password, confirm-password
  • User login (/login) with email and password
  • JWT-based authentication (7-day token)
  • Persistent session (token stored in localStorage, restored on page load via /api/auth/me)
  • Protected /dashboard route β€” redirects unauthenticated users to /login
  • Logout clears token and session state
  • Navbar shows "Hi, [First Name]" + Dashboard + Logout when authenticated
  • Dual mode: MongoDB Atlas when MONGO_URI is set, in-memory fallback for local development without a database

Backend

  • Express REST API (Node.js + Express 5)
  • MongoDB / Mongoose for user and contact data
  • Google Apps Script integration for Career Portal data
  • 60-second server-side in-memory cache on career data to respect Apps Script rate limits
  • Morgan HTTP request logging
  • Centralized error handling middleware
  • 404 not-found middleware
  • CORS configured for frontend origin

πŸ—οΈ Architecture

React Frontend (Vite + TailwindCSS v4)
            β”‚
            β”‚ fetch /api/*
            β–Ό
Express REST API (Node.js)
            β”‚
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”
   β–Ό                 β–Ό
MongoDB Atlas    Google Apps Script
(Users,            β”‚
 Contacts)         β–Ό
              Google Sheets
           (Career Listings)
Layer Purpose
React + Vite SPA frontend with page routing and UI
Express API REST endpoints, auth, proxy to Google Sheets
MongoDB Persists registered users and contact messages
Google Apps Script Serves Google Sheet career data as JSON
Google Sheets Single source of truth for career listings

πŸ“ Project Structure

vaultofcodes/
β”‚
β”œβ”€β”€ client/                         # React + Vite frontend
β”‚   β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ assets/
β”‚   β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”‚   β”œβ”€β”€ about/              # AboutHero, OurStory, MissionVision, Team, AboutTimeline
β”‚   β”‚   β”‚   β”œβ”€β”€ auth/               # ProtectedRoute
β”‚   β”‚   β”‚   β”œβ”€β”€ careers/            # CareerCard, CareerFilters
β”‚   β”‚   β”‚   β”œβ”€β”€ common/             # AnimatedCounter, Badge, Button, CareerSkeleton,
β”‚   β”‚   β”‚   β”‚                       # Container, EmptyState, ErrorState, FilterSelect,
β”‚   β”‚   β”‚   β”‚                       # GlassCard, SearchInput, SectionHeading, ScrollReveal…
β”‚   β”‚   β”‚   β”œβ”€β”€ home/               # Hero, HeroBackground, TrustStats, WhatWeDo,
β”‚   β”‚   β”‚   β”‚                       # Programs, SoftwareEcosystem, WhyUs, HowItWorks,
β”‚   β”‚   β”‚   β”‚                       # Community, FinalCTA
β”‚   β”‚   β”‚   └── layout/             # Navbar, MobileMenu, Footer
β”‚   β”‚   β”œβ”€β”€ context/
β”‚   β”‚   β”‚   └── AuthContext.jsx     # JWT auth state + session restore
β”‚   β”‚   β”œβ”€β”€ data/
β”‚   β”‚   β”‚   β”œβ”€β”€ programs.js         # Static program card data
β”‚   β”‚   β”‚   └── sampleCareers.js    # Dev-only fallback careers
β”‚   β”‚   β”œβ”€β”€ hooks/
β”‚   β”‚   β”‚   β”œβ”€β”€ useCareers.js       # Career data fetching hook
β”‚   β”‚   β”‚   β”œβ”€β”€ useDebounce.js      # Search debounce hook
β”‚   β”‚   β”‚   └── useSEO.js           # Document title/meta hook
β”‚   β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   β”‚   β”œβ”€β”€ Home.jsx
β”‚   β”‚   β”‚   β”œβ”€β”€ About.jsx
β”‚   β”‚   β”‚   β”œβ”€β”€ Careers.jsx
β”‚   β”‚   β”‚   β”œβ”€β”€ CareerDetails.jsx
β”‚   β”‚   β”‚   β”œβ”€β”€ Contact.jsx
β”‚   β”‚   β”‚   β”œβ”€β”€ Login.jsx
β”‚   β”‚   β”‚   β”œβ”€β”€ Register.jsx
β”‚   β”‚   β”‚   β”œβ”€β”€ Dashboard.jsx
β”‚   β”‚   β”‚   └── NotFound.jsx
β”‚   β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”‚   └── api.js              # Fetch wrapper + authAPI + careerAPI + contactAPI
β”‚   β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”‚   └── format.js           # Date formatting helpers
β”‚   β”‚   β”œβ”€β”€ App.jsx                 # Route definitions + AnimatePresence transitions
β”‚   β”‚   β”œβ”€β”€ main.jsx
β”‚   β”‚   └── index.css               # TailwindCSS v4 design tokens + utilities
β”‚   β”œβ”€β”€ .env.example
β”‚   β”œβ”€β”€ vite.config.js              # Dev proxy /api β†’ localhost:5001
β”‚   └── package.json
β”‚
β”œβ”€β”€ server/                         # Node.js + Express backend
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   └── db.js                   # MongoDB connection (graceful no-op without MONGO_URI)
β”‚   β”œβ”€β”€ controllers/
β”‚   β”‚   β”œβ”€β”€ authController.js       # Register + Login + GetMe (with in-memory fallback)
β”‚   β”‚   β”œβ”€β”€ careerController.js     # Career list + career detail (from Google Sheets)
β”‚   β”‚   └── contactController.js    # Contact message save
β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   β”œβ”€β”€ authMiddleware.js       # JWT Bearer token verification
β”‚   β”‚   β”œβ”€β”€ errorMiddleware.js      # Centralized error handler
β”‚   β”‚   └── notFound.js             # 404 handler
β”‚   β”œβ”€β”€ models/
β”‚   β”‚   └── User.js                 # Mongoose user schema (bcrypt password hashing)
β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”œβ”€β”€ authRoutes.js
β”‚   β”‚   β”œβ”€β”€ careerRoutes.js
β”‚   β”‚   └── contactRoutes.js
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   └── googleSheets.js         # Google Apps Script fetch + 60s cache + fallback logic
β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   └── fallbackCareers.js      # Dev-only sample career data for server side
β”‚   β”œβ”€β”€ server.js                   # App entry point
β”‚   β”œβ”€β”€ .env.example
β”‚   └── package.json
β”‚
β”œβ”€β”€ docs/
β”‚   └── screenshots/                # 13 QA output screenshots
β”‚
β”œβ”€β”€ package.json                    # Root scripts (dev, install:all, etc.)
β”œβ”€β”€ .gitignore
└── README.md

πŸ› οΈ Tech Stack

Frontend

Technology Version Purpose
React 19 UI framework
Vite 8 Build tool + dev server
Tailwind CSS 4 Utility-first CSS
Framer Motion 13 Animations & page transitions
React Router DOM 7 Client-side routing
Lucide React 1 Icon library

Backend

Technology Purpose
Node.js Runtime
Express 5 HTTP server + routing
Mongoose MongoDB ODM
bcryptjs Password hashing
jsonwebtoken JWT auth tokens
Morgan HTTP request logging
dotenv Environment variables
nodemon Dev hot-reload

Database & External

Service Purpose
MongoDB Atlas User accounts and contact messages
Google Sheets Single source of truth for career listings
Google Apps Script Exposes Google Sheet data as a JSON REST endpoint

βš™οΈ Installation & Setup

Prerequisites

  • Node.js 20+
  • npm 10+
  • MongoDB Atlas account (optional for local dev β€” in-memory fallback available)
  • Google Sheet + Apps Script URL (optional β€” sample fallback data available for local dev)

1. Clone the repository

git clone <repository-url>
cd vaultofcodes

2. Install all dependencies

npm run install:all

Or manually:

cd server && npm install
cd ../client && npm install

3. Configure environment variables

Backend β€” server/.env

PORT=5001
MONGO_URI=your_mongodb_atlas_connection_string
GOOGLE_APPS_SCRIPT_URL=your_google_apps_script_exec_url
JWT_SECRET=your_strong_jwt_secret_here
JWT_EXPIRES_IN=7d
CLIENT_URL=http://localhost:5173
ALLOW_CAREER_FALLBACK=true   # Set true for local dev without Google Sheets

Frontend β€” client/.env

VITE_API_URL=/api

The Vite dev server proxies /api to http://localhost:5001, so no full URL is needed in development.

4. Run the project

Run both together (from root):

npm run dev:server   # Terminal 1
npm run dev:client   # Terminal 2

Or use a single command (runs both in background):

npm run dev

πŸ”Œ API Endpoints

Health

Method Endpoint Description
GET /api/health API health check

Auth

Method Endpoint Description Body
POST /api/auth/register Create new account { name, email, password }
POST /api/auth/login Login { email, password }
GET /api/auth/me Get current user (protected) β€”

Response (register/login):

{
  "success": true,
  "user": { "id": "...", "name": "...", "email": "...", "role": "user" },
  "token": "eyJhbGci..."
}

Careers

Method Endpoint Description Query Params
GET /api/careers List active opportunities type, department, mode, search
GET /api/careers/:id Get single opportunity by ID β€”

Filtering Examples:

GET /api/careers?type=Internship
GET /api/careers?department=Development&mode=Remote
GET /api/careers?search=React

Response:

{
  "success": true,
  "data": [
    {
      "id": "1",
      "title": "Frontend Developer Intern",
      "type": "Internship",
      "department": "Development",
      "location": "Remote",
      "mode": "Remote",
      "experience": "0-1 years",
      "duration": "2 Months",
      "skills": ["React", "JavaScript", "CSS"],
      "description": "...",
      "deadline": "2026-09-30",
      "applyLink": "https://...",
      "status": "Active",
      "featured": true
    }
  ]
}

Contact

Method Endpoint Description Body
POST /api/contact Submit contact message { name, email, message }

πŸ“Š Google Sheets Setup

The Career Portal reads data live from a Google Sheet via a Google Apps Script web app.

1. Create the Google Sheet

Create a Google Sheet with the following columns (row 1 = headers):

Column Description
id Unique ID (e.g. voc-01)
title Job/internship title
type Job or Internship
department e.g. Development, Design, Marketing
location e.g. Remote, Bengaluru, IN
mode Remote, Hybrid, or On-site
experience e.g. 0-1 years, 1-3 years
duration e.g. Full-time, 2 Months
skills Comma-separated list: React, Node.js, MongoDB
description Full job/internship description
deadline ISO date: 2026-09-30
applyLink Application form URL
status Active or Closed
featured TRUE or FALSE
createdAt ISO date: 2026-07-01

2. Create the Apps Script

In your Google Sheet: Extensions β†’ Apps Script

Paste the following script:

function doGet() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const rows = sheet.getDataRange().getValues();
  const headers = rows[0];
  const data = rows.slice(1).map(row => {
    const obj = {};
    headers.forEach((h, i) => { obj[h] = row[i]; });
    return obj;
  });
  return ContentService
    .createTextOutput(JSON.stringify(data))
    .setMimeType(ContentService.MimeType.JSON);
}

3. Deploy as Web App

  1. Click Deploy β†’ New deployment
  2. Select type: Web app
  3. Execute as: Me
  4. Who has access: Anyone
  5. Click Deploy and copy the /exec URL

4. Add to environment

GOOGLE_APPS_SCRIPT_URL=https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec

5. Verify

Start the backend and open the careers page β€” listings should load from your sheet.

To test active/inactive handling: set status = Closed on any row and reload the page β€” that listing will disappear.


πŸ—„οΈ MongoDB Setup

Required only for persisting user registrations. Without MONGO_URI, auth uses in-memory storage (resets on server restart).

Setup with MongoDB Atlas

  1. Create a free account at cloud.mongodb.com
  2. Create a new cluster
  3. Create a database user (Database Access β†’ Add New Database User)
  4. Allow your IP or use 0.0.0.0/0 for development (Network Access)
  5. Click Connect β†’ Drivers and copy the connection string
  6. Replace <password> in the connection string with your database user password
  7. Add to server/.env:
MONGO_URI=mongodb+srv://<username>:<password>@cluster0.xxxxx.mongodb.net/vaultofcodes?retryWrites=true&w=majority

⚠️ Never commit MONGO_URI or database credentials to version control.


🌍 Deployment

Frontend β†’ Vercel

# From project root
cd client
npm run build   # Creates client/dist/

# Or connect the GitHub repo to Vercel and set:
# Root Directory: client
# Build Command: npm run build
# Output Directory: dist

Vercel Environment Variables:

VITE_API_URL=https://your-backend.render.com/api

Backend β†’ Render

  1. Create a new Web Service on render.com
  2. Set:
    • Root Directory: server
    • Build Command: npm install
    • Start Command: node server.js
  3. Add all environment variables from server/.env.example

Database β†’ MongoDB Atlas

Follow the setup steps above. Atlas provides free M0 clusters suitable for this project.

Google Sheets β†’ Google Apps Script

Already handled in the Google Sheets Setup section above. The Apps Script URL is environment-variable-driven, so no code changes are needed for deployment.


βœ… Assignment Requirements

Requirement Status Notes
Homepage βœ… Full responsive homepage
Interactive Hero βœ… Animated background + CTA buttons
Programs Section βœ… Featured program cards with hover effects
SaaS Ecosystem Section βœ… Software products with animated cards
Trust Statistics βœ… Animated counter stats bar
Community / Testimonials βœ… Student community section
About Us Page βœ… Hero, Story, Mission/Vision, Team, Timeline, CTA
Career Portal βœ… Full career listing page at /careers
Job Listings βœ… Jobs filter tab works correctly
Internship Listings βœ… Internships filter tab works correctly
Google Sheets Integration βœ… Live data via Google Apps Script
Active/Closed Status Handling βœ… Closed rows excluded from listing
Search βœ… Debounced search across title, department, skills
Department Filter βœ… Dropdown populated dynamically from data
Work Mode Filter βœ… Remote / Hybrid / On-site filter
Location Filter βœ… Location dropdown filter
Combined Filters βœ… All filters combinable simultaneously
Career Details Page βœ… /careers/:id with full opportunity details
Apply Links (from Sheets) βœ… applyLink from Google Sheet (not hard-coded)
Loading State βœ… Skeleton UI while fetching careers
Error State βœ… Error message + Retry button on API failure
Empty State βœ… "No opportunities" and "No matches" states
Responsive Design βœ… Desktop (1920/1440/1280), Tablet (768), Mobile (414/390/375)
MERN Backend βœ… Express + MongoDB + Mongoose
Authentication β€” Register βœ… /register with validation
Authentication β€” Login βœ… /login with JWT
Protected Dashboard βœ… /dashboard redirects if unauthenticated
Logout βœ… Clears JWT and session state
Contact API βœ… POST /api/contact endpoint

πŸ§ͺ Testing

All features were tested against the running application:

βœ“ Production build (vite build) β€” PASS
βœ“ Backend starts without errors
βœ“ Health check GET /api/health β€” 200 OK
βœ“ Homepage loads without console errors
βœ“ All homepage sections render correctly
βœ“ About page renders correctly
βœ“ Career listings load (Google Sheets / fallback)
βœ“ Search β€” "Developer", "React", "Python" all filter correctly
βœ“ Tab filter β€” Jobs / Internships
βœ“ Department filter
βœ“ Work mode filter
βœ“ Combinable filters
βœ“ Career detail page (/careers/:id) β€” full data shown
βœ“ Apply Now button uses applyLink from data source
βœ“ Loading skeleton displayed during fetch
βœ“ Error state renders with Retry button
βœ“ Empty state renders for no matches
βœ“ Register flow β€” account created, redirected to dashboard
βœ“ Login flow β€” JWT returned, session restored on reload
βœ“ Protected route β€” /dashboard redirects unauthenticated users to /login
βœ“ Logout β€” clears session, navbar reverts to Login
βœ“ Mobile layout β€” 390Γ—844 β€” no horizontal scroll, no clipped content
βœ“ No React key warnings
βœ“ No uncaught JavaScript errors

πŸ“ Responsive Support

Breakpoint Resolution Status
Desktop XL 1920 Γ— 1080 βœ…
Desktop L 1440 Γ— 900 βœ…
Desktop M 1280 Γ— 800 βœ…
Tablet 768 Γ— 1024 βœ…
Mobile L 414 Γ— 896 βœ…
Mobile M 390 Γ— 844 βœ…
Mobile S 375 Γ— 812 βœ…

🎨 Design System

The project uses a custom dark-mode design system defined in client/src/index.css:

Token Value Usage
--color-bg #050810 Page background
--color-surface #0d1220 Card/panel background
--color-border #1c2333 Dividers and borders
--color-electric #4f7dff Primary accent (blue)
--color-violet #8b5cf6 Secondary accent
--color-cyan #22d3ee Tertiary accent
--color-text-primary #f4f6fb Main text
--color-text-secondary #a6adc4 Subdued text

Animations: prefers-reduced-motion is respected globally β€” all animations are suppressed when the user has enabled reduced motion in their OS settings.


πŸ”’ Security Notes

  • Passwords are hashed with bcryptjs (10 salt rounds) before storage
  • JWT tokens are signed with a server-side secret (JWT_SECRET)
  • .env files are excluded from version control via .gitignore
  • CORS is configured to allow the frontend origin only
  • The protect middleware validates JWT on all protected routes
  • MONGO_URI and all credentials must be kept in environment variables β€” never committed

πŸ“ Notes

  • All company statistics (50,000+ learners, 100+ programs, etc.) are sample/dummy data used for demonstration purposes
  • Career listings are sample data from the connected Google Sheet (or local fallback in dev mode)
  • This project was developed as a website development assignment
  • The project demonstrates a complete MERN stack architecture with Google Sheets integration

πŸ”— Demo

Local development demo available using the setup instructions above.

Frontend runs at: http://localhost:5173
Backend API runs at: http://localhost:5001

Contributors

sarojit049

Issues