Ryans Recruit Firm - AI Recruitment Site

A professional recruitment website built with Node.js, Express, and PostgreSQL. Features include job listings, application management, CV storage, and admin dashboard.

Features

Public Features

  • Job Listings - Browse open positions with detailed information
  • Online Applications - Submit applications with CV upload
  • Contact Form - Get in touch with the recruitment team
  • Responsive Design - Works on desktop, tablet, and mobile

Admin Features

  • Dashboard - Overview statistics and quick access
  • Application Management - View, filter, and manage applicants
  • CV Downloads - Download applicant CVs directly
  • Job Management - Create, edit, and manage job postings
  • First-time Setup - Automatic admin account creation on first login

Technology Stack

  • Backend: Node.js + Express
  • Database: PostgreSQL with BYTEA for CV storage
  • Authentication: Session-based with bcrypt
  • File Upload: Multer (PDF, DOC, DOCX support)
  • Deployment: Docker + Docker Compose + Coolify

Quick Start

Local Development

  1. Clone the repository

    git clone <repository-url>
    cd ai-recruit-site-template
    
  2. Install dependencies

    npm install
    
  3. Set up environment

    cp .env.example .env
    # Edit .env with your configuration
    
  4. Start PostgreSQL (if not using Docker)

    # Install PostgreSQL and create database 'recruitment'
    psql -U postgres -c "CREATE DATABASE recruitment;"
    
  5. Run migrations

    psql -U postgres -d recruitment -f migrations/001_init_schema.sql
    psql -U postgres -d recruitment -f migrations/002_seed_data.sql
    
  6. Start the application

    npm start
    
  7. Access the site

Docker Development

  1. Start all services

    docker-compose up -d
    
  2. View logs

    docker-compose logs -f app
    
  3. Stop services

    docker-compose down
    

Deployment to Coolify

Prerequisites

  • Coolify account and API token
  • Gitea repository
  • Cloudflare account (for DNS)

Environment Variables

export COOLIFY_TOKEN="your-coolify-api-token"
export GITEA_TOKEN="your-gitea-access-token"
export CLOUDFLARE_TOKEN="your-cloudflare-api-token"
export COOLIFY_API="https://app.coolify.io/api/v1"
export GITEA_API="https://git.startanaicompany.com/api/v1"
export CLOUDFLARE_API="https://api.cloudflare.com/client/v4"

Step 1: Generate SSH Deploy Keys

ssh-keygen -t ed25519 -f /tmp/recruitai_deploy_key -C "coolify-recruitai-deploy" -N ""

Step 2: Create Coolify Project

curl -s -X POST "${COOLIFY_API}/projects" \
  -H "Authorization: Bearer ${COOLIFY_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "RecruitAI",
    "description": "AI Recruitment Site"
  }'

Step 3: Add Deploy Key to Coolify

PRIVATE_KEY=$(cat /tmp/recruitai_deploy_key | jq -R -s .)

curl -s -X POST "${COOLIFY_API}/private-keys" \
  -H "Authorization: Bearer ${COOLIFY_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"name\": \"recruitai-deploy-key\",
    \"description\": \"Deploy key for recruitai repository\",
    \"private_key\": ${PRIVATE_KEY}
  }"

Step 4: Push to Gitea

git remote add origin git@git.startanaicompany.com:username/ai-recruit-site-template.git
git add .
git commit -m "Initial commit: AI Recruitment Site"
git push -u origin main

Step 5: Add Deploy Key to Gitea

cat > /tmp/gitea_deploy_key.json << EOF
{
  "title": "Coolify Deploy Key",
  "key": "$(cat /tmp/recruitai_deploy_key.pub)",
  "read_only": true
}
EOF

curl -s -X POST "${GITEA_API}/repos/username/ai-recruit-site-template/keys" \
  -H "Authorization: token ${GITEA_TOKEN}" \
  -H "Content-Type: application/json" \
  -d @/tmp/gitea_deploy_key.json

Step 6: Create Coolify Application

curl -s -X POST "${COOLIFY_API}/applications/public" \
  -H "Authorization: Bearer ${COOLIFY_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "project_uuid": "YOUR_PROJECT_UUID",
    "environment_name": "production",
    "server_uuid": 0,
    "type": "public",
    "source": {
      "type": "git",
      "url": "git@git.startanaicompany.com:username/ai-recruit-site-template",
      "branch": "main",
      "private_key_uuid": "YOUR_PRIVATE_KEY_UUID"
    },
    "build_pack": "dockerfile",
    "ports_exposes": "3000",
    "name": "recruitai"
  }'

Step 7: Add Webhook to Gitea

