Inspiration

High-quality and sustainable hydration is a commodity at Penn. While plastic water bottles saturate campus, water fountains remain impossible to find, taste weird, and sometimes don't even work. Instead of leaving this issue as an overlooked inconvenience, we asked—what if hydration could actually be fun, environmentally conscious, and community-driven? That question became Hydrate: an app that turns finding water into a shared, gamified experience.

What it does

Hydrate helps you find and review fountains across campus, but it’s much more than that:

Interactive Map: Identify working, broken, or low-quality fountains in real time (or alternatively, which water fountains in your area have the best-tasting water).

Fountain Reviews: Rate on coldness, pressure, experience, and yum factor.

Game Layer: Leaderboards for most hydrated, most upvoted ratings, and best water fountains, as well as 30+ achievement badges keep people engaged.

Social Interface: A feed with fountain reviews, comment functionality, and upvotes & downvotes makes it so that you can see what the local community (and the "water-influencers" that you follow) think about different fountains!

Drink Tracking: Log your hydration, compare with friends, and measure bottles saved.

And finally, our crowning feature:

hyDATEr:

A one-of-a-kind dating feature that matches people based on fountain rating compatibility, with real-time chat and date planning around fountain visits.

How we built it

Frontend: React 18 + TypeScript, styled with Tailwind, and mapped with Mapbox GL.

Backend: Supabase for auth, database, real-time subs, and storage.

  • Pearson correlation and weighted sum compatibility algorithm for hyDATEr. $$ r = \frac{\sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n} (x_i - \bar{x})^2 \sum_{i=1}^{n} (y_i - \bar{y})^2}} $$ \(x_i\) and \(y_i\) are the average ratings for fountain \(i\) by users 1 and 2 \(\bar{x}\) and \(\bar{y}\) are the overall average ratings for each user \(n\) is the number of shared fountains
  • Real-time WebSocket chat with read receipts.
  • A badge progression system with 8 categories and 30+ achievements.

Challenges we ran into

  • Attractive and responsive front page design: Creating a theme that is both water themed and modern (think Frutiger Aero but new!). We also needed to make sure the design was mobile-friendly.
  • Real-time updates: Real-time updates can cause unnecessary re-renders and dependency arrays in useEffect hooks can cause effect runs more often than intended. So, we needed to use callbacks and optimize the rendering, while still using real-time updates for features such as messaging.
  • Image uploads: Profile pictures and file uploads add significant complexity, and we had to complete multiple migrations for profile picture buckets and schemas before we found the system that worked best for us.

Accomplishments that we're proud of

  • Building a dating feature entirely around water fountain compatibility (and yes, it actually works!!!).
  • Pulling off real-time updates across chat, feeds, and fountain status.
  • Creating a badge system that makes hydration feel like a game.
  • Turning a “boring utility” into something students actually want to use.

What we learned

  • Image Handling Complexity: We had to make many changes/migrations to our schema due to poorly designed original tables and storage buckets, so we learned the value of thorough planning, especially for the DB (the backbone of the whole app).
  • Optimizing Real-Time Apps: We learned how to prevent over-rendering in React when working with real-time subscriptions, especially when multiple features (chat, feeds, fountain status) all rely on live data.
  • Balancing Ambition vs. UX: It was tempting to keep shipping features, but we learned the value of making tough design tradeoffs so the app stays usable and intuitive.

What's next for Hydrate

Making a react native app for mobile deployment.

QR Codes for Fountains: Place QR codes on fountains for users to easily be able to leave a review.

Built With

Share this project:

Updates