Study-Talk is an online website that contains 4 different pages each with their own unique features:
First webpage called the Study Groups page allows students to study together by joining online video call study groups, track time studied by an individual, users can also track their time on a leaderboard with the students with the most amount of hours studied in a day and in a week being awarded medals. Users can also view rooms that have been created and set as public by the room creator. While creating the room, the host can set the maximum number of participants allowed in their room, whether the participants should have their mics on or off, same with camera and also whether the room should be displayed publicly on the webpage to allow random strangers to join.
Second webpage access by clicking the Read Confessions option on the meetups page allows students all over the world to make confessions post about the various activities they have done while at college, press the believers button if a student believes the confession or the non believer button if they do not believe the post, make comments, share posts on various other platforms like Facebook, whatsapp or twitter, save a post and even report it if user feels as though it goes against the policies governed by the website. The webpage also has a section to display the hottest post of the week, filter posts by universities, save post and also view posts the user has made in the past.
Third webpage accessed by clicking the compete button allows users to join a random video call, create a video call or join a certain video call. However, it differs from the first page as this one allows users to compete by answering questions on various topics like minecraft to calculus in a video call environment allowing users to rank each other according to how many correct answers they achieved at the end of the quiz. This was inspired by Kahoot, an online quiz platform. However, Kahoot doesn't have video call implementation so I decided to implement my improved version of it. While making the video room, hosts can choose the topics the questions will be derived from, or even make their own questions. In addition, they can choose the time each participant is allowed to answer each question, how many questions will be asked, whether the participants mics should be on or off, whether the participants camera should be on or off, as well as whether the video call should be publicly accessible to other strangers or not.
The last webpage can be accessed by clicking the Talk button. This is an omegle styled video call which allows students to talk to random other students currently on the website. This works by using Redis' extremely low latency tech stack as well as docker containerisation with a separated socket-io server running to power this page.
This is an implementation I am overwhelmingly proud of as I had to learn to implement a serverless pipeline using prisma, Next.js as well as implementing a separate websocket server using socket-io dockerized with redis for very fast caching.















