Ever wanted to create a desktop app that recommends jobs based on your skills? In this tutorial, we’ll build a Job Recommendation Engine using Python, Tkinter, and ttkbootstrap.
We’ll cover:
Setting up the project
Defining the job data structure
Fetching and filtering jobs
Building a simple recommendation engine
Displaying results with Tkinter UI
Adding pagination and search
Let’s get started! 🚀
- Setup & Install Dependencies
First, make sure you have Python 3 installed. Then install the required packages:
pip install ttkbootstrap pillow requests
Packages explained:
ttkbootstrap → For modern Tkinter UI styling
Pillow → To handle and display images (company logos)
requests → To fetch logos from URLs
- Define the Job Data Structure
We’ll use a dataclass to represent each job. This makes it easy to store and manage job info.
from dataclasses import dataclass
from typing import List
@dataclass
class Job:
title: str
company: str
url: str
description: str
skills: List[str]
location: str
logo_url: str = ""
score: float = 0.0
✅ This gives each job a title, company, location, skills, logo, and a score for recommendations.
- Fetch Jobs
For this tutorial, we’ll use a static list of jobs. Later, you could replace this with API calls.
def fetch_jobs(query: str) -> List[Job]:
jobs_data = [
Job("Python Developer", "TechCorp", "https://example.com/job1",
"Develop backend applications using Python.", ["Python", "Django"], "Remote",
"https://via.placeholder.com/100x100.png?text=TechCorp"),
Job("Frontend Engineer", "Webify", "https://example.com/job2",
"Build responsive web apps with React.", ["JavaScript", "React"], "NY, USA",
"https://via.placeholder.com/100x100.png?text=Webify"),
Job("Data Scientist", "DataWorks", "https://example.com/job3",
"Analyze large datasets and build ML models.", ["Python", "ML", "Pandas"], "SF, USA",
"https://via.placeholder.com/100x100.png?text=DataWorks"),
]
# Filter jobs by query keyword
query_tokens = set(query.lower().split())
matched_jobs = []
for job in jobs_data:
text_to_match = " ".join([
job.title.lower(),
job.description.lower(),
" ".join(job.skills).lower()
])
if any(token in text_to_match for token in query_tokens):
matched_jobs.append(job)
return matched_jobs
💡 Tip: This simple search matches keywords in the job title, description, or skills.
- Build a Simple Recommendation Engine
We’ll assign a score to each job based on keyword matches to rank results.
def recommend_jobs(query: str, candidates: List[Job], top_n=5):
query_tokens = set(query.lower().split())
recommendations = []
for job in candidates:
text_to_match = " ".join([
job.title.lower(),
job.description.lower(),
" ".join(job.skills).lower()
])
score = sum(1 for token in query_tokens if token in text_to_match)
recommendations.append((job, score))
recommendations.sort(key=lambda x: x[1], reverse=True)
return recommendations[:top_n]
✅ Higher scores mean better matches. This is a simple content-based recommendation.
- Load Company Logos
We’ll use Pillow to fetch and display images in the app.
import requests
from PIL import Image, ImageTk
import io
logo_cache = {}
def load_image(url, size=(80, 80)):
if not url:
return None
if url in logo_cache:
return logo_cache[url]
try:
resp = requests.get(url, timeout=10)
img = Image.open(io.BytesIO(resp.content))
img = img.resize(size, Image.ANTIALIAS)
photo = ImageTk.PhotoImage(img)
logo_cache[url] = photo
return photo
except Exception:
return None
💡 Tip: Caching avoids downloading the same image multiple times.
- Build the Tkinter UI
Now let’s build the user interface with ttkbootstrap.
import ttkbootstrap as tb
from ttkbootstrap.widgets.scrolled import ScrolledText
import tkinter as tk
app = tb.Window(title="Job Recommendation Engine", themename="flatly", size=(980, 720))
Top Section: Search Bar
top = tb.Frame(app, padding=15)
top.pack(fill=tk.X)
tb.Label(top, text="Job Recommendation Engine", font=("Segoe UI", 16, "bold")).pack(anchor=tk.W)
query_entry = tb.Entry(top, font=("Segoe UI", 12))
query_entry.pack(fill=tk.X, pady=8)
tb.Button(top, text="Search", bootstyle="primary", command=lambda: print("Search clicked!")).pack(anchor=tk.E)
Results Area
result_frame = tb.Frame(app, padding=(15, 5))
result_frame.pack(fill=tk.BOTH, expand=True)
result_box = ScrolledText(result_frame, autohide=True)
result_box.pack(fill=tk.BOTH, expand=True)
text = result_box.text
text.configure(state="disabled", wrap="word")
This is where job results will be displayed.
Pagination
nav = tb.Frame(app, padding=10)
nav.pack(fill=tk.X)
prev_btn = tb.Button(nav, text="← Prev", bootstyle="secondary")
prev_btn.pack(side=tk.LEFT)
page_label = tb.Label(nav, text="Page 1", font=("Segoe UI", 10))
page_label.pack(side=tk.LEFT, padx=10)
next_btn = tb.Button(nav, text="Next →", bootstyle="secondary")
next_btn.pack(side=tk.LEFT)
💡 You can now hook these buttons to navigate between result pages.
- Putting It All Together
Finally, connect the search input with fetching, recommending, and displaying jobs. Use threading to avoid freezing the UI:
import threading
def perform_search():
query = query_entry.get().strip()
if not query:
return
threading.Thread(target=search_thread, args=(query,), daemon=True).start()
def search_thread(query):
candidates = fetch_jobs(query)
recommendations = recommend_jobs(query, candidates)
for job, score in recommendations:
print(f"{job.title} @ {job.company} | Score: {score}")
- Try It Out
Run your script:
python job_recommender.py
Type a keyword like Python or React
Double-click a job title to open the link (if implemented)
Navigate with Prev / Next buttons
- Full Source Code
You can find the full project on GitHub:
https://github.com/rogers-cyber/JOBREC
Conclusion
Congrats! 🎉 You now have a working Job Recommendation Engine with:
Python data classes
Simple content-based recommendations
Tkinter UI with search, results, and pagination
Next steps:
Replace the static job list with real API calls
Add fuzzy matching for smarter search
Enhance UI with images, icons, and filters

Top comments (0)