Inspiration
Every UBC student has said it: "this term, I'm going to start running." By week three, midterms win and the plan is gone.
We asked 115+ students on campus, and 78% said they had no real reason not to bail. The problem isn't motivation. It's that quitting costs nothing. Fitness apps track what you do, but nobody loses anything when you skip. We wanted accountability with real stakes, built for our own community.
What it does
Grit lets UBC students make running pacts with real money on the line.
- Verified students only. Sign in with a
@student.ubc.caemail and a one-time code. - Join or create a pact. Pick the activity, distance, deposit and dates. Make it public to every verified student or invite-only for friends.
- Put down a stake. Everyone deposits the same amount of SOL into the pool. Every deposit is a real Solana transaction you can verify on the explorer.
- Just run. Connect Strava once and activities sync automatically. Your progress stays private unless you opt into the leaderboard.
- Every run is checked. GPS checks reject car-speed movement, GPS spikes and suspicious gaps, so only real effort counts.
- Settlement runs itself. At the deadline, an n8n workflow settles the pact. Everyone who hit the goal splits the pool. If everyone or no one makes it, everyone is refunded. If anything fails, the error is handled and an admin is notified.
- 0% platform fee. Every pact has a public pool receipt showing exactly where the money went.
- Community. A campus chat for verified students, plus run clubs you can start or join with an invite code.
How we built it
- Design: Figma, then a mobile-first Next.js + Tailwind CSS frontend.
- App: Next.js (App Router) with TypeScript, server routes for auth, pacts, deposits, sync and settlement.
- Data and auth: Supabase (Postgres, row-level security, email OTP sign-in). Access policies keep each student's activity private.
- Activity: Strava OAuth and activity sync, with a tested core library (
packages/core) for GPS plausibility checks, progress and settlement math. - Money: Solana web3.js and wallet adapter for deposits, verified transactions, payouts and receipts.
- Automation: an n8n workflow on a 15-minute schedule calls an authenticated settlement endpoint, builds a summary, and alerts an admin on failure. n8n never sees fitness data.
- Deployment: Vercel.
Challenges we ran into
- Making it hard to cheat. We had to decide what counts as a real run. We built GPS checks for vehicle speed, spikes and gaps without exposing anyone's routes.
- Money logic edge cases. Split versus refund when everyone or no one finishes, duplicate or premature settlement, and failed payouts all needed clear rules and tests.
- Privacy versus accountability. Students should feel accountable without broadcasting their runs, so progress is private by default and the leaderboard is opt-in.
- Four people, 24 hours. Coordinating shared interfaces across frontend, backend, Strava, Solana and n8n at the same time.
Accomplishments that we're proud of
- A working flow from start to finish: sign in → connect Strava → deposit → run → verified progress → automated settlement → receipt.
- Real on-chain deposits and payouts with a public receipt for every pact.
- Settlement that runs on its own, with error handling and admin alerts.
- Grounding the idea in real feedback from 115+ UBC students.
What we learned
- Designing incentives is as much product design as engineering: the rules have to feel fair before people will put money in.
- How to keep a backend authoritative while letting automation tools like n8n trigger it safely.
- Working with OAuth, wallets and row-level security in one app.
What's next for Grit
- Pilot with UBC run clubs and residence floors.
- More activity types and team-versus-team pacts.
- Expanding to other campuses with verified student emails.
- Stronger anti-cheat and smarter goal suggestions based on each person's history.
Built With
- figma
- leaflet.js
- n8n
- next.js
- node.js
- oauth
- pnpm
- postgresql
- react
- solana
- solana-wallet-adapter
- solana-web3.js
- strava-api
- supabase
- tailwindcss
- typescript
- vercel
- vitest