We recently embarked on a journey to integrate a robust and secure comment system into our blog and portfolio pages. The goal was to provide an easy way for visitors to engage with our content without the hassle of traditional authentication, while ensuring the system remains protected from abuse. Here’s a look at how we built it.

What We Built

Our comment system allows users to post comments using only a display name and an arbitrary public ID, eliminating the need for complex sign-up processes. Key features include:

  • Authentication-Free Posting: Simple comment submission with a display name and a user-chosen ID.
  • Modern Backend: Utilizes Vercel Postgres for data storage and Next.js App Router’s Route Handlers for our API.
  • Integrated Experience: Seamlessly embedded comment lists and submission forms directly into both blog and portfolio pages.

Data Model: A Glimpse into the Database

At the heart of our system is a comments table, designed for efficiency and scalability. Each comment is assigned a unique UUID by the application. The table schema includes:

  • `id`: Unique identifier (UUID).
  • `site`: Indicates whether the comment belongs to the ‘blog’ or ‘portfolio’.
  • `slug`: Identifier for the specific page/post.
  • `user_display_name` & `user_public_id`: User identification without authentication.
  • `content`: The actual comment text.
  • `created_at`: Timestamp of comment creation.
  • `ip_hash`: A hashed version of the user’s IP for rate limiting (privacy-preserving).
  • `is_approved`: Boolean flag for moderation (defaults to true).
  • `parent_id`: Allows for threaded replies.

API Design: The Engine Behind the Comments

Our API is designed to be efficient and secure:

  • GET `/api/comments?site=…&slug=…`: Retrieves only approved comments relevant to a specific page.
  • POST `/api/comments`: Handles new comment submissions, enforcing content validation, employing honeypot techniques to deter bots, and applying rate limits based on hashed IP addresses.
  • PATCH/DELETE `/api/comments/[id]`: These endpoints are secured, requiring an `Authorization: Bearer COMMENT_ADMIN_TOKEN` for any moderation actions.

For enhanced security and privacy, we generate id using randomUUID() and store only sha256(ip + SALT) for IP addresses.

User Interface: Engaging and Intuitive

The CommentSection component offers a straightforward user experience:

  • Fields for display name, user ID, comment content, and a consent checkbox.
  • Comments are refreshed instantly after a successful submission.
  • The UI seamlessly integrates with our existing design system for a consistent look and feel.

Configuration for Flexibility and Security

We manage essential configurations via environment variables:

  • `POSTGRES_URL`: Connection string for Vercel Postgres.
  • `COMMENT_ADMIN_TOKEN`: A long, random value for securing moderation endpoints.
  • `COMMENT_HASH_SALT`: A unique salt for IP hashing, enhancing privacy.
  • `COMMENT_RATE_LIMIT_PER_MIN`: Sets the maximum number of comments a single IP can post per minute.
  • `COMMENT_MAX_LENGTH`: Defines the maximum allowed length for comment content.

Conclusion and Future Vision

By focusing on a well-thought-out, secure design from the outset, we aim to minimize operational overhead and ensure a positive user experience. This system, even with its current simplicity, is built to be resilient against common misuse. Looking ahead, we plan to expand its capabilities with features like threaded replies, a dedicated moderation UI, and comment export functionalities.

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.
You need to agree with the terms to proceed