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분 만에 확인하기Turn Facebook posts into a personal travel blog with an interactive world map, documenting my worldwide travel and marathon footprint.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
The Next.js web app for MaraMap — a running and travel log that turns years of
Facebook posts into an interactive map, timeline and list.
Pairs with MaraMap-Backend
(NestJS Content API + Supabase + Cloudflare R2).
The app needs the backend running on port 3016 for anything data-driven.README 전문 보기 ↗The Next.js web app for MaraMap — a running and travel log that turns years of Facebook posts into an interactive map, timeline and list.
Pairs with MaraMap-Backend (NestJS Content API + Supabase + Cloudflare R2).
| Framework | Next.js 16 (App Router, Turbopack) + React 19 |
| Styling | Tailwind CSS v4 |
| Map | Leaflet + react-leaflet + marker clustering |
| Motion / icons | framer-motion, lucide-react |
| Tests | Jest + Testing Library (unit), Playwright (E2E) |
| Package manager | Bun (what CI uses) |
| Hosting | Vercel |
bun install # also installs the pre-push git hook (see Testing)
bun run dev # http://localhost:3006
The app needs the backend running on port 3016 for anything data-driven.
A single gitignored .env holds everything this machine needs: NEXT_PUBLIC_API_URL
and NEXT_PUBLIC_CARTO_BASEMAP_API_KEY. There's no .env.development /
.env.production split locally — this repo only ever runs one environment
on a dev machine, and the deployed values on Vercel are configured in its own
dashboard rather than from a committed file (these were always gitignored, so
they never reached a Vercel build in the first place).
Leave NEXT_PUBLIC_API_URL empty for local dev. src/utils/apiBase.ts then
derives the backend URL from the page's own hostname, so the app works from
both the laptop (localhost:3016) and a phone on the same LAN
(<machine-LAN-IP>:3016) with no hardcoded address to update when the IP changes.
src/
app/
(public)/ # Public site — home, /log/[id], /personal-best
admin/ # Admin area — login, new, edit/[id], import, personal-best
map/ # Full-screen map view
components/ # MapView, ListView, TimelineView, CountryModal, SiteHeader…
admin/ # MediaManager, Combobox
utils/ # apiBase, formatLocation, locationData, postHelpers
| Route | Purpose |
|---|---|
/ | Home — map / list / timeline of all posts |
/log/[id] | Single post with photo and video carousels + lightbox |
/personal-best | Personal-best records |
/map | Full-screen map |
/admin | Post management (JWT auth against the backend) |
/admin/new, /admin/edit/[id] | Create / edit a post, with direct-to-R2 media upload |
/admin/import | Facebook export import review flow |
bun run test # Jest unit tests with coverage
bun run test:watch
bun run test:e2e # Playwright (starts its own dev server on :3006)
bun run test:e2e:ui # Playwright UI mode
bun run lint
A pre-push hook (.githooks/pre-push, installed automatically by the
prepare script) runs eslint --fix, amends any auto-fixes into the last
commit, then runs the unit tests and aborts the push if they fail.
.github/workflows/ci.yml runs on push and PR to develop / master:
lint → unit tests → Playwright E2E → bun run build. Test results are published
as PR checks via dorny/test-reporter.
These are non-obvious and each one was learned the hard way.
Images bypass the Vercel image optimizer (next.config.ts,
images.unoptimized: true). On the Hobby plan the optimizer has a monthly
transformation quota; photo-heavy post pages blew past it and every
next/image request started returning 402, breaking every image. R2 media is
already Cloudflare-served (free egress, CDN-cached) and FB-export sized
(~200 KB median). If per-device srcset/AVIF is wanted back, do it in
Cloudflare or pre-generate variants in the ETL — not Vercel.
Fonts are loaded with a plain <link>, not next/font/google
(src/app/layout.tsx). next/font downloads woff2 files at build time, and
when the Vercel builder could not reach fonts.gstatic.com the build hard-failed
with no fallback. Weights must stay in sync with the font-* utilities in use —
serif 900 in particular, which every font-serif font-black heading depends on.
Video preload is deliberate, not accidental (src/app/(public)/log/[id]/page.tsx).
The main carousel keeps preload="metadata" because the first frame is the
visual there. The thumbnail rail renders an icon tile instead of a <video>
(at 56 px the frame is unreadable, and each one costs a metadata fetch), and the
lightbox uses preload="none" because every slide in the strip is rendered at
once. See docs/VIDEO_PLAN.md.
Bun is the only supported package manager. package.json's
packageManager field pins the exact version and a preinstall hook
(npx only-allow bun) blocks npm/pnpm/yarn install attempts, so a
second lockfile can't reappear. A past package-manager switch dropped the
Vercel build cache and contributed to a build failure — that's the incident
this guards against.