惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
博客园 - 【当耐特】
Cloudbric
Cloudbric
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Attack and Defense Labs
Attack and Defense Labs
爱范儿
爱范儿
The Cloudflare Blog
腾讯CDC
Security Archives - TechRepublic
Security Archives - TechRepublic
TaoSecurity Blog
TaoSecurity Blog
云风的 BLOG
云风的 BLOG
Recent Announcements
Recent Announcements
C
Check Point Blog
Schneier on Security
Schneier on Security
S
Schneier on Security
J
Java Code Geeks
B
Blog RSS Feed
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
Stack Overflow Blog
Stack Overflow Blog
博客园_首页
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
A
About on SuperTechFans
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Google DeepMind News
Google DeepMind News
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
A
Arctic Wolf
S
Secure Thoughts
P
Palo Alto Networks Blog
The Last Watchdog
The Last Watchdog
SecWiki News
SecWiki News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 三生石上(FineUI控件)
D
Darknet – Hacking Tools, Hacker News & Cyber Security
量子位
U
Unit 42
I
InfoQ
D
DataBreaches.Net
P
Privacy International News Feed
T
Troy Hunt's Blog
博客园 - 叶小钗
T
Threatpost
博客园 - Franky
K
Kaspersky official blog
Hugging Face - Blog
Hugging Face - Blog
IT之家
IT之家
www.infosecurity-magazine.com
www.infosecurity-magazine.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Cisco Blogs

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
I automated my entire job search with AI — here's the full stack I built
Sanambir Sin · 2026-04-23 · via DEV Community

Sanambir Singh

I automated my entire job search with AI — here's the full stack I built

Manual job searching is genuinely miserable.

You open LinkedIn. You scroll. You find something promising. You copy-paste
your resume into their portal, tweak the cover letter for 20 minutes, submit,
and hear nothing for two weeks. Then you do it again. And again.

I got tired of it, so I built a tool that does the entire pipeline for me:
search → AI score → tailor resume → generate cover letter → email me the
best matches.

Here's how it works and what I learned building it.


What it actually does

  1. Scrapes jobs from LinkedIn, Indeed, Glassdoor, ZipRecruiter, and Google Jobs simultaneously
  2. Scores each listing against your resume using Gemini AI (0–100% match, with reasoning and a "missing skills" list)
  3. Skips low matches — anything below your threshold (default 75%) gets stored but not processed further
  4. Tailors your resume bullet points to the specific job description
  5. Writes a cover letter personalised to the role and company
  6. Emails you a summary of the best matches with the tailored documents attached

The whole pipeline runs in the background. You set it once, and it finds and
evaluates jobs while you sleep.


The tech stack

Layer Tech
Backend FastAPI (Python 3.11)
Frontend React + TypeScript + Tailwind CSS
Database SQLite via SQLAlchemy ORM
AI Google Gemini API
Job scraping jobspy
Email Resend SMTP
Auth httpOnly cookie sessions + bcrypt
Hosting VPS via Coolify + Cloudflare CDN

Nothing exotic — the interesting parts are in how the pieces connect.


The scraping layer

I'm using jobspy, an open-source Python library that wraps LinkedIn,
Indeed, and others into a single interface. It returns a pandas DataFrame
which I convert straight to dicts:

from jobspy import scrape_jobs

jobs = scrape_jobs(
    site_name=["linkedin", "indeed", "glassdoor"],
    search_term="React Developer",
    location="Remote",
    results_wanted=15,
    hours_old=72,
    linkedin_fetch_description=True,  # full JD, not just snippet
)
linkedin_fetch_description=True is the one flag that matters most  without
it you get a 2-sentence snippet, not the actual job description. It also makes
searches 23x slower because each listing needs a separate HTTP request, but
the AI scoring is useless without the full text.

The AI scoring pipeline
Each job gets sent to Gemini with the user's resume and the full job
description. The prompt asks for a structured JSON response:


prompt = f"""
You are a recruiter. Given this resume and job description, return a JSON
object with exactly these fields:
- score: integer 0-100 (match percentage)
- reasoning: 2-3 sentence explanation
- missing_skills: list of strings (skills in JD not in resume)

Resume:
{resume_text}

Job Description:
{job_description}

Return only valid JSON. No markdown fences.
"""
Gemini is surprisingly good at this. The scores correlate well with what a
human recruiter would say — a senior dev resume against a junior listing gets
95+, the same resume against a role requiring 5 years of Java when you've
never touched it gets 2030.

