Skip to content

samir-ouaammou/Transcendence

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

229 Commits
 
 
 
 
 
 

Repository files navigation

This project has been created as part of the 42 curriculum by Samir, Abderrahim, Youssef, Samia, Amal.

PinSpace Logo

PinSpace

A full-stack Pinterest-inspired creative social platform

Next.js TypeScript Tailwind CSS Prisma PostgreSQL Socket.io Docker ELK Stack


Table of Contents


Overview

PinSpace is a feature-rich, production-ready social platform built as a team project. Inspired by Pinterest, it lets users discover, create, and share visual content ("pins") organized into curated boards. Beyond content sharing, PinSpace includes a full social graph (followers, friends), real-time private messaging, live notifications, OAuth 2.0 login, two-factor authentication, a secured public API, and a complete DevOps observability stack powered by the ELK suite.

The entire application runs in a single Next.js process — the API routes serve as the backend, server components leverage SSR for SEO, and a custom Socket.io server layered on top of the Next.js HTTP server powers all real-time features.


Features

Core Content

Feature Description
Pins Create, view, like, comment, and tag image-based posts with optional links and descriptions
Boards Organise pins into named collections; manage and delete boards
Feed Personalised, paginated home feed based on who you follow
Search Advanced search with filters, sorting, and pagination
File Upload Upload and manage images via Vercel Blob Storage

Social

Feature Description
Follow system Follow/unfollow any user; followers & following counts on profiles
Friend system Send, accept, and remove friend requests (PENDING → ACCEPTED)
User profiles Public profiles with cover image, bio, website, pins, and boards
Direct messaging Real-time 1-to-1 conversations with read receipts and unread counts

Authentication & Security

Feature Description
Email/Password auth Register, login, email verification, forgot/reset password
OAuth 2.0 One-click sign-in with Google, GitHub (and 42 School)
Two-Factor Auth (2FA) TOTP-based 2FA with QR code setup and toggle in settings
Custom JWT HTTP-only cookie-based JWT for session management
API Key auth Secured public API access using generated API keys with rate limiting
Account management Change email, change password, delete account

Real-time

Feature Description
Live notifications Instant alerts for likes, comments, friend requests, follows
Online presence See which users are online/offline in real time
Real-time messaging Messages and read-receipts delivered instantly over WebSocket
Sidebar updates Conversation sidebar refreshes live on new messages

Infrastructure & Observability

Feature Description
ELK Stack Structured JSON logs shipped from the app → Logstash → Elasticsearch → Kibana
ILM policy Automatic log rotation (7-day rollover, 30-day deletion)
Health checks Status page and automated backup/disaster-recovery procedures
Docker Compose One-command spin-up of app, PostgreSQL, Elasticsearch, Logstash, and Kibana
SSR Every page is server-rendered for fast initial load and SEO

Tech Stack

Layer Technology
Framework Next.js 16 (App Router, SSR, API Routes)
Language TypeScript 5
Styling Tailwind CSS 4 + shadcn/ui components
ORM Prisma 7
Database PostgreSQL 14
Real-time (server) Socket.io 4
Real-time (push) Pusher
Authentication Custom JWT + NextAuth.js 4 (OAuth)
2FA Speakeasy + QRCode
Email Resend
File Storage Vercel Blob
Validation Zod 4
Logging Custom Logstash logger → Elasticsearch 8.11 → Kibana 8.11
Containerisation Docker + Docker Compose

Architecture

┌────────────────────────────────────────────────────────────┐
│                        Browser Client                      │
│          Next.js App Router  ·  Socket.io-client           │
└─────────────┬───────────────────────────┬──────────────────┘
              │  HTTP / SSR               │  WebSocket
              ▼                           ▼
