Episode 42 membangun platform social media: user profiles dan relationships, post creation dengan media upload, komentar dan reaksi, following-followers, timeline feed dengan pagination, notifikasi real-time, chat, hashtag, hingga strategi performa feed di skala besar.

Project kedua di fase real-world: platform social media dengan fitur lengkap dan real-time. Ini adalah salah satu tipe aplikasi paling menantang karena kombinasi data sosial kompleks, media upload, feed berskala besar, dan notifikasi instan.
Episode 42 membangunnya lapis demi lapis: fitur sosial inti, fitur real-time, fungsionalitas lanjutan, dan strategi performa untuk feed.
Model relasi sosial di Prisma:
model User {
id Int @id @default(autoincrement())
username String @unique
displayName String
avatarUrl String?
followers Follow[]
following Follow[]
}
model Follow {
followerId Int
followingId Int
createdAt DateTime @default(now())
@@id([followerId, followingId])
}Relationship mengikuti polanya: Follow sebagai join table dengan composite primary key. Query followers dan following memakai pagination (episode 12) karena bisa berjumlah besar.
Post dengan media memakai file upload (episode 17):
type Mutation {
createPost(input: CreatePostInput!, media: [Upload!]): Post!
}
input CreatePostInput {
body: String!
hashtags: [String!]
}Media diupload ke object storage (S3), dan URL-nya disimpan di post. Validasi tipe dan ukuran file diterapkan sebelum upload — sesuai checklist keamanan episode 17.
Komentar adalah tree (komentar bisa membalas komentar), dan reaksi memakai enum:
type Comment {
id: ID!
body: String!
parent: Comment
replies: CommentConnection!
}
enum ReactionType {
LIKE
LOVE
LAUGH
SAD
ANGRY
}
type Reaction {
type: ReactionType!
count: Int!
}Komentar bertingkat dibatasi kedalamannya untuk performa; reaksi di-agregat dengan query group by.
Live notifications memakai subscription per user:
type Subscription {
notificationReceived: Notification!
}async function notifyUser(userId, notification) {
await pubsub.publish(`NOTIFICATION:${userId}`, { notificationReceived: notification });
}Online presence memakai pola presence dari episode 38: status online di-publish dan didengarkan user lain yang relevan.
Real-time chat memakai topik per room (episode 16). Live comment updates bisa memakai subscription per post — setiap komentar baru dipublish ke topik post tersebut. Untuk lalu lintas tinggi, batasi frekuensi atau agregasi singkat (misalnya update tiap beberapa detik).
isPrivate di user — post hanya terlihat follower yang disetujui.type Query {
hashtag(tag: String!, first: Int!, after: String): PostConnection!
}Penerapan privacy memakai data filtering (episode 14): resolver feed menyaring post berdasarkan isPrivate dan relasi follow — user tidak boleh melihat konten privat orang yang bukan follower.
Feed adalah masalah klasik social media. Strategi yang umum:
const followers = await ctx.db.follows.findMany({ where: { followingId: userId } });
for (const f of followers) {
await ctx.redis.lpush(`feed:${f.followerId}`, postId);
}Pilih strategi sesuai skala; mulai dari fan-out on read yang sederhana, lalu evolusi.
LPUSH feed:123 postId pada pola feed.authorId, createdAt, dan join table.Feed yang dipaginasi dengan cursor (episode 12) dikombinasikan dengan cache membuat scroll pengalaman terasa mulus.
Inti yang harus dibawa pulang:
Di episode 43 selanjutnya kalian akan mempelajari proyek multi-tenant SaaS — arsitektur multi-tenancy dengan database per tenant versus shared, tenant context propagation, manajemen organisasi dengan undangan dan role, billing dengan Stripe subscriptions, hingga fitur enterprise seperti SSO dan audit logs. Aplikasi SaaS enterprise kalian akan siap!