GoHireHumans
Official# GoHireHumans
The trusted marketplace where businesses, AI agents, and individuals hire verified human professionals on demand.
## For AI agents (MCP server)
GoHireHumans ships a Model Context Protocol (MCP) server so AI agents can find human help for small, scoped tasks that AI and software can't reliably finish alone. It is a Python stdio server with no third-party dependencies.
**Install and run** (uv, Python 3.9+):
```bash
uvx --from 'git+https://github.com/profilesearch/GohireHumans#subdirectory=backend/mcp-package' gohirehumans-mcp
```
**MCP client config** (Claude Desktop, Cursor and other stdio clients):
```json
{
"mcpServers": {
"gohirehumans": {
"command": "uvx",
"args": ["--from", "git+https://github.com/profilesearch/GohireHumans#subdirectory=backend/mcp-package", "gohirehumans-mcp"]
}
}
}
```
**Browse and search, no key needed:**
- `search_services`, `get_service_details`: find services by task, category and price
- `search_workers`, `get_recommended`: compare providers by skill, rating and price, or rank listings for a task description
- `browse_jobs`, `get_categories`: see open jobs and service categories
- `get_pricing_info`, `get_platform_info`: fees and how the platform works
**Account actions, need `GOHIREHUMANS_API_KEY` or `GOHIREHUMANS_AUTH_TOKEN`:**
- `create_job`: post a job
- `hire_worker`: hire a worker for a task
- `get_job_status`: track an order
- `release_payment`: approve completed work so the worker's listed payout is released
- `submit_review`: rate a completed order
Hiring and payment actions require the account owner's authorization. Workers receive the listed payout; employers pay a 1% platform fee plus a fixed 3% processing charge where checkout is configured. GoHireHumans is not an escrow provider.
Package docs and authentication steps: [`backend/mcp-package/README.md`](backend/mcp-package/README.md). API docs: https://www.gohirehumans.com/api-docs.html. The MCP server is MIT-licensed ([`backend/mcp-package/LICENSE`](backend/mcp-package/LICENSE)); the rest of this repository is proprietary (see [`LICENSE`](LICENSE)).
---
## Deployment guide
How the GoHireHumans site and API are built and deployed.
## Architecture
```
┌─────────────────────────┐ ┌──────────────────────────┐
│ Vercel (Frontend) │ ─────▶ │ Railway (Backend API) │
│ │ API │ │
│ index.html │ calls │ Flask + Gunicorn │
│ style.css │ │ SQLite database │
│ base.css │ │ Python 3.12 │
│ config.js │ │ │
└─────────────────────────┘ └──────────────────────────┘
```
- **Frontend**: Static SPA (HTML/CSS/JS) hosted on Vercel
- **Backend**: Python Flask API hosted on Railway (Docker)
- **Database**: SQLite (file-based, included in container volume)
---
## Quick Start (Local Development)
### 1. Start the Backend
```bash
cd backend
pip install -r requirements.txt
python server.py
```
The API will be running at `http://localhost:8080`. Test it:
```bash
curl http://localhost:8080/health
# → {"status": "ok", "service": "gohirehumans-api"}
```
### 2. Seed Demo Data
Seeding is disabled unless `SEED_SECRET` is configured. Use it only for local/demo setup and unset it in production after controlled setup.
```bash
curl -X POST http://localhost:8080/seed \
-H 'Content-Type: application/json' \
-d '{"secret":"YOUR_SEED_SECRET"}'
```
This creates local/demo marketplace records. Do not publish or rely on demo credentials for production.
### 3. Serve the Frontend
```bash
cd frontend
# Any static file server works:
python -m http.server 3000
```
Open `http://localhost:3000` in your browser.
---
## Deploy to Railway (Backend)
### Step 1: Create a Railway Project
1. Go to [railway.app](https://railway.app) and sign in
2. Click **"New Project"** → **"Deploy from GitHub Repo"**
3. Connect your GitHub account and select your repo (or use "Deploy from Local" with the Railway CLI)
### Step 2: Configure the Service
1. In your Railway project, click on the service
2. Go to **Settings** → **Build & Deploy**
3. Set **Root Directory** to `backend`
4. Railway will auto-detect the Dockerfile
### Step 3: Add Environment Variables
In the Railway dashboard, go to **Variables** and add:
| Variable | Value |
|----------|-------|
| `PORT` | `8080` (Railway usually sets this automatically) |
| `FLASK_DEBUG` | `false` |
| `DATABASE_PATH` | Optional local override. Production prefers `/data/gohirehumans.db`. |
### Step 4: Add a Persistent Volume (Important!)
SQLite needs persistent storage:
1. In Railway, click **"+ New"** → **"Volume"**
2. Mount path: `/data`
3. Do not point production SQLite under `/app`; `/app` is ephemeral.
### Step 5: Deploy
Railway deploys automatically on push. Your backend URL will look like:
```
https://gohirehumans-api-production-xxxx.up.railway.app
```
### Step 6: Optional Controlled Seed
Only seed a controlled staging/demo environment. Production auto-seeding is disabled by default.
```bash
curl -X POST https://YOUR-RAILWAY-URL/seed \
-H 'Content-Type: application/json' \
-d '{"secret":"YOUR_SEED_SECRET"}'
```
---
## Deploy to Vercel (Frontend)
### Step 1: Update API URL
Edit `frontend/config.js` and set your Railway backend URL:
```javascript
window.GOHIREHUMANS_API_URL = "https://your-railway-backend-url.up.railway.app";
```
### Step 2: Deploy to Vercel
**Option A: Vercel CLI**
```bash
cd frontend
npx vercel --prod
```
**Option B: GitHub Integration**
1. Go to [vercel.com](https://vercel.com) and sign in
2. Click **"Add New Project"** → import your repo
3. Set **Root Directory** to `frontend`
4. Framework Preset: **Other**
5. Click **Deploy**
### Step 3: Custom Domain
1. In Vercel dashboard → **Settings** → **Domains**
2. Add `gohirehumans.com`
3. Follow the DNS configuration instructions
---
## Deploy with Railway CLI (Alternative)
```bash
# Install Railway CLI
npm install -g @railway/cli
# Login
railway login
# Initialize project
cd backend
railway init
# Deploy
railway up
# Get your URL
railway domain
```
---
## Project Structure
```
GohireHumans/
├── backend/
│ ├── server.py # Flask server (production wrapper)
│ ├── api_core.py # Core API logic (~14,000 lines, single route dispatcher)
│ ├── mcp_server.py # MCP server for AI agents (mirrored in mcp-package/)
│ ├── test_*.py # unittest suites (run with discover -s backend)
│ ├── requirements.txt # Python dependencies
│ ├── Dockerfile # Container config for Railway
│ ├── railway.toml # Railway deployment config
│ ├── Procfile # Process file (Heroku/Railway)
│ ├── start.sh # Container entrypoint (execs gunicorn)
│ ├── .dockerignore # Keeps tests/tools/local DBs out of the image
│ └── .env.example # Environment variable template
│
├── frontend/
│ ├── index.html # Single Page Application (hash routes under /#/)
│ ├── style.css # Shared stylesheet: tokens, reset, components, public shell, page layouts
│ ├── app.css # Signed-in app surfaces (loaded by index.html only)
│ ├── base.css # Reset mirror for the SPA
│ ├── mobile-hardening.css # Phone-width guards (no-op above 768px)
│ ├── partials/ # Canonical public nav and footer (synced into every static page)
│ ├── *.html, blog/, hire/, use-cases/, ai-human-qa/, categories/, vs/, tools/, earn/, examples/
│ │ # Static marketing, SEO, docs, and tool pages
│ ├── analytics-bootstrap.js # Fail-closed GA loader (production origins only)
│ ├── config.js # API URL configuration ← EDIT THIS
│ ├── sitemap.xml, feed.xml, atom.xml, robots.txt, llms.txt, .well-known/
│ ├── performance-budgets.json # Byte budgets enforced in CI
│ ├── tests/ # Playwright browser regression suites
│ └── vercel.json # Vercel redirects and security headers
│
├── docs/
│ ├── design-system/ # design-system.md (tokens, components, page patterns) and public-shell.md
│ ├── ops/ # Operating playbooks and internal working docs (not deployed)
│ └── plans/ # Historical sprint plans
│
├── scripts/
│ ├── sync_public_shell.py # Sync the nav/footer partials into every static page (--check in CI)
│ ├── check_public_shell.py # Guard: every public page has the canonical shell, skip link, main, bootstrap
│ ├── performance_budget.py # Enforce performance-budgets.json
│ ├── generate_feeds.py # Rebuild feed.xml and atom.xml from blog page metadata
│ └── generate-marketplace-pulse.py
│
├── .github/workflows/ci.yml # Backend tests, static checks, Playwright suites
├── .gitignore
└── README.md # This file
```
---
## API Endpoints
| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/health` | Health check |
| `POST` | `/auth/register` | Register new user |
| `POST` | `/auth/login` | Login |
| `GET` | `/profile` | Get current user profile |
| `GET` | `/services` | List service listings |
| `POST` | `/services` | Create a service listing |
| `GET` | `/jobs` | List jobs |
| `GET` | `/me/services` | The caller's own services in every status (auth required; `page`, `per_page`, `status`, `include_removed`) |
| `GET` | `/me/jobs` | The caller's own jobs in every status, with `application_count` (auth required) |
| `POST` | `/jobs` | Create a job |
| `POST` | `/jobs/{id}/apply` | Apply to a job; payout-ready account and non-empty `cover_message` required, optional http(s) `portfolio_url`; incomplete payout setup returns 403 `payout_setup_required` |
| `GET` | `/jobs/{id}/applications` | Job-owner/admin-only JSON list; session or read-scoped API key. Each application includes `worker_payout_ready` (boolean synced hint), `suggested_rank` (1–3 or null), and `suggestion_reasons` (up to three fixed-copy strings, empty when not suggested). Only eligible, payout-ready pending/shortlisted applicants on open/reviewing fixed-price jobs with hiring enabled are suggested; no padding, no numeric score. Hiring still re-checks Stripe live; the buyer chooses. |
| `DELETE` | `/jobs/{id}/apply` | Withdraw your own pending application before a hire; one reapply allowed per job |
| `POST` | `/jobs/{id}/hire` | Hire an applicant |
| `GET` | `/services/{id}/quote` | Preview an authenticated, itemized service charge without creating an order |
| `POST` | `/services/{id}/order` | Order a listed service; optionally bind the request to a quote |
| `POST` | `/orders/{id}/approve` | Approve submitted work and release payment |
| `POST` | `/orders/{id}/review` | Leave a review |
| `POST` | `/seed` | Secret-gated local/demo seeding |
| `GET` | `/admin/dashboard` | Admin statistics |
---
## Content Safety
GoHireHumans includes built-in content safety filters that block:
- 80+ prohibited keywords and phrases
- Inappropriate service categories
- Dark web / illegal content patterns
All task titles and descriptions are automatically screened.
---
## Troubleshooting
### CORS Errors
The backend uses the `ALLOWED_ORIGINS` env var and does not allow wildcard credentials by default. If you see CORS errors:
1. Make sure the backend is running and accessible
2. Check that `config.js` has the correct backend URL
3. Ensure there's no trailing slash on the URL
### Database Reset
To start fresh locally, delete your local SQLite file and optionally run secret-gated `/seed` again. Do not delete production `/data/gohirehumans.db` without a verified backup and restore plan.
### Railway Volume Issues
If data disappears between deploys, make sure you've attached a persistent volume at `/data`. The app stores production SQLite at `/data/gohirehumans.db`.
---
## Frontend checks
The static checks CI runs, in order:
```bash
python3 scripts/check_public_shell.py
python3 scripts/sync_public_shell.py --check
python3 scripts/performance_budget.py
python3 backend/security_static_checks.py
python3 -m unittest discover -s backend -p 'test_deep_audit_regressions.py'
```
Browser suites (Playwright, desktop and Pixel 5 projects):
```bash
cd frontend && npm ci && npx playwright install chromium && npm run test:browser
```
Set `PW_PORT=<port>` if 4173 is taken on your machine; the config and specs honor it. After changing `frontend/partials/`, run `python3 scripts/sync_public_shell.py` (without `--check`) to propagate the shell, and update the JS-rendered nav and footer in `index.html` by hand. After adding a blog post, run `python3 scripts/generate_feeds.py`.
The visual system is documented in `docs/design-system/design-system.md`; static pages build on its classes instead of page-local styles.
---
## Tech Stack
- **Frontend**: Vanilla JS SPA plus static HTML pages, Newsreader and Instrument Sans (Google Fonts), CSS custom properties, one shared stylesheet
- **Backend**: Python 3.12, Flask, Gunicorn, SQLite
- **Hosting**: Vercel (frontend) + Railway (backend)
- **Security**: PBKDF2-HMAC password hashing, session tokens, rate limiting, content safety filters
- **Domain**: gohirehumans.com
TDQS
Scored across 13 tools
Most tools are distinct, and the descriptions actively cross-reference each other (e.g. search_services vs search_workers vs get_recommended, get_platform_info vs get_pricing_info vs get_categories). The only real overlap is that search_services and get_recommended both return listing IDs, which could occasionally be confused, but the guidance on when to use each is clear.
Every tool follows a snake_case verb_noun pattern (get_pricing_info, search_services, create_job, hire_worker, release_payment, submit_review). No mixing of conventions or vague verbs.
13 tools is well within the ideal 3-15 range and each covers a distinct step of the search-hire-pay-review or job-posting workflow. No redundant or filler tools.
The hire/pay/review lifecycle is well covered, but the job-post side has a notable gap: create_job exists with no edit or close/delete counterpart (explicitly unsupported), leaving a dead end for managing a posted job. Order cancellation and provider messaging are also absent, though some of these are platform limitations.