BikeControl (SwiftControl)
Use Zwift Click, Zwift Play, Shimano Di2, or any Bluetooth controller with MyWhoosh, Rouvy, Zwift, and more. Free to try on iOS, Android, Windows, and macOS.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Wager is a rec sports meetup app: find a pickup match, pay the entry fee, lock your spot on the roster. Hosts get paid out through Stripe Connect. This repo is a Bun-workspaces monorepo.
REST API contract: docs/api.md.
Mobile (separate terminal): cd apps/mobile && bunx expo start. See apps/mobile/README.md.README 전문 보기 ↗Wager is a rec sports meetup app: find a pickup match, pay the entry fee, lock your spot on the roster. Hosts get paid out through Stripe Connect. This repo is a Bun-workspaces monorepo.
apps/
web/ # Next.js 16 — App Router, REST /api, Better Auth, Server Actions
mobile/ # Expo SDK 55 — TanStack Query + REST against web /api
packages/
domain/ # @wager/domain — server-only match, entry, and payment logic
payments/ # @wager/payments — Stripe Connect, Checkout, refunds, webhooks (server-only)
shared/ # @wager/shared — Zod API schemas, DTOs, api-client, query keys
db/ # @wager/db — Prisma
auth/ # @wager/auth — Better Auth
REST API contract: docs/api.md.
bun install
cp apps/web/.env.example apps/web/.env # fill in values
bun run --filter @wager/db prisma:migrate:dev
bun run dev # web on :3000
bun run stripe:listen # forwards webhooks; copy the whsec_ into .env
| Command | What it does |
|---|---|
bun run dev | Next.js web only (:3000) |
bun run build | web production build |
bun run lint | web lint |
bun run prisma-sanity | validate + generate Prisma artifacts |
bun run test:domain | domain integration tests (needs DATABASE_URL pointing at a disposable DB — the tests truncate tables) |
Mobile (separate terminal): cd apps/mobile && bunx expo start. See apps/mobile/README.md.
/host/payouts. Paid matches can't be created until charges_enabled and details_submitted are true (account.updated webhook, with a direct check on return).POST /api/matches/:id/entry locks the match row (SELECT … FOR UPDATE), counts confirmed entries plus unexpired holds, and either confirms (free) or writes a Pending entry with holdExpiresAt ≈ 31 min and returns a Checkout URL.PLATFORM_FEE_BPS (5%). Checkout expires just inside the hold window.checkout.session.completed confirms the seat. If the hold lapsed and the seat was taken, or the match was cancelled meanwhile, the payment is refunded automatically. Events are recorded in StripeEvent after success, so failures are retried by Stripe.refundCutoffHours; seat released without refund after.@wager/domain for server reads; Server Actions for match create/update/cancel and payout onboarding; TanStack Query for lists and join/leave.@wager/shared api-client. Paid joins use WebBrowser.openAuthSessionAsync; /checkout/return bounces Stripe's https redirect to wager://.@wager/db; business logic in @wager/domain (server-only)./api/auth/* (Google), Redis secondary storage.@wager/payments.Single Vercel project with Root Directory apps/web.
| Variable | Purpose |
|---|---|
DATABASE_URL | Postgres |
REDIS_URL | Session secondary storage |
AUTH_SECRET, BETTER_AUTH_URL, OAuth client IDs/secrets | Better Auth |
STRIPE_SECRET_KEY | Stripe API |
STRIPE_WEBHOOK_SECRET | Signing secret for /api/webhooks/stripe |
Create the webhook endpoint at {origin}/api/webhooks/stripe with "Listen to events on Connected accounts" enabled (needed for account.updated) and subscribe to: checkout.session.completed, checkout.session.expired, checkout.session.async_payment_succeeded, checkout.session.async_payment_failed, account.updated, charge.refunded.
OAuth redirects: {origin}/api/auth/callback/google.
Entry fees go to the host to cover court time, refs, and gear. Pooling fees into a prize paid to winners turns this into a paid-entry contest, which is regulated state by state and restricted under Stripe's terms — review both before adding winner payouts.