A JavaScript scraper for job leads evolved into a full SaaS system that automates lead generation and generates $1,200/month in recurring revenue.

I wasn’t trying to build a product.
I was just tired of finding clients manually.
But somehow, that frustration turned into a lead-generation system people now pay for every month.
Freelancing sounds simple… until you realize:
You’re always chasing the next client.
My routine looked like this:
Open job boards
Scroll endlessly
Copy leads
Save them somewhere
Forget half of them
It wasn’t hard.
Just exhausting.
And worse?
It didn’t scale.
One night, after saving yet another job post, I stopped and thought:
“Why am I doing this manually when this is structured data?”
That changed everything.
Because anything structured can be:
Scraped
Automated
Turned into a system
No design. No optimization.
Just results.
const puppeteer = require("puppeteer");
async function scrapeJobListings() {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto("https://example-job-board.com");
const jobResults = await page.evaluate(() => {
return Array.from(document.querySelectorAll(".job-card")).map(card => ({
title: card.querySelector(".title")?.innerText,
url: card.querySelector("a")?.href,
}));
});
await browser.close();
return jobResults;
}It wasn’t perfect.
But it saved hours.
Raw data is noise.
So I refined it:
function filterRelevantJobs(jobList) {
return jobList.filter(job =>
job.title.toLowerCase().includes("javascript") ||
job.title.toLowerCase().includes("node")
);
}Now it wasn’t scraping.
It was curating opportunities.
Manually running scripts kills momentum.
So I automated it:
const cron = require("node-cron");
cron.schedule("0 9 * * *", async () => {
console.log("Running daily scraper...");
const jobs = await scrapeJobListings();
const filteredJobs = filterRelevantJobs(jobs);
console.log(filteredJobs);
});Now it ran:
Every morning
Without effort
Without reminders
Data alone isn’t valuable.
Delivery is.
So I added email alerts:
const nodemailer = require("nodemailer");
async function sendDailyLeads(leads) {
const mailer = nodemailer.createTransport({
service: "gmail",
auth: {
user: "your@email.com",
pass: "password",
},
});
const message = leads.map(j => `${j.title} - ${j.url}`).join("\n");
await mailer.sendMail({
from: "your@email.com",
to: "client@email.com",
subject: "Daily Job Leads",
text: message,
});
}Now it became:
Scrape → Filter → Deliver → Automate
I showed it to a friend.
They said:
“Can I get this daily?”
That’s when it clicked.
I wasn’t solving my problem anymore.
I was solving a market problem.
Instead of rewriting everything, I added personalization:
const users = [
{ email: "user1@email.com", keywords: ["node", "backend"] },
{ email: "user2@email.com", keywords: ["react", "frontend"] }
];
function filterJobsByKeywords(jobs, keywords) {
return jobs.filter(job =>
keywords.some(k => job.title.toLowerCase().includes(k))
);
}Now:
One scraper
Multiple users
Personalized results
That’s SaaS logic.
At first, I gave it away.
Bad move.
So I changed it to:
👉 $10/month per user
Then:
50 users → $500/month
120 users → $1,200/month
Same system.
No extra work.
Script → Scraping data
System → Filtering + automation
Product → Multi-user SaaS
Business → Recurring revenue
And I never “started a startup.”
I just solved one problem at a time.
I used to think:
“I need better skills to make money.”
Now I think:
I need better systems.
Because with:
Node.js
Puppeteer
Node-cron
You can build real income systems.
People don’t want to search. They want results.
Once you understand that…
You stop building tools.
And start building subscriptions.

Keep exploring
A simple Node.js script built to detect website changes evolved into a fully automated mon…