I added an exponential-backoff retry wrapper because Gemini's free tier hits
rate limits when processing a batch of 15–20 jobs in parallel:


async def call_gemini_with_retry(prompt: str, max_retries: int = 4):
    delay = 2
    for attempt in range(max_retries):
        try:
            response = await model.generate_content_async(prompt)
            return response.text
        except ResourceExhausted:
            if attempt == max_retries - 1:
                raise
            await asyncio.sleep(delay + random.uniform(0, 1))
            delay *= 2
Streaming results with SSE
Waiting 5–8 minutes for a search to finish with no feedback is a terrible UX.
I switched the search endpoint to Server-Sent Events so the frontend sees
jobs appear in real time as each platform finishes:


@router.post("/search")
async def search_jobs(payload: SearchPayload, ...):
    async def event_stream():
        for platform in payload.platforms:
            jobs = await scrape_platform(platform, payload)
            for job in jobs:
                scored = await score_job(job, user.resume_text)
                yield f"data: {json.dumps(scored)}\n\n"
        yield "data: {\"done\": true}\n\n"

    return StreamingResponse(event_stream(), media_type="text/event-stream")
On the React side, the EventSource API processes each job as it arrives
and appends it to the feed — the list builds itself as you watch.

The bug that humbled me
About two days after launching, a user reported seeing someone else's jobs
in their feed.

I panicked.

After two hours of debugging, I found the root cause: Cloudflare was
caching /api/jobs responses by URL, completely ignoring the auth cookie.

The sequence that caused it:

User A logs in, hits /api/jobs  Cloudflare caches the response
User B logs in, hits /api/jobs  Cloudflare serves User A's cached data
It only happened after a cache purge (which I triggered on every deployment)
because the first request after a cold cache got stored. The fix was two lines
on every API response:


response.headers["Cache-Control"] = "no-store, no-cache, must-revalidate, private"
response.headers["Vary"]          = "Cookie, Authorization"
Plus a Cloudflare Cache Rule to bypass caching entirely for /api*. The
private directive tells any intermediary (Cloudflare, ISPs, proxies) that
the response is user-specific and must never be shared. The Vary: Cookie
tells it that even if it wanted to cache, responses differ per cookie value.

Lesson: never assume a CDN won't cache your authenticated API endpoints.
Always set cache headers explicitly.

The freemium model
I added a tier system to avoid burning through my Gemini API credits. The
backend is straightforward:


TIER_LIMITS = {"free": 3, "premium": 10}

def check_rate_limit(user: User):
    today = date.today().isoformat()
    if user.last_search_date != today:
        user.daily_searches_used = 0
        user.last_search_date = today
    limit = TIER_LIMITS.get(user.tier or "free", 3)
    if user.daily_searches_used >= limit:
        raise HTTPException(429, f"Daily limit of {limit} searches reached")
    user.daily_searches_used += 1
The reset logic compares ISO date strings  no timezone handling needed for
a daily counter. Admins bypass the check entirely.

What I'd do differently
Use PostgreSQL from day one. SQLite is fine for a solo project but
migrating later is painful. The moment you want concurrent writes or proper
JSON queries, you'll wish you started with Postgres.

Abstract the AI layer earlier. All Gemini calls are currently scattered
across scorer.py, tailor_service.py, etc. with duplicated retry logic. A
single ai_client.py with a clean interface would have saved a lot of
copy-paste.

Add observability before users arrive. I had no logging, no error
tracking, nothing. When the Cloudflare bug hit, I was debugging blind. Even
a free Sentry integration would have surfaced the issue immediately.

Enter fullscreen mode Exit fullscreen mode

Try it / look at the code

The project is open source and free to use:

Live: workfinderx.sanambir.com
GitHub: github.com/Sanambir/AutoJob-Finder
If you're in a job search right now, give it a try. If you're a developer,
the codebase is a reasonable example of a full-stack FastAPI + React app
with AI integration, SSE streaming, and a freemium tier system.

Built with Claude Code

I vibe coded the majority of this with Claude Code
— Anthropic's AI coding assistant that works directly in the terminal and
your editor. Most of the backend routers, the React components, the Gemini
integration, and the Cloudflare debugging were done in conversation with it.

If you're building a side project and haven't tried AI-assisted development
yet, it's worth it. The iteration speed is genuinely different — you spend
more time on product decisions and less time looking up syntax or boilerplate.

Questions or feedback welcome in the comments.