┌────────────────────────────────────────────────────────────┐
│               Node.js / Next.js Server  (port 3000)        │
│                                                            │
│  ┌──────────────────┐   ┌──────────────────────────────┐   │
│  │  Next.js Handler │   │     Socket.io Server         │   │
│  │  (API Routes +   │   │  • online presence           │   │
│  │   SSR pages)     │   │  • messaging events          │   │
│  └────────┬─────────┘   │  • like/comment/follow notif │   │
│           │             │  • friend-request notif      │   │
│           │             └──────────────┬───────────────┘   │
│           │                            │                   │
│  ┌────────▼────────────────────────────▼───────────────┐   │
│  │                   Prisma ORM                        │   │
│  └────────────────────────┬────────────────────────────┘   │
│                           │                                │
│  ┌────────────────────────▼─────────────────────────────┐  │
│  │         Logstash Logger  →  TCP :5044                │  │
│  └──────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────┘
              │                             │
              ▼                             ▼
     ┌────────────────┐           ┌──────────────────────┐
     │  PostgreSQL 14 │           │  Logstash 8.11       │
     └────────────────┘           │    → Elasticsearch   │
                                  │    → Kibana          │
                                  └──────────────────────┘

Directory Structure

Transcendence/
├── Project/                       # Application root
│   ├── app/
│   │   ├── (frontend)/            # All UI routes (Next.js App Router)
│   │   │   ├── (auth)/            # Login, Register, 2FA, Forgot/Reset password
│   │   │   └── feed/              # Protected app pages
│   │   │       ├── page.tsx       # Home feed
│   │   │       ├── pin/[id]/      # Pin detail page
│   │   │       ├── board/[id]/    # Board detail page
│   │   │       ├── profile/       # User profiles
│   │   │       ├── message/       # Real-time messaging
│   │   │       ├── notifications/ # Notification centre
│   │   │       └── settings/      # Account, 2FA, privacy settings
│   │   └── api/                   # REST API route handlers
│   │       ├── auth/              # Auth endpoints (login, register, 2FA, OAuth)
│   │       ├── pins/              # Pin CRUD
│   │       ├── boards/            # Board CRUD
│   │       ├── chat/              # Conversations & messages
│   │       ├── friends/           # Friend requests & relations
│   │       ├── notifications/     # Notification fetch & cleanup
│   │       ├── public/            # API-key-secured public endpoints
│   │       └── user/              # User update, email, password, delete
│   ├── components/                # Shared React components
│   ├── lib/                       # Utility modules (JWT, Prisma, Pusher, OAuth…)
│   ├── hooks/                     # Custom React hooks
│   ├── prisma/
│   │   └── schema.prisma          # Full database schema
│   ├── devops/
│   │   ├── logstash/pipeline/     # Logstash pipeline config
│   │   └── setup-elk.sh           # ELK bootstrap script (ILM, index template, Kibana)
│   ├── server.js                  # Custom HTTP + Socket.io server
│   ├── otel-config.js             # Logstash structured logger
│   ├── docker-compose.yml         # Full stack orchestration
│   └── Dockerfile                 # Multi-stage production image
└── Subject/
    └── subject.pdf                # Project specification

Database Schema

The Prisma schema defines 14 models covering the full data domain:

Model Purpose
User Core user identity, profile, 2FA, online status
Account OAuth provider accounts linked to a user
Session NextAuth sessions
VerificationToken Email verification tokens
ResetPasswordToken Password reset tokens
Pin User-created image posts with tags
Board Named collections of pins
Like User ↔ Pin likes (unique constraint)
Comment User comments on pins
LikeComment Likes on comments (unique constraint)
Friendship Bidirectional friend requests (PENDING / ACCEPTED)
Follow Unidirectional follow relationships
Conversation + ConversationParticipant Private messaging threads
Message Individual chat messages with read status
Notification Typed notifications (LIKE, COMMENT, FRIEND_REQUEST, etc.)

Repository Structure

The repository contains two top-level folders:

  • Project: main application
  • Subject: project subject/resources

Getting Started

  1. Clone the repository:
git clone https://github.com/samir-ouaammou/Transcendence.git
  1. Enter the application folder:
