This is a submission for the DEV Weekend Challenge: Community
The Community
Runners. All of them — from the person chasing their first 5K finish to the ultramarathoner logging 100-mile weeks. Whether you're training for TCS World 10K Bengaluru, a local park run, or a marathon on the other side of the world, every runner carries a goal that deserves to be said out loud.
I'm currently training for the TCS World 10K Bengaluru and I wanted a place where runners could declare their goals publicly — and have the community send energy back. Race day is personal, but the journey to the start line is communal.
StrideBoard is built for all of them.
What I Built
StrideBoard — a community race goal hype wall for runners everywhere.
Runners can drop their race goal on the board — their target time, goal type, target pace, and a short message about what's driving them. The community can then 🔥 hype each card. It's part bulletin board, part leaderboard, part pre-race ritual.
Features
- 🎯 Goal Cards — post your race goal with target time, pace, and a motivation message
- 🔥 Hype Button — one-tap community support, fully anonymous count
- 🎭 Goal Types — Personal Best, Sub-60, First Ever Race, Just Finish Strong, Injury Comeback
- 🕶️ Privacy by default — auto-generated runner nicknames (like
SwiftGazelle47) with a one-click anonymous mode so no real names are ever stored - 📊 Community Stats — runners in, total hypes, sub-60 chasers, first-timers
- 🏆 Top Hyped Leaderboard — the most-supported runners float to the top
- ⏱️ Live Race Countdown — days to your target race + a 16-week training progress bar
- 📡 Real-time Redis backend — shared state across all users, no stale data
Demo
🔗 https://strideboard-rose.vercel.app/
Code
StrideBoard 🏃
A community hype wall where runners everywhere can post their race goals and get hyped up by the crowd. 🔥
Deploy to Vercel
1. Get Upstash credentials
- Go to console.upstash.com and create a free Redis database
- Choose the Mumbai (ap-south-1) region for lowest latency
- Copy the REST URL and REST Token from the database page
2. Deploy
npm i -g vercel # if you don't have it
vercel # follow prompts — deploy as-is, no framework
3. Add environment variables
In the Vercel dashboard → your project → Settings → Environment Variables, add:
| Name | Value |
|---|---|
UPSTASH_REST_URL |
https://xxxx.upstash.io |
UPSTASH_REST_TOKEN |
AXxxxx... |
Then redeploy (or run vercel --prod again) — done.
Project structure
strideboard/
├── public/
│ └── index.html # The full app — pure HTML/CSS/JS
├── api/
│ └── redis.js # Vercel serverless proxy — keeps token server-side
├── vercel.json # Tells Vercel to serve from /public
└── package.json
Redis
…Screenshot
How I Built It
This was a deliberately lean stack — the goal was to ship fast and keep it deployable in one command.
Tech Stack
| Layer | Choice | Why |
|---|---|---|
| Frontend | Vanilla HTML/CSS/JS | Zero build step, fast to iterate |
| Backend | Vercel Serverless Function | Token proxy — credentials never hit the browser |
| Database | Upstash Redis (REST API) | Serverless, Mumbai region, instant reads |
| Deployment | Vercel | One vercel command, done |
| Fonts | Bebas Neue + DM Mono | Race bib aesthetic — felt right for runners |
Architecture
The whole app is a single index.html served from Vercel's CDN. All Redis commands go through a thin /api/redis.js serverless function that proxies requests with an allow-list (LRANGE, LPUSH, HGETALL, HINCRBY only). The Upstash token never touches the browser.
Browser → /api/redis (Vercel Function) → Upstash Redis
Redis schema:
-
stride:cards— a Redis List. Each card isLPUSH'd as JSON soLRANGE 0 99always returns newest-first. -
stride:hypes— a Redis Hash. Each field is a card ID, value is the hype count. Incremented withHINCRBYso concurrent hypes from different users don't collide.
Hype counts are separated from card data intentionally — it means we never need to rewrite card JSON just to bump a counter.
Privacy Decisions
One thing I thought carefully about was PII. A running community is a tight-knit group — real names on a public board felt uncomfortable.
The solution:
- Auto-generated nicknames on load (20 adjectives × 20 animals × 90 numbers = 36,000 combos). No real name is ever suggested.
-
Anonymous mode checkbox — posts as
🕶️ Anonymous Runner, the nickname is never sent to Redis at all. - Hypes are fully anonymous — just a count in Redis, no user identity attached.
Zero PII hits the database either way.
Challenges
The trickiest part was deciding how to handle hype state across sessions. Since there's no auth, I used sessionStorage to track "did this browser tab already hype this card" — which prevents double-hyping within a session without requiring login. It's a deliberate trade-off: refresh the page and you can hype again, but that felt fine for a community hype board rather than a voting system.
All writes are optimistic with rollback — the UI updates instantly and reverts if the Redis call fails.
Reflections
I usually build side projects that solve my problems. This one was different — I built it thinking about every runner who has a goal sitting in their head that they haven't told anyone yet.
The first-timers who are terrified. The comeback runners who've been off for months with an injury. The sub-60 chasers who've been trying for years. They exist in every city, in every running community, at every race.
StrideBoard is for all of them.
Whatever your race, whatever your goal — drop it on the board. The community's got you. 🏃
🙏 Thanks for reading! Would love any feedback or ideas in the comments.

Top comments (0)