Your neighbors are already going there. Save time, reduce emissions, and strengthen your communityβone errand at a time.
Rundour is a hyper-local errand-sharing platform that connects neighbors who are already heading to the same stores. Need one item from the hardware store? Your neighbor is going there anywayβRundour makes the match instantly.
Built as a zero-backend, fully functional single-page application that runs entirely in the browser with real-time cross-tab synchronization, geolocation, interactive mapping, and a complete user management system.
Live Demo: Open
index.htmlin any modern browser. Click "Try Demo Account" on the login screen to explore with pre-populated data, or sign up to start from zero and watch the community grow as you use it.
- πΊοΈ Hyper-Local Discovery β Radius-based matching (1β25km) with Haversine distance calculation
- π Interactive Mapping β Full Leaflet/OpenStreetMap integration with live markers, popups, and user geolocation
- π¬ Real-Time Messaging β In-app encrypted chat threads per errand; no phone numbers exchanged
- β‘ Live Sync β Cross-tab real-time updates via BroadcastChannel API + localStorage persistence
- π Eco Impact Tracking β Automatic fuel (L) and COβ (kg) savings calculation per completed errand
- π Secure Auth β Registration, login, session tokens, password hashing, rate limiting, XSS sanitization
- β Verification Tiers β Email, phone (SMS simulation), and ID verification with badge display
- β Reputation Engine β Rating system, completion counters, response time tracking
- π Privacy-First β Exact coordinates never shared; only neighborhood-level visibility
| Plan | Price | Limits |
|---|---|---|
| Neighbor | Free | 3 errands/month, 2km radius |
| Local Hero | $4.99/mo | Unlimited errands, 10km radius, verified badge, priority support |
| Community Champion | $9.99/mo | 25km radius, gold badge, analytics dashboard, 24/7 support |
- Landing β Animated hero, live stats, how-it-works, feature grid, pricing, security trust section
- Dashboard β Private overview with stats, activity feed, nearby errands, profile sidebar
- Explore β Dual-pane map + list with distance slider, category chips, urgency filters
- Create Errand β Multi-section form with tips, safety reminders, and plan enforcement
- Errand Detail β Status workflows, compensation display, real-time message thread
- Community β Discussion board, events, likes/shares, trending topics, neighbor directory
- Inbox β Tabbed messages & notifications with unread badges and conversation routing
- Profile β Cover photo layout, badges, subscription tier, verification status, tabbed history
- Settings β Account editing, privacy toggles, notification preferences, password change, account deletion
| Layer | Technology |
|---|---|
| Framework | Vanilla JavaScript (ES6+) β zero dependencies |
| Styling | Custom CSS with CSS Variables, Flexbox, CSS Grid |
| Maps | Leaflet 1.9.4 + OpenStreetMap tiles |
| Icons | Font Awesome 6.4 |
| Typography | Inter (Google Fonts) |
| Persistence | localStorage + BroadcastChannel API |
| Security | Client-side input sanitization, token generation, rate limiting |
No build step. No server required. Just open the file.
# Clone the repo
git clone https://github.com/yourusername/rundour.git
cd rundour
# Open in browser (macOS)
open index.html
# Or serve locally for full geolocation support
npx serve .
# Then visit http://localhost:3000rundour/
βββ index.html # Main SPA shell (75KB)
βββ css/
β βββ style.css # Complete design system (60KB)
βββ js/
β βββ app.js # Application logic, store, router (93KB)
βββ README.md # This file
Centralized immutable-ish store with the following data shape:
{
currentUser: null | User,
users: [],
errands: [],
messages: [],
communityPosts: [],
notifications: [],
stats: { totalUsers, totalErrands, totalFuelSaved, totalCO2Saved }
}- Auto-save every 5 seconds to
localStorage - Cross-tab sync via
BroadcastChannel(falls back gracefully) - All CRUD operations return updated references for reactive UI updates
Hash-based SPA router with 14 routes:
routes: [
'home', 'login', 'register', 'dashboard', 'explore', 'create',
'errand', 'community', 'inbox', 'profile', 'settings',
'my-errands', 'running', 'history', 'pricing'
]- Route guards for authenticated pages
- Dynamic parameter parsing (
#/errand/:id) - Page-specific initialization hooks
Security: {
hashPassword(password) // Simple hash for demo
sanitize(str) // XSS prevention via textContent
validateEmail(email) // RFC-style regex
generateToken() // crypto.getRandomValues(32)
checkRateLimit(key, max, window)
}- Landing β Click Get Started
- Login β Click "Try Demo Account" (instant demo user with 3 errands)
- Dashboard β See stats, activity feed, and nearby errands
- Explore β Pan the map, filter by category/urgency, click an errand
- Errand Detail β Accept an errand, open the message thread, send a message
- Community β Create a post, like posts, view neighbors
- Profile β Verify phone (code:
123456), upgrade subscription - Settings β Toggle privacy, change password, manage notifications
All data persists in localStorage. Open the app in a second tab to see real-time sync in action.
| Threat | Mitigation |
|---|---|
| XSS | All user input sanitized via textContent before DOM insertion |
| CSRF | Session tokens generated with crypto.getRandomValues |
| Brute Force | Rate limiting: 5 login attempts per minute per IP (simulated) |
| Data Leak | Exact coordinates never rendered; only neighborhood strings shown |
| Injection | No innerHTML with user data; parameterized store queries |
Note: This is a client-side prototype. Production deployment requires a proper backend with bcrypt, HTTPS, JWT refresh tokens, and server-side validation.
| Token | Value | Usage |
|---|---|---|
--primary |
#059669 |
Emerald β trust, eco-friendly actions |
--secondary |
#f59e0b |
Amber β energy, urgency highlights |
--accent |
#ec4899 |
Pink β community, warmth, notifications |
--bg |
#f8fafc |
Slate-50 β clean canvas |
--surface |
#ffffff |
White β cards, modals |
--text |
#0f172a |
Slate-900 β primary text |
- Mobile-first responsive breakpoints at
1024px,768px,480px - Backdrop blur navigation for modern glassmorphism feel
- CSS Grid + Flexbox throughout; no framework bloat
- Backend API β Node.js/Express + PostgreSQL or MongoDB
- Real-time Messaging β Socket.io or WebSockets for instant chat
- Payment Integration β Stripe for subscription billing
- Geocoding β Google Places API or Mapbox for store autocomplete
- Push Notifications β Web Push API for mobile alerts
- PWA β Service workers, offline support, installable app
- Image Uploads β Cloudinary or S3 for avatar/ID verification
- Moderation AI β Content filtering for community posts
Contributions are welcome! This is a vanilla JS projectβno build tools to learn.
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing-thing) - Commit your changes (
git commit -m 'Add amazing thing') - Push to the branch (
git push origin feature/amazing-thing) - Open a Pull Request
Please ensure your code passes the existing security patterns (sanitize all inputs, no raw innerHTML with user data).
MIT Β© 2026 Rundour
Built with π for stronger neighborhoods.