BikeControl (SwiftControl)
使用 Zwift Click、Zwift Play、Shimano Di2 或任何藍牙控制器,搭配 MyWhoosh、Rouvy、Zwift 等。iOS、Android、Windows、macOS 均可免費試用。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
BallDoenSai.com คือแพลตฟอร์มสำหรับนักกีฬาฟุตบอลเยาวชนไทย ผู้ปกครอง โค้ช และผู้จัดการแข่งขัน ไม่ได้ตั้งใจเป็นเพียงเว็บลงแข่งหรือเว็บจัดอันดับ แต่สร้าง Digital Sports Identity ให้เด็กคนหนึ่งมี “เส้นทางนักกีฬา” ของตัวเองที่เติบโตตามผลงานจริง Production: ballsai-teal.vercel.app GitHub: werawoot/ballsai การแข่งขันหนึ่งนัดไม่ควรหายไปหลังเสียงนกหวีดจบ แต่ควรกลายเป็นหลักฐานของความพยายาม เช่น การ์ดนักเตะ, XP, Badge, ผลงาน, Highlight, อันดับ และความทรงจำที่ส่งต่อให้เพื่อนหรือครอบครัวดูได้查看完整 README ↗
เปลี่ยนทุกการแข่งขันให้เป็นตัวตน ความทรงจำ และความก้าวหน้าที่นักกีฬาเยาวชนภูมิใจจะเก็บและแชร์
BallDoenSai.com คือแพลตฟอร์มสำหรับนักกีฬาฟุตบอลเยาวชนไทย ผู้ปกครอง โค้ช และผู้จัดการแข่งขัน ไม่ได้ตั้งใจเป็นเพียงเว็บลงแข่งหรือเว็บจัดอันดับ แต่สร้าง Digital Sports Identity ให้เด็กคนหนึ่งมี “เส้นทางนักกีฬา” ของตัวเองที่เติบโตตามผลงานจริง
ชื่อธุรกิจและผลิตภัณฑ์: BallDoenSai.com
ชื่อ repository เดิม: ballsai
สถานะเอกสาร: อัปเดตล่าสุด 11 สิงหาคม 2026
เอกสารส่งต่องาน Closed Beta ล่าสุดสำหรับผู้ช่วยพัฒนา: docs/claude-handoff-next-steps.md
Production: doensai.com (ตั้งแต่ 25 ต.ค. 2026; ballsai-teal.vercel.app ยังเปิดได้) GitHub: werawoot/ballsai
หัวใจของ BallDoenSai คือทำให้เด็กที่ลงสนามรู้สึกว่า:
“ฉันกำลังเติบโต ฉันมีผลงาน และนี่คือเส้นทางนักกีฬาของฉัน”
การแข่งขันหนึ่งนัดไม่ควรหายไปหลังเสียงนกหวีดจบ แต่ควรกลายเป็นหลักฐานของความพยายาม เช่น การ์ดนักเตะ, XP, Badge, ผลงาน, Highlight, อันดับ และความทรงจำที่ส่งต่อให้เพื่อนหรือครอบครัวดูได้
| กลุ่ม | สิ่งที่ได้จากระบบ |
|---|---|
| นักกีฬาเยาวชน | Card, Passport, Level, Badge, Highlight, ประวัติและลิงก์แชร์ |
| ผู้ปกครอง | เห็นเส้นทางและผลงานของน้อง ช่วยดูแลโปรไฟล์/การสมัครแข่ง |
| โค้ช / สเกาต์ | ค้นหานักกีฬา ดู Rating, ผลงาน, วิดีโอ และความสม่ำเสมอ |
| ผู้จัดการแข่งขัน | สร้างรายการ, รับทีม, ตรวจสลิป, ยืนยันทีม, บันทึกผล |
| ผู้ดูแลระบบ | ดูแลข้อมูล, นักกีฬา, Hall of Fame, การดำเนินงาน และความปลอดภัย |
| มุมที่วัด | ความพร้อมโดยประมาณ | ความหมาย |
|---|---|---|
| Digital Sports Identity (Card / XP / Badge / Passport / Hall / Highlight) | 90% | ฟังก์ชันหลักเขียนและเชื่อมฐานข้อมูลแล้ว เหลือพิสูจน์กับข้อมูลและผู้ใช้จริง |
| แพลตฟอร์ม Closed Beta | 65–70% | มีระบบหลักและโครงสร้างปลอดภัย แต่ยังต้องใส่ข้อมูลจริง ทดสอบ flow จริง และเก็บ feedback |
| การเปิดสาธารณะระดับ Production 100% | ยังไม่ถึง | ต้องผ่าน Closed Beta, ข้อมูลจริง, การดูแลผู้เยาว์, Monitoring และโดเมนจริงก่อน |
ข้อสำคัญ: “100%” ไม่ได้หมายถึงเขียนโค้ดครบอย่างเดียว แต่หมายถึงเด็ก ผู้ปกครอง และผู้จัดใช้งานจริงได้โดยไม่เจอ flow หลักพัง และทีมดูแลตอบสนองปัญหาได้
| ระบบ | สถานะ | ทำอะไรได้แล้ว |
|---|---|---|
| 🃏 Player Card | พร้อมใช้งาน Beta | สร้างการ์ดจากข้อมูลนักกีฬา/รูป/ตำแหน่ง/ทีม, บันทึก, ดาวน์โหลดภาพ และเปิดการแชร์ผ่านระบบของอุปกรณ์/ลิงก์ |
| ⭐ Level / XP | โครงหลักพร้อม | มี athlete_progress, XP events, level 1–99 และ progress calculation จากผลงานการแข่งขันที่ยืนยันแล้ว |
| 🏆 Achievement / Badge | โครงหลักพร้อม | มี Badge Road: Rookie, First Kick, Winner, Goal Hunter, Playmaker, The Wall, MVP, Road Warrior, Rising Star และสร้าง Achievement ให้สัมพันธ์กับ Badge |
| 📖 Career Timeline / Athlete Passport | พร้อมใช้งาน Beta | รวมข้อมูลโปรไฟล์, ทีม, ผลแข่ง, Rating, Achievement และ Highlight เป็นประวัติของนักกีฬา |
| 🏛️ Hall of Fame | พร้อมใช้งาน Beta | มีหน้า Hall จริง, filter ฤดูกาล/รุ่นอายุ/จังหวัด/หมวดรางวัล และหน้า admin สำหรับมอบรางวัล |
| 🎬 Highlight Moments | พร้อมใช้งาน Beta | เพิ่มรูป/วิดีโอหรือ URL ของ YouTube/TikTok, แสดงใน Passport/โปรไฟล์สาธารณะ และจัดเก็บผ่าน Supabase Storage |
| โปรไฟล์สาธารณะ | พร้อมใช้งาน Beta | หน้า /players/[id] พร้อม Open Graph image เพื่อให้ลิงก์ที่แชร์มีภาพประกอบ |
นิยามที่ต้องรักษาไว้ในการพัฒนาต่อ:
Ranking = ลำดับเชิงตัวเลขและผลงานปัจจุบัน เช่น Power Rating หรือกำลังมาแรงHall of Fame = พื้นที่เชิดชูความสำเร็จที่คัดเลือก/มอบรางวัลตามจังหวัด รุ่นอายุ ฤดูกาล หรือประเภท ไม่ใช่แค่ตารางอันดับอีกชุด/tournaments และหน้ารายละเอียดรายการ/dashboard/resultsmatch_results, match_player_performances, rating_events และเป็นต้นทางของ XP/Badge ที่เกี่ยวข้อง/athletes/ranking/hall-of-fame/impact, career /career, profile /profile, card /card/welcome เพื่อเก็บข้อมูลแบบสั้น 3 ขั้น:
profiles และสร้าง athlete_profiles ให้ผู้เลือกบทบาทนักกีฬาเมื่อจำเป็น/admin/moderation ซ่อนได้ทันทีและกู้คืนได้ โดยไม่ต้องลบไฟล์ของเด็ก/profile ลบข้อมูลนักกีฬาและไฟล์ทันที ตัดชื่อออกจากตาราง ranking แต่เก็บตัวเลขที่ทีมอื่นถูกวัดด้วยไว้ แล้วส่งคำขอปิดบัญชีให้แอดมินที่ /admin/operationsGoogle Login ถูกตั้งค่าด้วยบัญชีเจ้าของ [email protected] แล้ว
| รายการ | สถานะ |
|---|---|
| Google Cloud project | สร้างแล้ว: BallDoenSai |
| Google Auth branding | DOENSAI.com (25 ต.ค. 2026; ยังไม่ได้ยื่น Verify branding) |
| OAuth Client | สร้างแล้ว: BallDoenSai Web |
| Authorized JavaScript origin | https://ballsai-teal.vercel.app |
| Google → Supabase callback | https://hivedzrwrrcnjrlirhtv.supabase.co/auth/v1/callback |
| Supabase Google provider | Enabled |
| OAuth publishing | Testing mode |
ขณะที่ Google Auth อยู่ใน Testing mode จะเข้าได้เฉพาะ owner และบัญชีที่เพิ่มเป็น Test user ใน Google Cloud เท่านั้น เหมาะสำหรับ Closed Beta ระยะแรก
ก่อนเปิดให้คนทั่วไปใช้ ต้อง:
doensai.com เพิ่มแล้ว (25 ต.ค. 2026): Google Authorized domains, Supabase Site URL https://doensai.com และ Redirect URL https://doensai.com/auth/callbackห้าม commit หรือวาง Client Secret / API key ลง GitHub, README หรือไฟล์ฝั่ง client
ผู้ใช้ (Browser)
│
▼
Next.js 15 App Router on Vercel
│ ├─ Public pages / Server Components / Cached public data
│ ├─ Route handlers: teams, payments, results, highlights
│ └─ Login + onboarding flows
▼
Supabase
├─ Auth (Email OTP + Google OAuth)
├─ Postgres + RLS
├─ Storage (slips, athlete-highlights)
└─ Rating / XP / Badge / Hall database functions
│
├─ Resend: transactional mail (when domain is verified)
└─ Upstash Redis: shared rate limiting (when env is configured)
ใช้ Supabase project ref: hivedzrwrrcnjrlirhtv (Ballsai)
ห้ามนำ SQL ไป apply ใน Supabase project เก่า/คนละ project โดยไม่ตรวจ URL และ project ref ก่อน เพราะในอดีตเคยมีความเสี่ยงของการทำงานผิด project
ลำดับการ apply แบบเต็มพร้อมเหตุผลและ dependency อยู่ใน docs/closed-beta-runbook.md §3 — ตารางนี้เป็นสารบัญว่าแต่ละไฟล์ทำอะไร
| ไฟล์ | หน้าที่ | ลำดับ |
|---|---|---|
sql/check-duplicates-before-unique-indexes.sql | ตรวจ duplicate ก่อนเพิ่ม unique indexes | 1 |
sql/supabase-rls.sql | RLS โครงหลัก + is_admin() / is_organizer() | 2 |
sql/fix-profile-auth-trigger.sql | trigger สร้าง profiles ให้ทุกบัญชี Auth + backfill บัญชีเก่า | 3 |
sql/ballsai-rating-v1.sql | Power Rating, match result, rating events | 4 |
sql/athlete-profile-v2.sql | Athlete profile, video, achievement, skill assessment + bucket athlete-avatars | 5 |
sql/link-player-ranks-to-profiles.sql | ผูก player_ranks.player_id กับบัญชีจริง + unique index ต่อ season | 6 |
sql/digital-identity-v1.sql | XP, Level, Badge และ triggers จาก rating events | 7 |
sql/digital-identity-v2-hall.sql | Rookie badge, Achievement sync, Hall of Fame | 8 |
sql/athlete-highlight-uploads-v1.sql | Athlete highlights + bucket athlete-highlights (private) | 9 |
sql/onboarding-v1.sql | ข้อมูล first-visit onboarding | 10 |
sql/production-hardening.sql | ทำให้ slips เป็น private, RPC register_team_safely / confirm_payment_safely / record_match_result_safely, indexes | 11 |
sql/match-result-void-v1.sql | RPC void_match_result_safely() ยกเลิกผลแข่งพร้อมคืน Rating/XP/Badge | 12 |
sql/guardian-consent-enforcement-v1.sql | บังคับกฎความยินยอมผู้ปกครองก่อนเผยแพร่โปรไฟล์ผู้เยาว์ในระดับฐานข้อมูล | 13 |
sql/highlight-moderation-v1.sql |
ไฟล์ที่ ไม่ต้อง apply:
sql/supabase-rls-private-slips.sql — เป็นทางเลือกแทน sql/supabase-rls.sql สำหรับการติดตั้งที่หยุดแค่ไฟล์ base เท่านั้น เพราะลำดับ 11 ทำให้ slips เป็น private ด้วย policy เวอร์ชันใหม่อยู่แล้ว ถ้า apply ไฟล์นี้ทับจะเขียน policy profiles ของลำดับ 3 กลับไปเป็นเวอร์ชันเก่าsql/sample-data.sql — ข้อมูลตัวอย่างสำหรับ demo เท่านั้น Closed Beta ใช้ข้อมูลจริงล้วนหมายเหตุ: ไม่มีไฟล์ SQL ไหนสร้าง bucket slips ต้องสร้างเองใน Supabase Storage แบบ private แล้วรันลำดับ 11 ซ้ำ
Migrations ด้านบนถูก apply ใน project ที่ถูกต้องแล้วสำหรับระบบปัจจุบัน การแก้ schema ต่อไปควรทำเป็นไฟล์ migration ใหม่ แทนการแก้ข้อมูลจริงแบบ ad-hoc ใน dashboard
| Route | หน้าที่ | กลุ่มผู้ใช้ |
|---|---|---|
/ | หน้าแรกและจุดเริ่มต้น | ทุกคน |
/login | Google Login / Email OTP | ทุกคน |
/welcome | onboarding หลัง login ครั้งแรก | ผู้ใช้ใหม่ |
/card | Player Card Builder | นักกีฬา |
/profile | แก้ไข Athlete Identity | นักกีฬา |
/career | Athlete Passport / Career Timeline | นักกีฬา |
/players/[id] | โปรไฟล์สาธารณะ/ลิงก์แชร์ | ทุกคน |
/athletes | ค้นหานักกีฬา | โค้ช, สเกาต์, ทุกคน |
/ranking | ตารางคะแนน/กำลังมาแรง | ทุกคน |
/hall-of-fame | Hall of Fame จริง | ทุกคน |
/tournaments | รายการแข่ง | ทุกคน |
/dashboard | ผู้จัดการแข่งขัน | organizer |
/dashboard/results | บันทึกผล + Preview rating changes | organizer |
/admin/hall | มอบ Hall of Fame | admin / organizer ที่มีสิทธิ์ |
/admin | ดูแลนักกีฬา/operations/infrastructure | admin |
สมัคร → onboarding → สร้าง profile → สร้าง Card → สมัครแข่ง → ส่งสลิป → ผู้จัดยืนยัน → บันทึกผล → XP/Badge/Ranking เปลี่ยน → แชร์doensai.com (Hostatom, Nameservers ของ Vercel, 25 ต.ค. 2026)RESEND_FROM_EMAILระบบปัจจุบันรองรับ ดาวน์โหลด Card เป็นภาพ และเรียก native share / share link ซึ่งผู้ใช้สามารถนำไปโพสต์ใน TikTok, IG Story หรือ Facebook ได้
สิ่งที่ยังไม่ใช่ และไม่ควรสื่อสารเกินจริง:
สร้าง .env.local สำหรับ local development:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
RESEND_API_KEY=your_resend_api_key
RESEND_FROM_EMAIL="BallDoenSai.com <[email protected]>"
UPSTASH_REDIS_REST_URL=your_upstash_redis_rest_url
UPSTASH_REDIS_REST_TOKEN=your_upstash_redis_rest_token
NEXT_PUBLIC_SHOW_DEMO_DATA=false
NEXT_PUBLIC_ACTIVE_SPORT=football
NEXT_PUBLIC_ACTIVE_SEASON=2026
# optional: CAPTCHA before an email code (docs/captcha-setup.md)
NEXT_PUBLIC_TURNSTILE_SITE_KEY=
หมายเหตุ:
NEXT_PUBLIC_ACTIVE_SPORT / NEXT_PUBLIC_ACTIVE_SEASON คือช่วงการแข่งขันที่ระบบใช้อยู่ (Ranking, Hall of Fame, บันทึกผล, Player Card, admin) ไม่ตั้งก็ได้ ค่า default คือ football / 2026 ตามที่ lib/season.ts กำหนด การเปลี่ยนฤดูกาลต้อง redeploy เพราะเป็นค่าระดับ build time
Google OAuth Client ID/Secret ตั้งใน Supabase Auth provider dashboard ไม่ใช่ .env.local ของ client
RESEND_API_KEY จำเป็นเมื่อเปิดส่งอีเมลแจ้งสถานะทีม
ไม่มี Upstash ใน environment จะ fallback เป็น in-memory rate limit ซึ่งเหมาะกับ local เท่านั้น
production/closed beta ควรใช้ NEXT_PUBLIC_SHOW_DEMO_DATA=false
npm install
npm run dev
เปิด http://localhost:3000
ตรวจสอบก่อน deploy:
npm run lint
npm run build
npm run smoke:public
npm run verify:production
ทดสอบ deployment ระยะไกล:
BASE_URL=https://your-deployment-url npm run smoke:public
เอกสารทดสอบ Closed Beta เพิ่มเติม: docs/closed-beta-runbook.md
เมื่อเริ่มทำงานต่อ ให้อ่านส่วนนี้ก่อน แล้วทำตามลำดับ:
git status -sb
git log --oneline -5
hivedzrwrrcnjrlirhtvnpm run lint && npm run build ทุกครั้งเมื่อมีการเปลี่ยน TypeScript/Next.js สำคัญBallDoenSai ไม่ใช่เว็บจัดอันดับฟุตบอลธรรมดา
มันคือแพลตฟอร์มที่จะทำให้ ทุกเกมกลายเป็นความทรงจำ ทุกผลงานกลายเป็นหลักฐาน และทุกเด็กเห็นเส้นทางการเติบโตของตัวเอง.
| คิวรายงานเนื้อหา, ซ่อน/แสดง Highlight และ storage policy ที่ตามสถานะการซ่อน |
| 14 |
sql/data-deletion-v1.sql | สิทธิ์ลบข้อมูลตาม PDPA + คิวคำขอปิดบัญชีสำหรับแอดมิน | 15 |