cd Transcendence/Project
  1. Use the Makefile commands below to manage the application and Docker environment.

Using Makefile

Recommended usage for the local environment:

  • make up - Start the Docker Compose stack in detached mode.
  • make up-build - Build the images and start the stack in detached mode.
  • make down - Stop the stack and remove the Compose volumes.
  • make restart - Stop the stack and start it again.
  • make force-restart - Stop and remove all containers, then start the stack again.
  • make docker-clean - Remove all local containers, volumes, and images.
  • make clean - Run a full Docker system prune with volumes.
  • make reset - Run the full reset workflow defined in the Makefile.

Environment Variables

Copy .env.example to .env and populate every value:

# ── Database ──────────────────────────────────────────────────
POSTGRES_USER=your_postgres_user
POSTGRES_PASSWORD=your_postgres_password
POSTGRES_DB=your_postgres_db
DATABASE_URL=postgresql://user:password@localhost:5432/dbname

# ── Auth ──────────────────────────────────────────────────────
AUTH_SECRET=your_auth_secret
JWT_SECRET=your_jwt_secret               # signs custom JWT cookies
NEXTAUTH_SECRET=your_nextauth_secret     # signs NextAuth sessions
NEXTAUTH_URL=http://localhost:3000
AUTH_TRUST_HOST=http://localhost:3000
DOMAIN=http://localhost:3000

# ── OAuth Providers ───────────────────────────────────────────
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret

# ── Storage ───────────────────────────────────────────────────
BLOB_READ_WRITE_TOKEN=your_vercel_blob_token

# ── Email ─────────────────────────────────────────────────────
RESEND_API_KEY=your_resend_api_key

# ── Realtime (Pusher) ─────────────────────────────────────────
PUSHER_APP_ID=your_pusher_app_id
PUSHER_APP_SECRET=your_pusher_app_secret
NEXT_PUBLIC_PUSHER_APP_KEY=your_pusher_app_key
NEXT_PUBLIC_PUSHER_CLUSTER=your_pusher_cluster

# ── ELK Stack ─────────────────────────────────────────────────
ELASTICSEARCH_HOSTS=http://elasticsearch:9200
KIBANA_HOST=http://kibana:5601

API Reference

All routes are under /api. Protected routes require a valid jwtToken HTTP-only cookie (or Authorization: Bearer <api-key> for public endpoints).

Auth

Method Route Description
POST /api/auth/register Create a new account
POST /api/auth/login Login and receive JWT cookie
GET /api/auth/me Get the authenticated user
POST /api/auth/verify Verify email address
POST /api/auth/forgot-password Send reset-password email
POST /api/auth/reset-password Set a new password via token
GET/POST /api/auth/[...nextauth] NextAuth OAuth endpoints
POST /api/auth/2fa/generate Generate TOTP secret + QR code
POST /api/auth/2fa/verify Verify a TOTP code
POST /api/auth/2fa/toggle Enable or disable 2FA

Pins & Boards

Method Route Description
GET/POST /api/pins List / create pins
GET /api/feed Personalised feed
GET/POST /api/boards List / create boards
DELETE /api/boards/[id]/delete_board Delete a board
GET /api/boards/[id]/pins List pins in a board

Social

Method Route Description
POST /api/like Toggle like on a pin
POST /api/comment Add a comment
POST /api/likeComment Toggle like on a comment
GET/POST /api/friends List friends / send request
POST /api/friends/accept Accept a friend request
POST /api/friends/follow Follow a user
DELETE /api/friends/remove Remove friend / unfollow

Messaging

Method Route Description
GET /api/chat/conversations List conversations
GET /api/chat/conversations/create-or-get/[friendId] Get or create DM thread
GET/POST /api/chat/messages/[id] Fetch / send messages
GET /api/chat/unread-count Unread message count

Notifications

Method Route Description
GET /api/notifications List notifications
GET /api/notifications/count Unread notification count
DELETE /api/notifications/cleanup Delete read notifications

Public API (API-key secured, rate-limited)

Method Route Description
GET /api/public/pins Browse public pins

DevOps & Observability

Logging Pipeline

Every server event (connections, messages, likes, friend requests, errors) is emitted as structured JSON to a custom Logstash logger (otel-config.js). Logs are sent over TCP to Logstash on port 5044, indexed in Elasticsearch, and visualised in Kibana.

App (JSON over TCP) → Logstash :5044 → Elasticsearch :9200 → Kibana :5601

Log fields: timestamp, level (INFO | WARN | ERROR), message, plus arbitrary attributes (userId, socketId, conversationId…).

Index Lifecycle Management

The setup-elk.sh bootstrap script configures:

  • ILM policy — roll over after 7 days or 5 GB; delete after 30 days
  • Index templatelogs-* pattern with typed field mappings
  • Kibana index pattern — auto-created for immediate dashboard use

Health & Recovery

  • All Docker containers are configured with restart: unless-stopped
  • PostgreSQL data is persisted in a named volume (postgres_data)
  • Elasticsearch data is persisted in a named volume (elasticsearch_data)
  • The elk-setup service waits for both Elasticsearch and Kibana to be healthy before applying configuration

Team Contributions

This project was built collaboratively. Each feature was assigned to one or more team members.

Member Contributions
Samir Complete user management system covering authentication and authorization, including registration, login, email verification, password reset, profile updates, account management, OAuth 2.0 integration (Google, GitHub, 42 School), and a full Two-Factor Authentication (2FA) workflow.
Abderrahim Real-time collaborative features, advanced search with filters / sorting / pagination, file upload & management system, SSR integration, user interaction flows
Samia Real-time features (WebSockets / Socket.io), user-to-user interaction flows, notification system (create / update / delete events)
Amal Real-time features, public API with secured API key + rate limiting, ORM setup (Prisma), user interaction flows, SSR integration
Youssef DevOps — ELK stack (Elasticsearch, Logstash, Kibana) for log management

Score breakdown (project spec): Web features — 14 pts · Accessibility & i18n — 1 pt · User Management — 4 pts · DevOps — 4 pts · Total: 23 pts


Project Rules

These conventions were adopted to keep the codebase consistent across the team:

Git Workflow

  • All work happens on feature branches (feature/<name>, fix/<name>, devops/<name>)
  • Pull requests are mandatory before merging into main — no direct pushes
  • Every PR requires at least one review from another team member before merging
  • Commit messages follow the Conventional Commits format: feat:, fix:, chore:, docs:, style:, refactor:, test:

Code Standards

  • All code is written in TypeScriptany types are forbidden unless strictly necessary
  • Zod schemas are used for all API input validation
  • API routes must always return typed JSON responses and use correct HTTP status codes
  • Database access goes exclusively through the Prisma client — raw SQL is not allowed
  • Secrets and credentials are stored in .env only — never hard-coded or committed

Architecture Rules

  • Frontend pages live under app/(frontend)/; API handlers live under app/api/
  • Reusable logic (auth, database, utilities) belongs in the lib/ directory
  • Shared UI components live in components/; page-local components stay co-located with their route
  • Real-time events are handled by the custom Socket.io server in server.js

Environment & Deployment

  • The .env.example file must be kept up to date whenever a new environment variable is added
  • The application must run cleanly with docker compose up --build without manual steps
  • All services must start and pass health checks before the app is considered ready

System-Wide Interaction Graph

