Back to projects

Case study / 03

Loop

One trusted student network for the everyday logistics of campus life.

Loop brings rides, marketplace listings, study groups, and context-linked conversation previews into one authenticated Waterloo student network. A shared relational model connects users, trust fields, memberships, seat requests, and messages. Protected Next.js APIs validate create payloads with Zod, while serializable transactions and unique relationships protect capacity-sensitive actions. Marketplace contact preserves the originating listing, and shared identity keeps coordination consistent across otherwise different campus workflows.

  • Next.js 15
  • React 19
  • TypeScript
  • Tailwind
  • Prisma
  • PostgreSQL
  • NextAuth
  • Zod
Waterloo email restriction4 connected workflowsContext-linked messaging

Shared Identity

One authenticated User model connects every product domain.

Contextual Messaging

Conversation context links messages to listings, rides, or groups.

Validated Mutations

Protected handlers and Zod validate create payloads before persistence.

Consistent Multi-User State

Transactions and unique relationships protect joins and seat requests.

System architecture

Next.js student client passes through credentials authentication, route handlers, Zod, and Prisma to PostgreSQL. Shared users connect marketplace, rides, study groups, and conversation previews.
View full diagram

One identity. Four connected workflows. Credentials are restricted to @uwaterloo.ca addresses; stored verification levels are prototype trust fields, not proof of institutional verification.

Engineering decisions

DecisionWhyTradeoff
One relational model across product surfaces.Users, trust fields, listings, memberships, and conversations need consistent relationships.Cross-domain schema changes require careful migrations.
Context-linked conversations.Messages retain the resource that initiated the interaction.Extra contextual state; resource references are enforced by application logic.
Serializable capacity mutations and unique relations.Ride seats and group joins must resist duplicates and oversubscription.Transaction complexity and explicit conflicts for callers to handle.

Under the hood

Auth / Trust

  • NextAuth credentials, bcrypt passwords, JWT sessions
  • Sign-in restricted to @uwaterloo.ca addresses
  • Stored verification, ratings, and activity counters

Domain / Data

  • Prisma ORM with PostgreSQL persistence
  • Shared User relations across product domains
  • Compound unique keys for seat requests and memberships

API / Consistency

  • Session checks in protected Next.js Route Handlers
  • Zod schemas validate listing, ride, and group creation
  • Serializable transactions with guarded capacity decrements

Technical deep dives

Relational model linking User to marketplace listings, rides and seat requests, study groups and members, reviews, conversation participants, and messages.

Relational Domain Model

View full diagram

Shared users connect listings, seat requests, memberships, conversations, and reviews.

Conversation contextId is a logical reference, not a database foreign key. Marketplace contact creates or reuses a contextual conversation; the schema also supports ride and group contexts.

Authenticated request starts a serializable transaction, validates the resource and existing relation, conditionally decrements positive capacity, creates a unique relation, and commits. Full rides become waitlisted.

Concurrency-Safe Capacity Flow

View full diagram

Seat requests and group joins use the same transaction pattern to protect capacity.

Existing relationships return 200 without another decrement. New relationships return 201; exhausted capacity or transaction failures return 409. There is no automatic transaction retry loop.

Shared infrastructure, connected product flows

Rides

Offer / request → seat request → capacity / status

Marketplace

Listing → contact → contextual conversation

Study Groups

Group → join → membership / capacity

Messages

Conversation → domain context → latest / unread preview

System checks

  • Product APIs require an authenticated user.
  • Listing, ride, and group creation pass Zod validation.
  • Compound keys constrain duplicate ride/group relations.
  • Guarded decrements protect remaining capacity.
  • Conversation records retain their domain context.

Next at scale

Evolve prototype trust into institutional verification and stronger authorization policies. Add production messaging and event delivery beyond the current previews, and exercise capacity conflicts with concurrent database integration tests.