Skip to content

Repository files navigation


FastAPI Chrome HuggingFace Python

Groq Mistral Claude


⚡ A Chrome extension + FastAPI backend that lives inside Upwork

Auto-extracts job data · Scores your profile · Writes proposals · Coaches your replies
Bring your own API key — developer hosts nothing, pays nothing.


🔍 Profile Analysis 💼 Job Evaluation 📝 Auto Proposals 💬 Reply Coaching
Score title & bio Apply or Skip Generated on high score Sales tactics for clients

What It Does

Feature Where it runs What it gives you
Profile Optimizer upwork.com/freelancers/* Scores title & bio, finds issues, suggests rewrites
Job Evaluator upwork.com/jobs/* Apply / Skip decision with score, green/red flags, proposal tips
Auto Proposal upwork.com/jobs/* Generates a tailored proposal when job score is high enough
Conversion Coach upwork.com/messages/* Suggests replies to client messages with tactics
Title Generator Extension popup 5 AI-optimized profile title variants

Screenshots

Job Evaluation — Panel Job Evaluation — Results
Job — Score & Flags Profile Evaluation — Open
Profile — Scores Profile — Suggestions
Profile — Titles Extension Icon

Architecture

Chrome Extension (MV3)
    │
    ├── content/profile.js   ← runs on upwork.com/freelancers/*
    ├── content/job.js       ← runs on upwork.com/jobs/*
    ├── content/messages.js  ← runs on upwork.com/messages/*
    └── background.js        ← service worker, routes API calls
            │
            │  HTTPS  (BYOK: X-API-Key header)
            ▼
FastAPI Backend (HuggingFace Spaces — Docker)
    │
    ├── /profile/analyze
    ├── /job/evaluate
    ├── /proposal/generate
    ├── /tools/generate-titles
    └── /tools/conversion-coach
            │
            ├── Groq   (free)  — llama-3.3-70b-versatile
            ├── Mistral        — mistral-small-latest
            └── Claude         — claude-haiku-4-5

Part 1 — Deploy the Backend (HuggingFace Spaces)

The backend is a Docker app. HuggingFace Spaces hosts it for free — no credit card needed.

Step 1 — Create a Space

  1. Go to huggingface.co and sign in (or create a free account)
  2. Click New Space
  3. Fill in:
    • Space name: upwork-optimizer-api (or any name you want)
    • SDK: Docker
    • Visibility: Public
  4. Click Create Space

Step 2 — Get a HuggingFace Token

  1. Go to Settings → Access Tokens
  2. Click New Token → choose Write permission
  3. Copy the token — you'll need it next

Step 3 — Push the Code

# Clone the repo
git clone https://github.com/YOUR_USERNAME/upwork-optimizer.git
cd upwork-optimizer

# Add HuggingFace as a remote
git remote add hf https://YOUR_HF_USERNAME:YOUR_HF_TOKEN@huggingface.co/spaces/YOUR_HF_USERNAME/upwork-optimizer-api

# Push
git push hf main

Replace YOUR_HF_USERNAME and YOUR_HF_TOKEN with your actual values.

Step 4 — Wait for Build

  • Go to your Space page on HuggingFace
  • Click the Logs tab and watch the Docker build
  • When it shows Running, your API is live at:
https://YOUR_HF_USERNAME-upwork-optimizer-api.hf.space

Step 5 — Update the Extension with Your URL

Open extension/background.js and change line 1:

// Before
const API_BASE = "https://hizardev-upwork-optimizer-api.hf.space";

// After
const API_BASE = "https://YOUR_HF_USERNAME-upwork-optimizer-api.hf.space";

Note: HuggingFace free Spaces sleep after ~15 minutes of inactivity. The first request after sleep takes ~20-30 seconds to wake up — this is normal.


Part 2 — Install the Chrome Extension

Step 1 — Get an API Key

Pick one provider and get a free or paid key:

Provider Cost Get Key
Groq Free console.groq.com/keys
Mistral Paid console.mistral.ai/api-keys
Claude Paid console.anthropic.com/settings/keys

Groq is recommended for free usage — it's fast and the quota is generous.

Step 2 — Load the Extension

  1. Open Chrome and go to chrome://extensions
  2. Enable Developer mode (toggle in top-right)
  3. Click Load unpacked
  4. Select the extension/ folder from this repo
  5. The ⚡ icon will appear in your Chrome toolbar

Step 3 — Add Your API Key

  1. Click the ⚡ icon in the toolbar
  2. Select your provider (Groq / Mistral / Claude)
  3. Paste your API key
  4. Click Save
  5. Click Test Connection to verify it works

Part 3 — Using the Extension

On a Job Page (upwork.com/jobs/*)

  1. Open any Upwork job listing
  2. Click the ⚡ EVALUATE button (bottom-right of the page)
  3. The panel opens and auto-fills the job title and description
  4. If auto-fill fails, paste manually into the text fields
  5. Click Evaluate This Job
  6. You'll get:
    • APPLY / SKIP recommendation with a score out of 10
    • Green flags (good signs) and red flags (risks)
    • Proposal writing tips
    • If the job scores high enough — a full proposal is auto-generated

On Your Profile Page (upwork.com/freelancers/*)

  1. Open your Upwork profile
  2. Click the ⚡ OPTIMIZE button
  3. The panel auto-fills your title and bio
  4. Click Analyze My Profile
  5. You'll get:
    • Scores for Title Clarity, Bio Hook, Positioning, Simplicity, and Overall
    • Specific issues found
    • Actionable improvement steps
    • A rewritten title suggestion
    • A stronger bio opening
    • 5 alternative title variants with explanations

On Messages (upwork.com/messages/*)

  1. Open any Upwork conversation
  2. Click the ⚡ REPLY button
  3. The panel tries to auto-detect the last client message
  4. If not detected, paste the message manually
  5. Optionally add context about the job
  6. Click Get Reply Suggestion
  7. You'll get a suggested reply + the sales tactic used + what to avoid

API Endpoints Reference

All endpoints accept POST requests with Content-Type: application/json and require the X-API-Key header.

POST /profile/analyze

{
  "title": "Your Upwork profile title",
  "bio": "Your full bio/overview text",
  "model": "groq"
}

POST /job/evaluate

{
  "job_title": "Job title",
  "job_description": "Full job description",
  "client_rating": 4.9,
  "client_country": "United States",
  "hire_rate": 80,
  "total_spent": "$10K",
  "proposals_count": 15,
  "model": "groq"
}

POST /proposal/generate

{
  "job_title": "Job title",
  "job_description": "Full job description",
  "freelancer_niche": "Flutter developer specializing in AI apps",
  "model": "groq"
}

POST /tools/generate-titles

{
  "skills": "Flutter, Firebase, AI integration",
  "target_clients": "startups and product companies",
  "current_title": "Flutter Developer",
  "model": "groq"
}

POST /tools/conversion-coach

{
  "client_message": "What's your rate for this?",
  "context": "Mobile app project, 3 months timeline",
  "model": "groq"
}

Models

Model Provider model value Notes
LLaMA 3.3 70B Groq groq Free tier available
Mistral Small Mistral mistral Fast, affordable
Claude Haiku Anthropic claude High quality

Local Development

# Clone and install
git clone https://github.com/YOUR_USERNAME/upwork-optimizer.git
cd upwork-optimizer
pip install -r requirements.txt

# Create .env with your keys (optional — extension sends keys via header)
cp .env.example .env

# Run
uvicorn app.main:app --reload --port 8000

API docs available at http://localhost:8000/docs


Project Structure

upwork-optimizer/
├── app/
│   ├── main.py
│   ├── core/
│   │   ├── config.py          # Settings / env vars
│   │   ├── dependencies.py    # BYOK header dependency
│   │   └── parsing.py         # LLM JSON parser
│   ├── models/
│   │   └── schemas.py         # Pydantic request/response models
│   ├── routers/
│   │   ├── profile.py
│   │   ├── job.py
│   │   ├── proposal.py
│   │   └── tools.py
│   └── services/
│       ├── llm_router.py      # Claude / Mistral / Groq routing
│       ├── document_loader.py # Playbook chapter loader
│       ├── profile_service.py
│       ├── job_service.py
│       ├── proposal_service.py
│       └── tools_service.py
├── extension/
│   ├── manifest.json
│   ├── background.js
│   ├── content/
│   │   ├── profile.js
│   │   ├── job.js
│   │   └── messages.js
│   ├── popup/
│   │   ├── settings.html
│   │   ├── settings.css
│   │   └── settings.js
│   └── sidebar/
│       └── sidebar.css
├── Docs/
│   └── upwork_complete_playbook.docx
├── screenshot/
├── Dockerfile
├── requirements.txt
└── README.md

Packaging a Release (Share the Extension)

Chrome extensions aren't installable from a .exe — users load a ZIP. Here's how to create and share a proper release on GitHub.

Step 1 — Create the extension ZIP

Windows (PowerShell):

Compress-Archive -Path "extension\*" -DestinationPath "upwork-optimizer-extension-v1.0.0.zip"

Mac / Linux:

cd extension
zip -r ../upwork-optimizer-extension-v1.0.0.zip . -x "*.DS_Store"

Step 2 — Create a GitHub Release

  1. Push your latest code to GitHub
  2. Go to your repo → ReleasesDraft a new release
  3. Click Choose a tag → type v1.0.0Create new tag
  4. Set title: v1.0.0 — Initial Release
  5. Write release notes (what it does, what's new)
  6. Under Assets, drag and drop the .zip file you created
  7. Click Publish release

Step 3 — How users install it

Share the GitHub release link. Users do:

  1. Download upwork-optimizer-extension-v1.0.0.zip from the release
  2. Unzip it to a folder on their computer
  3. Open Chrome → chrome://extensions
  4. Enable Developer mode (top-right toggle)
  5. Click Load unpacked → select the unzipped folder
  6. Done — extension is installed

About

AI-powered tool to analyze and optimize Upwork profiles with actionable insights, scoring, and auto-generated descriptions to help freelancers get more clients.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages