Modern web editors aren’t just UI components — they’re entry points for user-generated content, which means they’re also entry points for abuse.
Platforms like Wikipedia don’t just let users edit content freely — they track, analyze, and moderate every submission. One of the key signals they rely on is IP-based metadata.
In this guide, you’ll learn how to build a simple, production-style moderation layer using:
- Editor: Froala Editor
- Geo API: IPstack
- Backend: Node.js + Express
We’ll keep it beginner-friendly, but grounded in real-world architecture.
Key Takeaways
- User-generated content requires backend moderation.
- IP-based metadata is a simple, high-impact signal for detecting abuse patterns
- Rate limiting and geo-tracking are table stakes for any platform accepting submissions
- Privacy matters: store only what you need, hash sensitive data, set retention limits
What You’re Building
By the end, your app will:
- Accept content from a WYSIWYG editor
- Capture the user’s IP and location securely, on the backend, using IPstack
- Store metadata with each post
- Apply basic moderation rules (rate limiting / blocking)
Why This Matters
If your app allows users to submit content (posts, comments, HTML):
You are exposed to:
- Spam bots
- Fake accounts
- Malicious content
- Coordinated attacks
The editor is not the problem. Uncontrolled submissions are.
Architecture Overview
Here’s the flow we’ll implement:
User → Froala Editor → Submit Content
↓
Frontend sends content
↓
Backend (Express):
- Call IPstack
- Store metadata
- Run moderation checks
↓
Save or block
Step 1: Project Setup
mkdir froala-moderation
cd froala-moderation
npm init -y
npm install express cors
Step 2: Add Froala Editor (Frontend)
Create a simple index.html:
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/froala-editor/css/froala_editor.pkgd.min.css" rel="stylesheet">
</head>
<body>
<textarea id="editor"></textarea>
<button onclick="submitContent()">Submit</button>
<script src="https://cdn.jsdelivr.net/npm/froala-editor/js/froala_editor.pkgd.min.js"></script>
<script>
const editor = new FroalaEditor('#editor');
async function submitContent() {
const content = editor.html.get();
const res = await fetch('http://localhost:3000/api/post', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content })
});
const data = await res.json();
alert(data.message);
}
</script>
</body>
</html>
This is your content entry point.
Step 3: Create Express Backend
Create server.js:
const express = require('express');
const cors = require('cors');
const path = require('path');
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
const PORT = 3000;
app.listen(PORT, () => {
console.log(Server running on http://localhost:${PORT});
});
Step 4: Capture User IP and Location (IPstack)
Sign up at IPstack and get your API key.
Add this function:
async function getGeoData() {
const API_KEY = 'YOUR_IPSTACK_KEY';
const res = await fetch(http://api.ipstack.com/check?access_key=${API_KEY});
const data = await res.json();
return {
ip: data.ip,
country: data.country_name,
city: data.city
};
}
Step 6: Add Moderation Logic
We’ll start simple.
Example rule:
- Block if too many requests from same IP
Add a basic in-memory tracker:
const requestLog = {};
function isSuspicious(ip) {
const now = Date.now();
if (!requestLog[ip]) {
requestLog[ip] = [];
}
requestLog[ip].push(now);
// keep last 1 minute
requestLog[ip] = requestLog[ip].filter(t => now - t < 60000);
return requestLog[ip].length > 5; // more than 5 posts/min
}
Step 7: Handle Content Submission
Now combine everything:
app.post('/api/post', async (req, res) => {
const { content } = req.body;
// get geo data
const geo = await getGeoData();
// moderation check
if (isSuspicious(ip)) {
return res.status(429).json({
message: 'Too many requests. Try again later.'
});
}
const post = {
content,
ip,
country: geo.country,
city: geo.city,
createdAt: new Date()
};
console.log('Saved post:', post);
res.json({ message: 'Post saved successfully!' });
});
Step 8: Privacy Best Practices
This is not optional.
✔ Do:
- Store country, not precise location
- Set retention (e.g., delete IP after 30 days)
- Keep IP private (never expose in UI)
❌ Don’t:
- Collect GPS location
- Trust frontend IP
- Store data you don’t use
Step 9: Test Your App
-
Run backend:
node server.js
Open index.html
Submit content multiple times
After ~5 rapid submissions:
- You should get a rate limit.
What You Just Built
You now have:
- A working WYSIWYG editor
- A backend moderation pipeline
- IP-based tracking
- Basic abuse prevention
This is a simplified version of what platforms like Wikipedia do.
Next Steps (Make It Production-Ready)
To level this up:
- Store data in a database (MongoDB/PostgreSQL)
- Hash IP addresses for privacy
- Add CAPTCHA for flagged users
- Integrate IP reputation services
- Build a moderation dashboard
Why This Works Well with Froala
Froala Editor fits naturally into this architecture:
- Clean API (
editor.html.get()) - Easy integration with any backend
- No lock-in to specific frameworks
- Designed for real production use — not just demos
It becomes part of your system — not a limitation.
Final Thoughts
If you’re building any app that accepts user content, you’re building a content pipeline.
The difference between a thriving platform and a spam receptacle is whether you moderate at the backend. IP-based tracking is the simplest, highest-impact place to start.
Ready to move beyond this demo? The architecture you’ve built here scales. Add a database, hash those IPs, layer in reputation scoring — and you’ve got the foundation Wikipedia uses.
Start by downloading the editor. Build fr*om there.*
Originally published on the Froala blog.
Top comments (0)