RapidComments - A Reddit-Like Commenting System With Amplify

Chirag PadyalChirag Padyal
4 min read

Introduction ๐Ÿ“–

Comments are very important for user engagement. They allow users to share their thoughts and opinions on a particular topic. They also help to build a community around a topic. However, implementing a commenting system is not an easy task. Building a robust and scalable commenting system requires a lot of time and effort. So, I decided to build an aws cloud-based commenting system using AWS Amplify.

Project Overview

Rapid Comment is a commenting system. It allows users to comment on posts and reply to other comments. It also allows users to upvote and downvote comments. It is built using amplify, appsync and cognito.

Amplify Backend: I chose GraphQL as the API specification to manage data and offer a cutting-edge development experience

Angular Frontend: I chose Angular because it has good amplify support and I am familiar with it.

Tech Stack

  1. AWS Amplify

  2. Cognito - Authentication

  3. App sync - GraphQL API

  4. Figma for ux

GraphQL Schema Explained

type Thread
  @model
  @auth(
    rules: [
      { allow: owner, ownerField: "owner", operations: [create, update, read] }
      { allow: private, provider: userPools, operations: [read] }
    ]
  ) {
  id: ID!
  name: String!
  posts: [Comment] @hasMany
}

I am using Thread as a root node. It has a one to many relationship with Comment. A thread can have multiple comments. It represents a url where the comments are displayed. Each url has a unique thread id.

type Comment
  @model
  @auth(
    rules: [
      # { allow: owner, ownerField: "owner", operations: [create, update, read] }
      {
        allow: private
        provider: userPools
        operations: [create, update, read]
      }
    ]
  ) {
  id: ID!
  threadId: Thread @belongsTo
  content: String!
  vote: [Reaction] @hasMany
  createdAt: AWSDateTime!
  lastModified: AWSDateTime
  likes: Int!
  dislikes: Int!
  quality: Float!
  username: String!
  parentId: ID @index(name: "byParent", queryField: "categoryByParent")
  children: [Comment] @hasMany(indexName: "byParent", fields: ["id"])
}

A comment is the main node. It has a many-to-one relationship with Thread. A comment, self-references itself to create a tree structure. It has a one-to-many relationship with itself to form replies. A comment can have multiple reactions i.e are User Reaction i.e like or dislike. It also has a username field which is used to display the username of the user who created the comment. It excludes the need of extra user table as only username is required to display the user who created the comment.

type Reaction
  @model
  @auth(
    rules: [
      { allow: owner, ownerField: "owner", operations: [create, update, read] }
    ]
  ) {
  id: ID!
  vote: Int!
  comment: Comment @belongsTo
}

Reaction is used to store the user reaction i.e like or dislike. It has a many to one relationship with Comment. A comment can have multiple reactions. Also it can only be read, create or updated by the owner i.e the user who created the reaction.

Reddit Inspired Commenting System ๐Ÿ“ (Future Work)

  1. Reddit has a great commenting system that allows users to comment on posts and reply to other comments. It also allows users to upvote and downvote comments. I wanted to implement a similar open-source commenting system so that other developers can use it in their projects.

  2. The sorting can be achieved by a lambda function. The lambda function will be triggered when a comment reacted. It will calculate the Wilson score and update the comment. The Wilson score is calculated using the following formula.

     /**
      * Calculate the Wilson score interval for a given upvote and downvote count.
      * 
      * @param upvotes   The number of upvotes
      * @param downvotes The number of downvotes
      * @return The Wilson score interval
      */
     private double getWilsonScore(Long upvotes, Long downvotes) {
         double n = upvotes + downvotes;
         if (n == 0) {
             return 0;
         }
         double z = 1.96; // 95% confidence interval
         double phat = (double) upvotes / n;
         double score = (phat + z * z / (2 * n) - z * Math.sqrt((phat * (1 - phat) + z * z / (4 * n)) / n))
                 / (1 + z * z / n);
         return (score * 2) - 1; // Normalize the score between -1 and 1
     }
    
  3. Using this Wilson score and date of creation, I can sort the comments in descending order.

Conclusion ๐Ÿš€

Thanks to AWS Amplify and Hashnode for this opportunity. I am now more confident in aws services and I will be using them in my future projects.

I enjoyed creating a full-stack project with AWS Amplify

Note:- If after login it shows blank, just refresh the page.

21
Subscribe to my newsletter

Read articles from Chirag Padyal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Chirag Padyal
Chirag Padyal