Skip to content

eddmann/step-wars

Repository files navigation

Step Wars

Step Wars

A fitness challenge app where users compete by tracking daily steps.

This started as a friendly rivalry: a friend and I have been challenging each other on step goals for the past year. WhatsApp screenshots weren't cutting it anymore, so I built an app to make it real.

Step Wars Intro

Rules / Gameplay

  • Challenge modes: cumulative (most total steps) and daily_winner (top 3 daily: 3/2/1).
  • Edit window: today always editable, yesterday editable until noon.
  • Timezone model: users log in their own timezone; challenges use the creator’s timezone for leaderboards and cutoffs; cron runs at noon UTC but processes per‑challenge timezone.

Scoring

Daily winner points: 1st=3, 2nd=2, 3rd=1. Cumulative: winner is highest total steps across the challenge window.

Badges

Badge Name How to earn
☀️ Daily Winner Win a day in a daily winner challenge
🏆 Challenge Champion Win a completed challenge
🔥 7 Day Streak Meet your daily goal 7 days in a row
🔥 14 Day Streak Meet your daily goal 14 days in a row
🌟 30 Day Streak Meet your daily goal 30 days in a row
💎 50 Day Streak Meet your daily goal 50 days in a row
👑 100 Day Streak Meet your daily goal 100 days in a row
🏃 Marathon Day Log 20,000+ steps in a single day
Perfect Week Meet your daily goal every day Mon–Sun

Quick Start

make start

Common commands:

make lint
make test
make build

Run make to see all available targets.

iOS App

The native iOS wrapper is built with PWAKit. To configure a fresh clone:

npx @pwa-kit/cli init ios --url "https://step-wars.eddmann.workers.dev/" --features "notifications,haptics,healthkit"

Architecture

Client

React + Redux Toolkit + React Router SPA.

  • UI and routes live in src/.
  • API client lives in src/lib/api.ts with typed request/response handling.

API Architecture

Cloudflare Workers + Hono + D1 SQLite, structured as a layered architecture with manual dependency injection:

  • Routes: worker/routes/ (HTTP handlers, validation)
  • Use cases: worker/usecases/ (business logic)
  • Repositories: worker/repositories/ (data access via interfaces)
  • Services: worker/services/ (challenge lifecycle, notifications, streak)
  • Clock injection: worker/utils/clock.ts

Routes wire concrete implementations at call time (for example createD1UserRepository(env)), and use cases declare dependencies as interfaces. It’s simpler than clean/hexagonal/onion patterns: no separate domain model layer, shared types live in shared/, and the HTTP layer calls use cases directly without adapters. The same pattern applies to services and clock injection, keeping everything testable without mocks or network calls.

Testing

Client Testing Strategy

Stack: Bun test runner + Testing Library + MSW.

  • UI tests: src/**/*.test.tsx
  • Fixtures: src/test/fixtures.ts
  • MSW mocks: src/test/mocks/

Run:

make test/client

API Testing Strategy

  • Use-case tests: worker/test/usecases/*.test.ts
  • Repository tests: worker/test/repositories/*.d1.test.ts
  • HTTP API tests: worker/test/http/*.http.test.ts

Run:

make test/worker

Database Migrations

make db
make db/remote

License

MIT License

About

Fitness challenge app where friends compete by tracking daily steps. React + Cloudflare Workers + D1.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors