🚀 Online Job Portal – Project Overview
A platform where job seekers can create profiles, upload resumes, and apply for jobs, while employers/recruiters can post job listings, manage applications, and shortlist candidates.
Tech Stack
Frontend: Next.js (React-based framework), ShadCN (UI components), TailwindCSS (styling), Redux Toolkit (state management)
Backend & Database: Appwrite (auth, database, storage, serverless functions)
Hosting/Deployment: Vercel (frontend) + Appwrite Cloud/Self-hosted
For Job Seekers:
Signup/Login with Appwrite Auth
Create & update profile (resume, skills, experience)
Search & filter jobs (by role, location, salary, company)
Apply for jobs (store in Appwrite DB)
Track application status
For Employers:
Post new jobs (title, description, salary, requirements, location)
Manage job listings
View applicants & shortlist candidates
General Features:
Modern UI with ShadCN & Tailwind
State management with Redux Toolkit
Serverless functions for application workflows
Notifications (optional: email via Appwrite functions)
Role-based access (job seeker vs employer)
Key Integrations
Authentication: Appwrite (OAuth or email/password)
Database: Appwrite collections (Users, Jobs, Applications)
Storage: Appwrite file storage for resumes
UI: ShadCN components (cards, forms, modals, tables)
State: Redux Toolkit slices for user, jobs, applications
📌 Header Component
import React from "react"; import Link from "next/link"; import { Button } from "../ui/button"; import Navlinks from "./Navlinks"; import { RxHamburgerMenu } from "react-icons/rx"; import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar"; const Header = () => { return ( <header className="bg-[#2a1b3d] px-4 sm:px-10 py-3 sm:py-5 flex justify-between items-center"> {/* Logo */} <div className="logo"> <Link href={"/"}> <h1 className="text-xl sm:text-3xl font-semibold text-white"> Online Job Portal </h1> </Link> </div> {/* Navigation Links */} <Navlinks /> {/* Right Section */} <div className="flex items-center gap-4"> {/* Login / Signup Button */} <Button className="border-none bg-[#D83F87] hover:bg-[#f54698] text-white"> Sign Up </Button> {/* Example Avatar */} <Avatar className="cursor-pointer hidden"> <AvatarImage src="" alt="User" /> <AvatarFallback>U</AvatarFallback> </Avatar> {/* Hamburger Menu for Mobile */} <RxHamburgerMenu color="white" size={32} className="lg:hidden cursor-pointer" /> </div> </header> ); }; export default Header;
Hero Section Component
import React from "react";
const Herosection = () => {
  return (
    <section className="relative flex flex-col justify-center items-center w-full h-[450px] sm:h-[350px] p-5 md:p-10">
      {/* Background Image with Overlay */}
      <div className="absolute inset-0 -z-10">
        <img
          src="https://images.unsplash.com/photo-1516534775068-ba3e7458af70?w=1200&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8OHx8b25saW5lJTIwam9ifGVufDB8fDB8fHww"
          alt="Hero Background"
          className="w-full h-full object-cover"
        />
        <div className="absolute inset-0 bg-[#190572ad]" />
      </div>
      {/* Hero Content */}
      <div className="z-10 max-w-3xl text-center">
        <h1 className="text-white text-2xl md:text-3xl lg:text-4xl font-bold leading-snug">
          “Connecting Employers with Top Talent Globally.”
        </h1>
        <h2 className="text-white text-lg md:text-2xl lg:text-3xl mt-3 leading-snug">
          Join millions of job seekers finding new opportunities every day.
        </h2>
        {/* Searchbox Placeholder */}
        {/* <div className="my-5">
          <Searchbox />
        </div> */}
      </div>
      {/* Chatbot Floating Button */}
      <div className="fixed right-5 bottom-10 md:top-56 z-30 flex flex-col items-end">
        {/* Example chatbot icon (replace with your actual asset) */}
        <img
          src="./Reddit.png"
          alt="chatbot"
          className="w-12 h-12 cursor-pointer hover:scale-110 transition-transform"
        />
      </div>
    </section>
  );
};
export default Herosection;
Job Section Component
import React from "react";
import Jobcard from "./Jobcard";
import Link from "next/link";
const Jobsection = () => {
  return (
    <section className="bg-[#2E2835] w-full h-auto px-2 py-5 sm:p-10">
      <h1 className="text-xl sm:text-3xl uppercase font-semibold text-center text-white p-10">
        Recent Jobs
      </h1>
      <div className="job-container flex flex-wrap justify-center gap-5">
        {/* Example Job Cards (Replace with dynamic jobs later) */}
        <Link href="/jobs/frontend-developer_123">
          <Jobcard
            data={{
              title: "Frontend Developer",
              company: "Tech Corp",
              location: "Remote",
              description: "Work on modern web applications with React & Next.js.",
            }}
          />
        </Link>
        <Link href="/jobs/backend-developer_456">
          <Jobcard
            data={{
              title: "Backend Developer",
              company: "CodeWorks",
              location: "Kathmandu, Nepal",
              description: "Build scalable backend services with Node.js and Django.",
            }}
          />
        </Link>
        <Link href="/jobs/ui-ux-designer_789">
          <Jobcard
            data={{
              title: "UI/UX Designer",
              company: "Design Studio",
              location: "Hybrid",
              description: "Create intuitive designs and user experiences.",
            }}
          />
        </Link>
      </div>
    </section>
  );
};
export default Jobsection;
Searchbox Component
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
const Searchbox = () => {
  return (
    <div className="search flex flex-col sm:flex-row w-full max-w-4xl mx-auto border-2 border-white rounded-lg overflow-hidden">
      {/* Job Title Input */}
      <Input
        type="text"
        placeholder="Search your Job title"
        className="text-white text-lg border-none outline-none flex-1 bg-transparent placeholder:text-white px-4 py-3"
      />
      {/* Location Selector */}
      <Select>
        <SelectTrigger className="w-full sm:w-[250px] text-white text-lg border-none bg-pink-600 hover:bg-pink-700 transition-colors">
          <SelectValue placeholder="Select your location" />
        </SelectTrigger>
        <SelectContent className="text-lg">
          <SelectItem value="kathmandu">Kathmandu</SelectItem>
          <SelectItem value="pokhara">Pokhara</SelectItem>
          <SelectItem value="lalitpur">Lalitpur</SelectItem>
          <SelectItem value="bhaktapur">Bhaktapur</SelectItem>
          <SelectItem value="remote">Remote</SelectItem>
        </SelectContent>
      </Select>
      {/* Search Button */}
      <Button className="w-full sm:w-[200px] bg-[#D83F87] hover:bg-[#f54698] text-white text-lg font-medium transition-colors">
        Search
      </Button>
    </div>
  );
};
export default Searchbox;
Navigation Links Component
import React from "react";
import { Button } from "../ui/button";
import Link from "next/link";
const Navlinks = () => {
  const Linksbtn = [
    { name: "about", link: "/" },
    { name: "skill certification", link: "/" },
    { name: "find job", link: "/" },
    { name: "post job", link: "/" },
    { name: "contact us", link: "/" },
  ];
  return (
    <nav className="text-white flex flex-col lg:flex-row lg:items-center gap-5 lg:gap-8 bg-[#af8dff20] lg:bg-transparent backdrop-blur-md px-10 py-8 lg:p-0rounded-lg lg:rounded-none fixed lg:relative top-0 right-0 w-[250px] lg:w-auto h-full lg:h-auto z-50 lg:z-auto transition-all">
      {Linksbtn.map((data) => (
        <Link href={data.link} key={data.name}>
          <Button
            variant="link"
            className="text-white text-lg lg:text-base capitalize hover:text-pink-500 transition-colors"
          >
            {data.name}
          </Button>
        </Link>
      ))}
    </nav>
  );
};
export default Navlinks;
Footer Component
import React from "react";
import Link from "next/link";
import { FaFacebookF, FaTwitter, FaLinkedinIn } from "react-icons/fa";
const Footer = () => {
  return (
    <footer className="bg-[#2a1b3d] text-white py-10 px-6 mt-10">
      <div className="max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-8">
        {/* About */}
        <div>
          <h2 className="text-xl font-semibold mb-3">Online Job Portal</h2>
          <p className="text-sm text-gray-300">
            Helping job seekers and employers connect with ease.
          </p>
        </div>
        {/* Quick Links */}
        <div>
          <h2 className="text-lg font-semibold mb-3">Quick Links</h2>
          <ul className="space-y-2 text-sm">
            <li>
              <Link href="/" className="hover:text-pink-400">Home</Link>
            </li>
            <li>
              <Link href="/jobs" className="hover:text-pink-400">Find Jobs</Link>
            </li>
            <li>
              <Link href="/post-job" className="hover:text-pink-400">Post a Job</Link>
            </li>
            <li>
              <Link href="/contact" className="hover:text-pink-400">Contact Us</Link>
            </li>
          </ul>
        </div>
        {/* Social Media */}
        <div>
          <h2 className="text-lg font-semibold mb-3">Follow Us</h2>
          <div className="flex gap-4">
            <Link href="https://facebook.com" target="_blank" className="hover:text-pink-400">
              <FaFacebookF size={20} />
            </Link>
            <Link href="https://twitter.com" target="_blank" className="hover:text-pink-400">
              <FaTwitter size={20} />
            </Link>
            <Link href="https://linkedin.com" target="_blank" className="hover:text-pink-400">
              <FaLinkedinIn size={20} />
            </Link>
          </div>
        </div>
      </div>
      <div className="text-center text-gray-400 text-sm mt-8">
        © {new Date().getFullYear()} Online Job Portal. All rights reserved.
      </div>
    </footer>
  );
};
export default Footer;
Chatbot Component
import React, { useState } from "react";
import { BsChatDotsFill } from "react-icons/bs";
const Chatbot = () => {
  const [isOpen, setIsOpen] = useState(false);
  const [messages, setMessages] = useState<{ sender: string; text: string }[]>([]);
  const [input, setInput] = useState("");
  const toggleChat = () => setIsOpen(!isOpen);
  const handleSend = () => {
    if (input.trim() === "") return;
    setMessages([...messages, { sender: "user", text: input }]);
    setInput("");
    // Fake bot reply
    setTimeout(() => {
      setMessages((prev) => [...prev, { sender: "bot", text: "Hello! How can I help you today?" }]);
    }, 1000);
  };
  return (
    <div className="fixed bottom-6 right-6">
      {/* Chat Icon */}
      <button
        onClick={toggleChat}
        className="bg-[#D83F87] p-4 rounded-full shadow-lg text-white hover:bg-[#f54698] transition"
      >
        <BsChatDotsFill size={24} />
      </button>
      {/* Chat Window */}
      {isOpen && (
        <div className="bg-white w-80 h-96 shadow-xl rounded-xl flex flex-col mt-3">
          {/* Header */}
          <div className="bg-[#2a1b3d] text-white px-4 py-3 rounded-t-xl">
            <h3 className="font-semibold">Job Portal Assistant</h3>
          </div>
          {/* Messages */}
          <div className="flex-1 p-3 overflow-y-auto text-sm space-y-2">
            {messages.map((msg, i) => (
              <div
                key={i}
                className={`p-2 rounded-lg ${
                  msg.sender === "user"
                    ? "bg-[#D83F87] text-white self-end"
                    : "bg-gray-200 text-gray-800 self-start"
                }`}
              >
                {msg.text}
              </div>
            ))}
          </div>
          {/* Input */}
          <div className="p-3 border-t flex gap-2">
            <input
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && handleSend()}
              placeholder="Type a message..."
              className="flex-1 border rounded-lg px-3 py-2 text-sm focus:outline-none"
            />
            <button
              onClick={handleSend}
              className="bg-[#D83F87] hover:bg-[#f54698] text-white px-3 rounded-lg"
            >
              Send
            </button>
          </div>
        </div>
      )}
    </div>
  );
};
export default Chatbot;
Category Signup Component
import { GiCrossMark } from "react-icons/gi"; const Categorysignup = () => { return ( <div className="fixed inset-0 backdrop-blur-md z-50 flex justify-center items-center p-5"> {/* Form Container */} <div className="w-full sm:w-[500px] bg-[#af8dff65] p-5 sm:p-10 rounded-lg backdrop-blur-md relative"> {/* Close Button */} <GiCrossMark className="text-3xl text-white cursor-pointer hover:text-red-500 absolute right-4 top-4" /> <h2 className="text-center font-bold text-white text-3xl mb-5"> Select Signup Category </h2> {/* Jobseeker Option */} <div className="w-full sm:w-[80%] h-[100px] rounded-lg px-4 py-4 bg-white my-6 mx-auto flex items-center justify-center text-center text-xl text-pink-500 cursor-pointer hover:bg-pink-50 transition-colors"> <div> <p className="font-semibold">Jobseeker</p> <p className="text-sm mt-1">Create a free account to apply!</p> </div> </div> {/* Job Provider Option */} <div className="w-full sm:w-[80%] h-[100px] rounded-lg px-4 py-4 bg-white my-6 mx-auto flex items-center justify-center text-center text-xl text-pink-500 cursor-pointer hover:bg-pink-50 transition-colors"> <div> <p className="font-semibold">Job Provider</p> <p className="text-sm mt-1">Create a free account to post vacancies!</p> </div> </div> </div> </div> ); }; export default Categorysignup;import React from "react";
Login Form
import React, { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
const Login = () => {
  const [form, setForm] = useState({ email: "", password: "" });
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setForm({ ...form, [e.target.name]: e.target.value });
  };
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    console.log("Login Data:", form);
  };
  return (
    <div className="max-w-md mx-auto mt-16 bg-white shadow-lg rounded-xl p-6">
      <h2 className="text-2xl font-semibold mb-4 text-center text-gray-900">Welcome Back</h2>
      <form onSubmit={handleSubmit} className="space-y-4">
        <Input
          type="email"
          name="email"
          placeholder="Email Address"
          value={form.email}
          onChange={handleChange}
          required
        />
        <Input
          type="password"
          name="password"
          placeholder="Password"
          value={form.password}
          onChange={handleChange}
          required
        />
        <Button type="submit" className="w-full bg-[#D83F87] hover:bg-[#f54698] text-white">
          Login
        </Button>
      </form>
    </div>
  );
};
export default Login;

No comments:
If you have any doubts please let's me know