Skip to content

christopher-tanaka-code/job-hub

Repository files navigation

Job Hub - Authentication System

A Next.js application with complete authentication flow using Supabase, including email verification and admin approval system.

Features

Email/Password Authentication - Secure user registration and login
Email Verification - Built-in Supabase email verification
Admin Approval System - Manual approval required for new users
Role-Based Access - Admin and User roles with different permissions
Protected Routes - Middleware-based route protection
Row Level Security - Database-level security policies
Modern UI - Clean, responsive design with dark mode support
TypeScript - Fully typed for better developer experience

Tech Stack

  • Framework: Next.js 16 (App Router)
  • Authentication: Supabase Auth
  • Database: Supabase PostgreSQL
  • Styling: Tailwind CSS 4.0
  • Language: TypeScript

Quick Start

1. Install Dependencies

npm install

2. Set Up Supabase

  1. Create a free account at supabase.com
  2. Create a new project
  3. Get your project URL and anon key from Settings > API

3. Configure Environment Variables

Create .env.local in the root directory:

NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

4. Set Up Database

Run the following SQL in your Supabase SQL Editor:

-- Create user_profiles table
CREATE TABLE user_profiles (
  user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
  email TEXT UNIQUE NOT NULL,
  is_approved BOOLEAN DEFAULT FALSE,
  is_admin BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Enable Row Level Security
ALTER TABLE user_profiles ENABLE ROW LEVEL SECURITY;

-- Allow users to read their own profile
CREATE POLICY "Users can read own profile"
ON user_profiles FOR SELECT
USING (auth.uid() = user_id);

-- Allow admins to read all profiles
CREATE POLICY "Admins can read all profiles"
ON user_profiles FOR SELECT
USING (
  EXISTS (
    SELECT 1 FROM user_profiles
    WHERE user_id = auth.uid() AND is_admin = TRUE
  )
);

-- Allow admins to update profiles
CREATE POLICY "Admins can update profiles"
ON user_profiles FOR UPDATE
USING (
  EXISTS (
    SELECT 1 FROM user_profiles
    WHERE user_id = auth.uid() AND is_admin = TRUE
  )
);

-- Create function to auto-create profile on signup
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO public.user_profiles (user_id, email)
  VALUES (NEW.id, NEW.email);
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Trigger to create profile on signup
CREATE TRIGGER on_auth_user_created
  AFTER INSERT ON auth.users
  FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();

-- Create himalayas_jobs table (optional - for job listings feature)
CREATE TABLE himalayas_jobs (
  guid TEXT PRIMARY KEY,
  title TEXT NOT NULL,
  company_name TEXT NOT NULL,
  company_logo TEXT,
  employment_type TEXT,
  min_salary NUMERIC,
  max_salary NUMERIC,
  currency TEXT,
  pub_date TIMESTAMP WITH TIME ZONE,
  expiry_date TIMESTAMP WITH TIME ZONE,
  application_link TEXT,
  job_url TEXT,
  excerpt TEXT,
  description_html TEXT,
  locations TEXT[],
  timezones INTEGER[],
  categories TEXT[],
  parent_categories TEXT[],
  seniority TEXT[],
  is_us BOOLEAN,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Enable RLS for jobs table
ALTER TABLE himalayas_jobs ENABLE ROW LEVEL SECURITY;

-- Allow all authenticated users to read jobs
CREATE POLICY "Authenticated users can read jobs"
ON himalayas_jobs FOR SELECT
TO authenticated
USING (TRUE);

5. Run Development Server

npm run dev

Visit http://localhost:3000

6. Create Your First Admin

  1. Sign up through the app
  2. Verify your email
  3. In Supabase SQL Editor, run:
UPDATE user_profiles
SET is_admin = TRUE, is_approved = TRUE
WHERE email = 'your-email@example.com';

Project Structure

job-hub/
├── app/
│   ├── sign-up/          # User registration page
│   ├── sign-in/          # User login page
│   ├── verify-email/     # Email verification status
│   ├── pending-approval/ # Admin approval waiting page
│   ├── dashboard/        # Main dashboard (authenticated users)
│   ├── admin/            # Admin panel (admins only)
│   └── auth/callback/    # OAuth callback handler
├── components/
│   ├── Dashboard.tsx     # Dashboard component
│   └── AdminDashboard.tsx # Admin dashboard component
├── lib/
│   ├── supabase/
│   │   ├── client.ts     # Client-side Supabase client
│   │   ├── server.ts     # Server-side Supabase client
│   │   └── middleware.ts # Supabase middleware utilities
│   └── types/
│       └── database.types.ts # Database type definitions
└── middleware.ts         # Next.js middleware for route protection

Authentication Flow

New User Registration

  1. User signs up with email/password → /sign-up
  2. Email verification link sent → /verify-email
  3. User clicks verification link → redirected back
  4. Account pending admin approval → /pending-approval
  5. Admin approves account → user can access /dashboard

Admin Flow

  1. Admin signs in → automatically redirected to /dashboard
  2. Admin can access /admin panel
  3. Admin can approve/revoke user access
  4. Admin has full platform access

Pages

Route Description Access
/ Landing page Public
/sign-up User registration Public
/sign-in User login Public
/verify-email Email verification status Authenticated
/pending-approval Waiting for admin approval Authenticated
/dashboard Main dashboard Approved users
/admin Admin panel Admins only

Security Features

  • Row Level Security (RLS): Database-level access control
  • Email Verification: Ensures valid email addresses
  • Admin Approval: Manual approval prevents unauthorized access
  • Middleware Protection: Server-side route guarding
  • Secure Cookies: HTTP-only cookies for session management
  • Password Hashing: Supabase handles secure password storage

Scripts

npm run dev          # Start development server
npm run build        # Build for production
npm run start        # Start production server
npm run lint         # Run ESLint
npm run lint:fix     # Fix ESLint errors
npm run format       # Format code with Prettier
npm run type-check   # Check TypeScript types

Environment Variables

Variable Description Required
NEXT_PUBLIC_SUPABASE_URL Your Supabase project URL Yes
NEXT_PUBLIC_SUPABASE_ANON_KEY Your Supabase anon/public key Yes

Database Schema

user_profiles Table

Column Type Description
user_id UUID Primary key, references auth.users
email TEXT User email (unique)
is_approved BOOLEAN Admin approval status
is_admin BOOLEAN Admin role flag
created_at TIMESTAMP Account creation time
updated_at TIMESTAMP Last update time

Troubleshooting

Email not sending

  • Check Supabase email settings
  • Verify SMTP configuration
  • Free tier has email limits

Can't access admin panel

  • Ensure you ran the SQL to set is_admin = TRUE
  • Sign out and sign back in

Stuck on pending approval

  • Admin needs to approve at /admin
  • Check database for approval status

Production Deployment

Vercel (Recommended)

  1. Push your code to GitHub
  2. Import project to Vercel
  3. Add environment variables
  4. Update Supabase Site URL and Redirect URLs
  5. Deploy

Other Platforms

  1. Build the project: npm run build
  2. Set environment variables
  3. Update Supabase settings with production URL
  4. Deploy

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License

Support

If you encounter any issues:

  1. Check that your Supabase environment variables are correct
  2. Verify database tables and policies are created
  3. Check browser console and terminal logs for errors
  4. Ensure your Supabase project is active and not paused

Built with ❤️ using Next.js and Supabase

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors