From Zero to Spam-Proof: Building a Bulletproof Feedback System

Building a Feedback System: How One Developer Went from Zero to Spam-Protected
The task was straightforward but ambitious: build a complete feedback collection system for borisovai-site that could capture user reactions, comments, and bug reports while protecting against spam and duplicate submissions. Not just the backend—the whole thing, from API endpoints to React components ready to drop into pages.
I started by designing the content-type schema in what turned out to be the most critical decision of the day. The feedback model needed to support multiple submission types: simple helpful/unhelpful votes, star ratings, detailed comments, bug reports, and feature requests. This flexibility meant handling different payload shapes, which immediately surfaced a design question: should I normalize everything into a single schema or create type-specific handlers? I went with one unified schema with optional fields, storing the submission type as a categorical field. Cleaner, more queryable, easier to extend later.
The real complexity came with protection mechanisms. Spam isn’t just about volume—it’s about the same user hammering the same page with feedback. So I built a three-layer defense: browser fingerprinting that combines User-Agent, screen resolution, timezone, language, WebGL capabilities, and Canvas rendering into a SHA256-like hash; IP-based rate limiting capped at 20 feedbacks per hour; and a duplicate check that prevents the same fingerprint from submitting twice to the same page. Each protection layer stored different data—the fingerprint and IP address were marked as private fields in the schema, never exposed in responses.
The fingerprinting logic was unexpectedly tricky. Browsers don’t make it easy to get a reliable unique identifier without invasive techniques. I settled on collecting public browser metadata and combining it with canvas fingerprinting—rendering a specific pattern and hashing the pixel data. It’s not bulletproof (sophisticated users can spoof it), but it’s sufficient for catching casual spam without requiring cookies or tracking pixels.
On the frontend, I created a reusable React Hook called useFeedback that handled all the API communication, error states, and local state management. Then came the UI components: HelpfulWidget for the simple thumbs-up/down pattern, RatingWidget for star ratings, and CommentForm for longer-form feedback. Each component was designed to be self-contained and droppable anywhere on the site.
Here’s something interesting about browser fingerprinting: it’s a weird space between privacy and security. The same technique that helps prevent spam can also be used for user tracking. The difference is intent and transparency. A feedback system storing a fingerprint to prevent duplicate submissions is reasonable. Selling that fingerprint to ad networks is not. It’s a line developers cross more often than they should admit.
By the end, I’d created eight files across backend and frontend, generated three documentation pieces (full implementation guide, quick-start reference, and architecture diagrams), and had the entire system ready for integration. The design team had a brief with eight questions about how these components should look and behave.
The next phase is visual design and then deployment, but the hard structural work is done. The system is rate-limited, protected against duplicates, and extensible enough to handle new feedback types without refactoring. Mission accomplished—and no spam getting through on day one.
Metadata
- Session ID:
- grouped_borisovai-site_20260213_0919
- Branch:
- master
- Dev Joke
- Почему GitHub Actions лучший друг разработчика? Потому что без него ничего не работает. С ним тоже, но хотя бы есть кого винить