TextGuard: Building a Spam Detection App
I built a spam detector without using any AI APIs. Here's how heuristics and basic probability can go a long way.
The Project
TextGuard is a spam detection demo I built to explore what's possible without reaching for an LLM.
The idea: can we build something useful with just pattern matching and basic statistics?
The Approach
Heuristics
Some signals are obvious spam indicators:
function getHeuristicScore(text) {
let score = 0;
// Excessive caps
const capsRatio = (text.match(/[A-Z]/g) || []).length / text.length;
if (capsRatio > 0.5) score += 0.2;
// Too many exclamation marks
const exclamations = (text.match(/!/g) || []).length;
if (exclamations > 3) score += 0.15;
// Contains suspicious URLs
if (text.match(/bit\.ly|tinyurl|click here/i)) score += 0.3;
// Money/urgency language
if (text.match(/free|winner|urgent|limited time/i)) score += 0.2;
return Math.min(score, 1);
}
Naive Bayes
For the probabilistic part, I used a simple Naive Bayes classifier trained on labeled examples:
class NaiveBayes {
constructor() {
this.wordCounts = { spam: {}, ham: {} };
this.categoryCounts = { spam: 0, ham: 0 };
}
train(text, category) {
const words = this.tokenize(text);
words.forEach(word => {
this.wordCounts[category][word] =
(this.wordCounts[category][word] || 0) + 1;
});
this.categoryCounts[category]++;
}
classify(text) {
const words = this.tokenize(text);
let spamScore = Math.log(this.categoryCounts.spam / this.totalDocs());
let hamScore = Math.log(this.categoryCounts.ham / this.totalDocs());
words.forEach(word => {
spamScore += Math.log(this.wordProbability(word, 'spam'));
hamScore += Math.log(this.wordProbability(word, 'ham'));
});
return spamScore > hamScore ? 'spam' : 'ham';
}
}
Combining Scores
The final score is a weighted combination:
function getSpamScore(text) {
const heuristicScore = getHeuristicScore(text);
const bayesScore = classifier.getScore(text);
return (heuristicScore * 0.3) + (bayesScore * 0.7);
}
The Stack
- **Frontend**: React with Vite
- **Backend**: Express.js
- **No database** - Classifier trained at startup from JSON file
What I Learned
1. **Simple often works** - You don't need GPT-4 for everything 2. **Heuristics are underrated** - Domain knowledge beats algorithms 3. **Probability basics go far** - Naive Bayes is surprisingly effective
Try It
- Live demo: textguard.chrishacia.com
- Source: github.com/chrishacia/TextGuard
What simple approaches have you used instead of reaching for ML/AI?