Yeti Jobs runs across three managed platforms in production: the React frontend is hosted on Vercel, the Express API is hosted on Render, and the PostgreSQL database plus file storage live on Supabase. This page walks through deploying each layer, connecting them together, and handling the quirks of free-tier hosting.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tech-dipesh/yeti-Jobs/llms.txt
Use this file to discover all available pages before exploring further.
Frontend on Vercel
Vercel auto-detects Vite projects — no build configuration is required. Thefrontend/vercel.json contains a single rewrite rule that makes client-side React Router navigation work correctly by sending all requests to index.html.
frontend/vercel.json
Import the repository
Go to vercel.com/new, click Add New Project, and import your GitHub repository. Vercel detects the
frontend/ directory as the Vite app automatically.Set the following in the Vercel project configuration:| Setting | Value |
|---|---|
| Root Directory | frontend |
| Framework Preset | Vite (auto-detected) |
| Build Command | npm run build |
| Output Directory | dist |
Add environment variables
In the Vercel dashboard go to Project → Settings → Environment Variables and add:
| Variable | Value |
|---|---|
VITE_SERVER_URL | Your Render backend URL, e.g. https://yeti-jobs.onrender.com |
Vite embeds environment variables into the bundle at build time. If you update
VITE_SERVER_URL in the Vercel dashboard, trigger a fresh deployment (Deployments → Redeploy) — the change is not picked up until the next build.Backend on Vercel (alternative)
The backend also ships with abackend/vercel.json that enables deploying the Express API as Vercel Serverless Functions. When deployed this way, every inbound request is routed to src/app.js, which is the Express application entry point compiled with the @vercel/node runtime.
backend/vercel.json
Serverless deployments on Vercel do not maintain persistent connections between invocations. This means the
pg.Pool in src/db.js reconnects on each cold start, and long-lived features such as cron jobs and WebSocket connections will not work as expected. For a production deployment that needs persistent state, use Render (documented below) instead of Vercel for the backend.Backend on Render
The Express server is deployed as a persistent Web Service on Render. Unlike Vercel serverless functions, Render runs a long-lived Node process — which suits Express well for keeping WebSocket connections, cron jobs, and pooled database connections alive.Create a new Web Service
In the Render dashboard click New → Web Service and connect your GitHub repository. Set the root directory to
backend.| Setting | Value |
|---|---|
| Root Directory | backend |
| Runtime | Node |
| Build Command | npm ci --omit=dev |
| Start Command | node db/migrate.js && node server.js |
| Instance Type | Free (or paid for always-on) |
Add all backend environment variables
In the Render dashboard go to your service → Environment and add every backend variable. See the Environment Variables reference for descriptions of each key.
| Variable | Example value |
|---|---|
DATABASE_PASSWORD | Supabase connection pooler URL (port 6543) |
URL_SUPABASE_CONNECT | https://xyzcompany.supabase.co |
ANON_KEY_SUPABASE | eyJ... |
NODEMAILER_MY_EMAIL | noreply@yourdomain.com |
NODEMAILER_MY_PASSWORD | Gmail app password |
NODEMAILER_MY_HOST | smtp.gmail.com |
JSON_SECRET_KEY | Random 32+ char string |
CLIENT_BASE_URL | https://yeti-jobs.vercel.app |
PORT | 3000 |
MAXAGE | 604800 |
GROK_API | Groq console API key |
SSL configuration
src/db.js includes ssl: { rejectUnauthorized: false } in the pg.Pool config so that the Supabase TLS certificate is accepted without requiring a CA bundle on the Render host:
backend/src/db.js
ssl: { rejectUnauthorized: false } — without it the TLS handshake to Supabase will fail on Render.
Database and Storage on Supabase
Supabase provides both the PostgreSQL database and the file-storage layer (resumes, profile pictures) for Yeti Jobs.PostgreSQL setup
Create a Supabase project
Go to supabase.com, create a new project, and choose a region closest to your Render service region to minimise latency.
Get the connection pooler URL
Navigate to Project Settings → Database → Connection pooling. Copy the Connection string for the Session mode pooler on port
6543. This is the value for DATABASE_PASSWORD.File storage (Supabase Storage)
Resumes and profile pictures are uploaded directly to Supabase Storage buckets via the@supabase/supabase-js SDK. The backend receives the file through multer, streams it to the appropriate bucket, and saves the returned public URL to the users table (resume_url or profile_pic_url columns).
To enable storage:
- In your Supabase project go to Storage and create two buckets: one for resumes and one for profile pictures (e.g.
resumes,profile-pictures). - Set bucket visibility to Public so URLs returned by the SDK are accessible without authentication tokens.
- Ensure
URL_SUPABASE_CONNECTandANON_KEY_SUPABASEare set correctly in your Render environment — the SDK uses them to authenticate storage requests.
Keep-alive for Render free tier
Render’s free tier sleeps instances after 15 minutes of inactivity. Yeti Jobs handles this with a GitHub Actions workflow at.github/workflows/keep-alive.yml that pings the backend health endpoint on a 5-minute schedule:
.github/workflows/keep-alive.yml