curl -s -X POST "${GITEA_API}/repos/username/ai-recruit-site-template/hooks" \
  -H "Authorization: token ${GITEA_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "gitea",
    "config": {
      "url": "https://app.coolify.io/api/v1/deploy?uuid=YOUR_APP_UUID",
      "content_type": "json",
      "http_method": "GET"
    },
    "events": ["push"],
    "active": true
  }'

Step 8: Configure Cloudflare DNS

curl -s -X POST "${CLOUDFLARE_API}/zones/YOUR_ZONE_ID/dns_records" \
  -H "Authorization: Bearer ${CLOUDFLARE_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "CNAME",
    "name": "recruitai",
    "content": "YOUR_COOLIFY_FQDN",
    "ttl": 1,
    "proxied": false
  }'

Step 9: Update Application Domain

curl -s -X PATCH "${COOLIFY_API}/applications/YOUR_APP_UUID" \
  -H "Authorization: Bearer ${COOLIFY_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "domains": "http://recruitai.startanaicompany.com"
  }'

Step 10: Deploy

curl -s -X GET "${COOLIFY_API}/deploy?uuid=YOUR_APP_UUID&force=true" \
  -H "Authorization: Bearer ${COOLIFY_TOKEN}"

First Time Setup

Admin Account

  1. Navigate to /admin/login
  2. On first visit, you'll be prompted to create an admin account
  3. Enter your email, password, and full name
  4. Click "Create Admin Account"
  5. You'll be logged in automatically

Add Jobs

  1. Go to Admin Dashboard → Jobs
  2. Click "Create New Job"
  3. Fill in job details
  4. Click "Save"

Database Schema

Tables

  • admins - Admin user accounts
  • job_postings - Job listings
  • applicants - Applicant information
  • applications - Application submissions with CV storage (BYTEA)
  • contact_submissions - Contact form messages

Migrations

Migrations are located in /migrations/ and run automatically on first Docker startup.

API Endpoints

Public APIs

  • GET /api/jobs - List all active jobs
  • GET /api/jobs/:id - Get job details
  • POST /api/apply - Submit application (multipart/form-data)
  • POST /api/contact - Submit contact form

Admin APIs (Authentication Required)

  • POST /api/admin/login - Login / Create first admin
  • GET /api/admin/check - Check auth status
  • POST /api/admin/logout - Logout
  • GET /api/admin/stats - Dashboard statistics
  • GET /api/admin/applications - List applications
  • GET /api/admin/applications/:id - Get application details
  • GET /api/admin/applications/:id/cv - Download CV
  • PATCH /api/admin/applications/:id - Update application
  • GET /api/admin/jobs - List all jobs
  • POST /api/admin/jobs - Create job
  • PATCH /api/admin/jobs/:id - Update job
  • DELETE /api/admin/jobs/:id - Delete job

Security Features

  • Password Hashing - bcrypt with 10 rounds
  • Session Management - Secure HTTP-only cookies
  • SQL Injection Protection - Parameterized queries
  • File Upload Validation - Type and size checks
  • CSRF Protection - Session-based authentication
  • Rate Limiting - (Recommended to add in production)

Environment Variables

Variable Description Default
DB_HOST PostgreSQL host postgres
DB_PORT PostgreSQL port 5432
DB_NAME Database name recruitment
DB_USER Database user postgres
DB_PASSWORD Database password changeme123
PORT Application port 3000
NODE_ENV Environment production
SESSION_SECRET Session encryption key (required)

File Upload Limits

  • Max CV Size: 5MB
  • Allowed Types: PDF, DOC, DOCX
  • Storage: PostgreSQL BYTEA column

Troubleshooting

Database Connection Issues

# Check if PostgreSQL is running
docker-compose ps

# View PostgreSQL logs
docker-compose logs postgres

# Restart PostgreSQL
docker-compose restart postgres

Migration Errors

# Connect to database
docker-compose exec postgres psql -U postgres -d recruitment

# Check tables
\dt

# Re-run migrations manually
docker-compose exec postgres psql -U postgres -d recruitment -f /docker-entrypoint-initdb.d/001_init_schema.sql

Application Won't Start

# Check application logs
docker-compose logs app

# Rebuild and restart
docker-compose down
docker-compose build --no-cache
docker-compose up -d

License

MIT

Support

For issues or questions, contact: info@ryansrecruit.com Webhook configured successfully!

Repository moved to organization

Description
AI Recruitment Site for Ryans Recruit Firm
Readme 144 KiB
Languages
HTML 55.2%
JavaScript 31.8%
CSS 8.5%
PLpgSQL 4.1%
Dockerfile 0.4%