My most proudest achievement is the user reputation system which was implemented on the confesssions posts. The reputation system led me to learn about the different ways social media websites create strong and robust algorithms. It is designed to distinguish quality users from spam bots and improve content quality on the confession platform. It uses multiple factors to calculate a comprehensive reputation score and detect suspicious activity patterns.
- Activity Score (25%): Account age, confession count, voting activity, recent engagement
- Quality Score (35%): Average votes received, positive vote ratio, comment engagement, content length
- Trust Score (40%): Report history, account verification, consistent activity, suspicious pattern detection
- Activity Rate Analysis: Detects rapid posting patterns
- Content Repetition: Identifies duplicate or similar content
- Timing Patterns: Detects unnatural posting intervals
- Engagement Analysis: Flags accounts with no community interaction
- Suspicious Patterns: Identifies generic content and short posts
- NEW_USER: Default for new accounts
- VERIFIED: Users with reputation > 200
- TRUSTED: Users with reputation > 500
- SUSPICIOUS: Users with bot probability > 70%
Level | Score Range | Description |
---|---|---|
LEGENDARY | 800+ | Top contributors, highly trusted |
EXPERT | 600-799 | Experienced, reliable users |
TRUSTED | 400-599 | Verified, active community members |
ACTIVE | 200-399 | Regular contributors |
REGULAR | 100-199 | Established users |
NEW | 0-99 | New or low-activity users |
model User {
// Reputation fields
reputationScore Int @default(0)
activityScore Int @default(0)
qualityScore Int @default(0)
trustScore Int @default(0)
// Activity tracking
lastActivityAt DateTime?
dailyConfessionCount Int @default(0)
dailyVoteCount Int @default(0)
dailyCommentCount Int @default(0)
// Bot detection
botProbability Int @default(0)
isFlagged Boolean @default(false)
verificationLevel String @default("NEW_USER")
// Audit trail
reputationHistory ReputationHistory[]
}
model ReputationHistory {
id String @id @default(auto()) @map("_id") @db.ObjectId
userId String
changeType String
changeAmount Int
reason String
previousScore Int
newScore Int
createdAt DateTime @default(now())
}
Calculates comprehensive reputation score based on:
- Activity patterns
- Content quality metrics
- Community trust indicators
- Bot detection analysis
Tracks user activity and triggers reputation recalculation every 10 actions.
Analyzes user behavior for suspicious patterns:
- High activity rates (>2 confessions/hour)
- Repetitive content detection
- Unnatural timing patterns
- No engagement flags
const activityRate = user.confessions.length / accountAgeHours;
if (activityRate > 2) {
botScore += 30; // High activity penalty
}
// Check for duplicate titles and content
const duplicateTitles = titles.filter((title, index) =>
titles.indexOf(title) !== index
).length;
// Detect too-regular intervals (bot-like behavior)
const regularIntervals = intervals.filter(interval =>
interval > 5000 && interval < 15000
).length;
// Check for generic content and short posts
const genericTitles = user.confessions.filter(c =>
c.title.toLowerCase().includes('test') ||
c.title.toLowerCase().includes('hello')
).length;
- Account Age: 1 point per day (max 365)
- Confession Activity: 5 points per confession
- Voting Activity: 1 point per vote
- Comment Activity: 2 points per comment
- Recent Activity: 3 points per confession in last 7 days
- Average Votes: 10 points per average vote received
- Positive Ratio: Up to 200 points for 100% positive votes
- Comment Engagement: 15 points per average comment received
- Content Length: Up to 50 points for longer content
- No Reports: 100 points bonus
- Account Verification: 50 points bonus
- Consistent Activity: 50 points bonus
- No Suspicious Patterns: 100 points bonus
Displays user reputation and verification status with tooltips showing detailed metrics.
<UserReputationBadge
userId={user.id}
showDetails={true}
/>
- LEGENDARY: Purple
- EXPERT: Blue
- TRUSTED: Green
- ACTIVE: Yellow
- REGULAR: Orange
- NEW: Gray
- Confession Creation: Triggers activity monitoring
- Voting: Updates reputation every 10 votes
- Commenting: Tracks engagement patterns
- Background Processing: Periodic recalculation
GET /api/user/reputation/[id]
: Get user reputation data- Integrated with existing confession and voting APIs
- Quality Content: Reputation encourages better contributions
- Community Trust: Users can identify reliable sources
- Recognition: Achievement system for active contributors
- Spam Prevention: Bot detection reduces low-quality content
- Content Quality: Reputation incentivizes better posts
- Community Health: Trust indicators improve user experience
- Automated Flagging: Suspicious users are automatically flagged
- Audit Trail: Complete history of reputation changes
- Risk Assessment: Bot probability helps identify problematic accounts
- Monitor flagged users for manual review
- Check reputation distribution for anomalies
- Review bot detection accuracy
- Analyze reputation trends
- Adjust scoring weights if needed
- Review false positive/negative rates
- Comprehensive reputation audit
- Update detection algorithms
- Performance optimization
- Average Reputation Score: Platform health indicator
- Bot Detection Rate: Effectiveness of spam prevention
- Reputation Distribution: User engagement levels
- False Positive Rate: Accuracy of bot detection
- High bot probability users (>70%)
- Rapid reputation changes
- Suspicious activity patterns
- System performance issues
- Reputation Decay: Scores decrease over inactivity
- Community Moderation: User-powered reputation adjustments
- Advanced Bot Detection: Machine learning-based detection
- Reputation Marketplace: Gamification elements
- Real-time Updates: Live reputation score changes
- Reputation Challenges: User engagement activities
- Reputation Transfer: Legacy account benefits
- Reputation Insurance: Protection against false flags
# Clone the main repository
git clone https://github.com/yourusername/study-talk.git
# Navigate to project directory
cd study-talk
# Verify you're in the correct directory
ls -la
Create a .env
file in the root directory with the following variables:
# Database Configuration
DATABASE_URL="mongodb+srv://username:password@cluster.mongodb.net/study-talk?retryWrites=true&w=majority"
# Authentication (Kinde)
KINDE_CLIENT_ID="your_kinde_client_id"
KINDE_CLIENT_SECRET="your_kinde_client_secret"
KINDE_ISSUER_URL="https://your-domain.kinde.com"
KINDE_SITE_URL="http://localhost:3000"
KINDE_POST_LOGOUT_REDIRECT_URL="http://localhost:3000"
KINDE_POST_LOGIN_REDIRECT_URL="http://localhost:3000"
# Stream Configuration
STREAM_API_KEY="your_stream_api_key"
STREAM_API_SECRET="your_stream_api_secret"
# Redis Configuration
REDIS_URL="redis://localhost:6379"
# WebSocket Server
WEBSOCKET_SERVER_URL="http://localhost:3001"
# Stripe (for premium features)
STRIPE_SECRET_KEY="sk_test_your_stripe_secret_key"
STRIPE_WEBHOOK_SECRET="whsec_your_webhook_secret"
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_your_stripe_publishable_key"
# Email Service (SendGrid)
SENDGRID_API_KEY="your_sendgrid_api_key"
FROM_EMAIL="noreply@studytalk.com"
# Security
JWT_SECRET="your_jwt_secret_key_here"
NEXTAUTH_SECRET="your_nextauth_secret_here"
NEXTAUTH_URL="http://localhost:3000"
Required Service Setups:
MongoDB Atlas:
- Go to MongoDB Atlas
- Create a free account and new cluster
- Create a database user with read/write permissions
- Get your connection string and replace in DATABASE_URL
- Add your IP address to the IP Access List
Stream Account:
- Visit GetStream.io
- Create a new app for video calling
- Copy your API Key and Secret from the dashboard
- Configure video calling settings in your Stream dashboard
Kinde Authentication:
- Go to Kinde.com
- Create a new application
- Configure OAuth settings and redirect URLs
- Copy your Client ID, Secret, and Issuer URL
# Start Redis container
docker run -d \
--name study-talk-redis \
-p 6379:6379 \
redis:7-alpine
# Verify Redis is running
docker ps
# Test Redis connection
docker exec -it study-talk-redis redis-cli ping
# Should return "PONG"
# Optional: Persist Redis data
docker run -d \
--name study-talk-redis \
-p 6379:6379 \
-v redis_data:/data \
redis:7-alpine
# Install Node.js dependencies
npm install
# Install additional development dependencies
npm install -D @types/node @types/react @types/react-dom
# Verify installation
npm list --depth=0
# Generate Prisma client
npx prisma generate
# Push database schema to MongoDB
npx prisma db push
# Optional: Seed initial data
npm run seed
# Verify database connection
npx prisma studio
# Start the main Next.js application
npm run dev
# In a separate terminal, start the WebSocket server
cd websocket
npm install
npm run dev
# Verify both servers are running
# Main app: http://localhost:3000
# WebSocket: http://localhost:3001