flowchart LR
  subgraph Client[Client Layer]
    U1[Guest User]
    U2[Authenticated User]
    FE[Next.js Frontend<br/>App Router + React]
    WSClient[Socket.io Client]
    U1 --> FE
    U2 --> FE
    FE --> WSClient
  end

  subgraph App[Application Layer]
    SSR[SSR + Server Components]
    API[Route Handlers<br/>/api/*]
    AUTH[Auth Services<br/>JWT + NextAuth + 2FA]
    SOCIAL[Social Services<br/>Pins/Boards/Friends/Follows]
    CHAT[Chat Services<br/>Conversations/Messages]
    NOTIF[Notification Services]
    PUBLICAPI[Public API<br/>/api/public/pins]
    RATE[API Key Validation + Rate Limit]

    FE --> SSR
    FE --> API
    API --> AUTH
    API --> SOCIAL
    API --> CHAT
    API --> NOTIF
    API --> PUBLICAPI
    PUBLICAPI --> RATE
  end

  subgraph Realtime[Real-time Layer]
    WSServer[Socket.io Server<br/>Project/server.js]
    PRESENCE[Online Presence]
    RTCHAT[Live Messaging]
    RTSOCIAL[Live Social Notifications]

    WSClient <--> WSServer
    WSServer --> PRESENCE
    WSServer --> RTCHAT
    WSServer --> RTSOCIAL
  end

  subgraph Data[Data Layer]
    PRISMA[Prisma ORM]
    DB[(PostgreSQL 14)]
    API --> PRISMA
    CHAT --> PRISMA
    SOCIAL --> PRISMA
    AUTH --> PRISMA
    PRISMA --> DB
  end

  subgraph External[External Integrations]
    OAUTH[OAuth Providers<br/>Google/GitHub]
    RESEND[Resend Email]
    BLOB[Vercel Blob Storage]
    PUSHER[Pusher]

    AUTH --> OAUTH
    AUTH --> RESEND
    SOCIAL --> BLOB
    NOTIF --> PUSHER
  end

  subgraph Obs[Observability]
    LOGGER[Structured Logger<br/>otel-config.js]
    LOGSTASH[Logstash :5044]
    ES[Elasticsearch :9200]
    KIBANA[Kibana :5601]

    API --> LOGGER
    WSServer --> LOGGER
    LOGGER --> LOGSTASH --> ES --> KIBANA
  end
Loading

Database Visualization

erDiagram
  User ||--o{ Board : creates
  User ||--o{ Pin : creates
  Board ||--o{ Pin : contains

  User ||--o{ Like : gives
  Pin  ||--o{ Like : receives

  User ||--o{ Comment : writes
  Pin  ||--o{ Comment : has
  Comment ||--o{ Comment : replies_to

  User ||--o{ LikeComment : gives
  Comment ||--o{ LikeComment : receives

  User ||--o{ Follow : follower
  User ||--o{ Follow : following

  User ||--o{ Friendship : friendA
  User ||--o{ Friendship : friendB
  User ||--o{ Friendship : requestedBy

  Conversation ||--o{ ConversationParticipant : has
  User ||--o{ ConversationParticipant : joins

  Conversation ||--o{ Message : has
  User ||--o{ Message : sends

  User ||--o{ Notification : receives
  User ||--o{ Notification : sends
  Pin  ||--o{ Notification : references

  User ||--o{ Account : owns
  User ||--o{ Session : owns
Loading

Relationship Notes

  • A user can own multiple boards and pins.
  • Pins can optionally belong to a board.
  • Like and LikeComment enforce uniqueness across (userId, targetId) pairs.
  • Friendships are tracked with status transitions (PENDING, ACCEPTED).
  • Conversations are many-to-many with users through ConversationParticipant.
  • Notifications uniquely combine user, sender, type, and optional relation context.

Conclusion

PinSpace is a complete ft_transcendence delivery that combines modern full-stack engineering, social product design, real-time communication, secure identity management, and operational observability in a single cohesive platform.

The project reflects strong collaborative execution across architecture, frontend, backend, realtime systems, and DevOps, and provides a solid foundation for continued product hardening and feature expansion.

About

PinSpace is a full-stack web application built as part of the ft_transcendence project at 1337 Coding School (42 Network), featuring a Pinterest-inspired platform where users can share content, interact in real time, and engage through modern social features.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors