Shipped
StudentSphere
Campus platform unifying a marketplace, study materials and a social feed
- My role
- Sole engineer — data model, payments integration, real-time features
- Timeline
- 2025 — 2026
- Team
- Solo
Outcome
- 3-in-1
- marketplace, materials and feed behind one login
- Stripe
- settled peer-to-peer transactions, no card data held
- Unified
- moderation across every content type
- MERN
- end-to-end ownership of the full stack
Context
Campus life is distributed across a dozen tools that do not speak to one another: coordination in group chats, academic questions on notice boards, and second-hand textbook sales wherever someone happened to post. Nothing is searchable, nothing is moderated, and everything is lost at the end of term.
The problem
- Three genuinely distinct products — a marketplace, a study-material library and a social feed — have to share one identity and permission model without fragmenting into three disconnected applications.
- Real money moves between students who have no prior relationship, so the platform needs a trusted intermediary rather than an honour system.
- Anything user-generated on a campus requires moderation tooling from the outset rather than after the first incident.
- Participation is seasonal and highly peaked around term dates, so the system has to degrade gracefully rather than assume steady traffic.
How I approached it
One identity across three surfaces
A single user model carries membership, reputation and role across the marketplace, the material library and the feed, so a student signs in once and permissions compose rather than duplicate.
Administrative capability is expressed as a role on that same model, which means moderation tooling operates uniformly across all three surfaces instead of requiring a separate back office per feature.
Stripe as the trust layer for peer-to-peer sale
Rather than building payment handling — and thereby holding card data — the marketplace delegates settlement to Stripe. Students transact through a processor they already recognise, and the application never touches raw payment details.
That decision removed PCI scope entirely and, more importantly, removed the question of whether two strangers should trust a student project with their card.
Real-time where it changes behaviour, and nowhere else
Socket.io backs the interactions where latency actually alters what a user does — conversations and feed activity — while the material library and marketplace listings remain ordinary cached reads.
Deciding that per-surface rather than globally kept the connection count proportional to genuine need instead of to page count.
Moderation as a first-class surface
Reporting, review and removal are built against the shared content model rather than per feature, so a new content type inherits moderation instead of requiring its own.
Administrative actions are recorded, which matters on a campus where a removal decision may later need to be explained.
Architecture
Surfaces
- Marketplace
- Study materials
- Social feed
Shared spine
- One user & role model
- Shared content model
Application
- Express REST API
- Role-based middleware
- Socket.io (selective)
Data
- MongoDB — users, listings, materials, posts, reports
External
- Stripe Checkout
Cross-cutting
- Moderation & administrative action log across every content type
- Frontend
- React SPA · shared authentication context across all three modules
- Backend
- Node.js + Express REST API · role-based middleware
- Realtime
- Socket.io, membership-gated, scoped to conversations and feed activity
- Database
- MongoDB — users, listings, materials, posts, orders, reports
- Payments
- Stripe Checkout — the application stores no card data
- Moderation
- Administrative role with cross-module oversight and an action log
Trade-offs I chose
Delegating payments to Stripe rather than building them
WhyHandling card data would have introduced PCI scope and a trust problem no student project can credibly solve. This was the clearest build-versus-buy call in the project.
One shared user model instead of per-module accounts
WhyThree separate account systems would have tripled the authentication surface and made consistent moderation effectively impossible.
Real-time applied selectively rather than universally
WhyA live connection per surface is a cost paid continuously. Restricting it to interactions where latency genuinely changes behaviour kept that cost proportionate.
What I took away
- The difficult part of a multi-module product is the shared spine — identity and permissions — rather than any individual feature.
- Choosing not to build payments was the highest-leverage decision in the project, and it took the least time.
- Building moderation against a shared content model meant later content types cost almost nothing to govern.
Stack
- React
- Express
- Node.js
- MongoDB
- Socket.io
- Stripe