Vibe Coding - Nền tảng đặt sân thể thao sportbooking.online
Sản phẩm - Xem nhanh không cần đọc.
Vibe Coding: Hành trình xây dựng sportbooking.online từ ý tưởng đến sản phẩm thực tế
Chia sẻ kinh nghiệm dùng AI-assisted development (vibe coding) để xây dựng một hệ thống đặt sân thể thao hoàn chỉnh — từ một developer solo đến một platform multi-tenant phục vụ nhiều câu lạc bộ.
Bối cảnh: Tại sao lại là "Vibe Coding"?
Cuối năm 2024, khái niệm "vibe coding" bắt đầu nổi lên — thay vì ngồi gõ từng dòng code, bạn mô tả ý tưởng cho AI và cùng nó xây dựng sản phẩm. Nghe có vẻ viễn tưởng, nhưng tôi đã thử và kết quả là sportbooking.online — một hệ thống đặt sân cầu lông online đang chạy production, phục vụ nhiều câu lạc bộ thực tế.
Tech Stack
Một trong những quyết định quan trọng nhất khi vibe coding là chọn tech stack mà AI hiểu tốt và có ecosystem mạnh:
- Next.js 15 (App Router) + React 19 — Server Components, SSG/ISR cho SEO, API Routes cho backend
- Supabase — PostgreSQL, Auth, Realtime, Row Level Security. Thay thế hoàn toàn một backend riêng
- TailwindCSS + shadcn/ui — UI nhanh, consistent, AI generate code chuẩn
- Google Genkit — AI content generation (blog, SEO content, user guide)
- Vercel — Deploy, Cron Jobs, Edge Functions, multi-domain
- Resend — Email notifications
- Supabase Storage — Image upload và CDN
Tại sao lại chọn stack này? Vì đơn giản là tiết kiệm. Chi phí hầu như bằng 0 nếu bạn dùng supabase với gói free, có thể nâng cấp lên nếu scaleable được hệ thống. Vercel -> Free. AI + Email notification -> Tạm thời free
Quá trình xây dựng: Từ MVP đến Production
Giai đoạn 1: MVP — Đặt sân cơ bản
Bắt đầu với blueprint đơn giản: hiển thị danh sách câu lạc bộ, chọn sân, chọn giờ, đặt lịch. Tôi mô tả từng feature cho AI và cùng nó build:
- Trang listing câu lạc bộ với filter theo loại sân
- Calendar chọn ngày, bảng slot 30 phút với color-coded status (Available, Booked, Blocked)
- Hệ thống pricing theo khung giờ (giờ vàng, giờ thường) và ngày (weekday/weekend)
- QR code thanh toán + upload proof of payment
- Auth bằng số điện thoại (convert sang email format
{phone}@badminton.vnđể dùng Supabase Auth)
Giai đoạn này mất khoảng 2-3 tuần. Phần lớn thời gian là iterate với AI để tinh chỉnh UX, không phải viết logic từ đầu. Phần UI/UX chủ yếu mình dùng google stitch để dựng idea cũng như lên ý tưởng
Giai đoạn 2: Admin Dashboard — Quản lý mọi thứ
Đây là phần phức tạp nhất. Admin dashboard có hơn 39 component files trong src/app/admin/_components/, mỗi file đảm nhiệm một chức năng riêng:
- Quản lý câu lạc bộ — CRUD clubs, courts, pricing, amenities
- Quản lý lịch đặt — Booking management, schedule calendar, fixed monthly bookings
- Quản lý nhân viên — Staff accounts, role-based access
- Quản lý khách hàng — Customer profiles, guest tracking
- Thống kê — Revenue charts (Recharts), booking trends, usage analytics
- Tin tức & Blog — Rich text editor (Tiptap), AI-powered blog writing
- SEO Management — Auto-generate landing pages, metadata management
- Subscription Plans — Tiered pricing (FREE/BASIC/PRO), quota enforcement
- Event Management — Sự kiện, time slots, participant tracking
- Club Crawler — Import data câu lạc bộ từ bên ngoài (Cheerio + Axios)
Mỗi feature tôi dùng Kiro Specs để plan trước khi code. Ví dụ, hệ thống Subscription Management có đầy đủ:
requirements.md— Yêu cầu chi tiếtdesign.md— Thiết kế kỹ thuật (database schema, API design)tasks.md— Breakdown thành từng task nhỏ
AI đọc spec rồi implement từng task. Tôi review, adjust, rồi move on. Flow này cực kỳ hiệu quả. Nói thêm nữa, khi đã có được spec từ kiro, có thể kết hợp dùng với Antigravity để hỗ trợ, chỉ cần Model Gemini Flash là đủ. Mọi thứ được AI xử lý rất nhanh chóng. Nhiệm vụ của chúng ta là test, test và test.
Giai đoạn 3: Multi-Tenant & SEO
Multi-tenant subdomain: Mỗi câu lạc bộ có subdomain riêng (ví dụ: caulonglinhdam.sportbooking.online). Middleware detect subdomain từ Host header, query database tìm club, set tenant context. Club owner đăng nhập vào admin chỉ thấy data của club mình.
SEO Pages tự động: Hệ thống generate 6 loại trang SEO từ data thực trong database:
- Theo thành phố:
san-cau-long-ha-noi - Theo quận:
san-cau-long-hoang-mai - Theo vị trí:
san-cau-long-gan-my-dinh(Haversine formula) - Theo giá:
san-cau-long-gia-re-ha-noi - Theo tiện ích:
san-cau-long-co-mai-che-ha-noi - Theo giờ:
san-cau-long-mo-dem-ha-noi
Mỗi khi admin save thông tin club → auto trigger API generate SEO pages → upsert vào database → ISR revalidate mỗi giờ. Không seed cứng, không hardcode — tất cả từ data thực.
Giai đoạn 4: Automation & Polish
- Cron Jobs — Vercel Cron chạy daily (check subscription expiry, auto-downgrade) và monthly (overage report, email notification)
- Email tự động — Cảnh báo quota 80%/90%/100%, thông báo 7 ngày trước hết hạn, báo cáo overage
- PDF Generation — Export user guide, owner guide (jsPDF + jspdf-autotable)
- QR Code — Generate QR thanh toán cho từng club
Tư duy tổ chức code: Steering Rules
Một bài học lớn: khi vibe coding, AI có xu hướng dump tất cả code vào một file. Nếu không có rules rõ ràng, chúng ta sẽ có những file 1000+ dòng không thể maintain. Và thật vậy luôn, khi muốn build nhanh sản phẩm, tôi dùng Antigravity nhưng khi nhìn lại code base thì hoảng hồn, lên 5-6K dòng code là bình thường. Vì vậy
Tôi tạo Steering Rules trong .kiro/steering/clean-code.md để AI tuân theo:
- Mỗi file tối đa ~300 dòng
- Mỗi feature tách thành file riêng trong _components/
- File đặt tên kebab-case, export PascalCase
- page.tsx chỉ chứa auth check + render component chính
- Schemas và types dùng chung đặt trong schemas.ts
- Không duplicate code — extract ra utility/hook
Kết quả? Admin dashboard có 39 files gọn gàng thay vì 1 file khổng lồ. Mỗi file có trách nhiệm rõ ràng. Khi cần sửa booking logic, tôi mở booking-manager.tsx. Khi cần sửa SEO, tôi mở seo-manager.tsx. Không bao giờ phải scroll qua hàng nghìn dòng code không liên quan.
Cấu trúc chuẩn cho mỗi route:
src/app/[route]/
├── page.tsx # Entry point — auth + loading + render
├── _components/
│ ├── schemas.ts # Zod schemas & types
│ ├── [feature]-manager.tsx # Component chính (~300 dòng)
│ └── [shared-component].tsx # Component dùng chung
Business Logic: Những bài toán thực tế
Hệ thống Pricing phức tạp
Mỗi club có pricing riêng, chia theo:
- Khung giờ (giờ vàng 17h-21h giá cao hơn)
- Ngày trong tuần (weekend giá khác weekday)
- Priority tiers (giờ nào ưu tiên hiển thị trước)
type Pricing = {
weekday: PriceTier[]; // Mỗi tier: timeRange + price + is_priority
weekend: PriceTier[];
};
Subscription & Quota Management
3 gói: FREE (3 sân, 100 booking/tháng), BASIC (10 sân, 1000 booking), PRO (30 sân, 3000 booking). Database functions xử lý real-time:
check_court_limit()— Kiểm tra trước khi tạo sân mớicheck_booking_quota()— Tính usage percentage, overageincrement_booking_count()— Tự động tính phí vượt mứcdecrement_booking_count()— Trừ khi hủy booking
Logic này chạy ở database level (PostgreSQL functions), không phải application level. Nhanh hơn, an toàn hơn, không bị race condition.
Role-Based Access Control
4 roles với quyền khác nhau:
- Admin — Toàn quyền, thấy tất cả clubs
- Club Owner — Chỉ thấy clubs mình quản lý
- Staff — Chỉ thấy schedule và booking
- Customer — Đặt sân, xem lịch của mình
Supabase RLS (Row Level Security) enforce ở database level. Kể cả API bị bypass, data vẫn an toàn.
Những bài học rút ra
1. Spec trước, code sau
Với mỗi feature lớn, tôi tạo Kiro Spec gồm 3 file: requirements → design → tasks. AI đọc spec và implement chính xác hơn nhiều so với mô tả bằng lời. Tôi có 5 specs cho 5 feature lớn nhất: subscription management, event booking, multi-tenant subdomain, recurring monthly booking, và migration từ Firebase sang Supabase.
2. Steering Rules là bắt buộc
Không có rules, AI sẽ viết code "chạy được" nhưng không maintainable. Steering rules giống như coding standards cho team — chỉ là "team" ở đây có một thành viên là AI.
3. Database-first thinking
Đẩy logic xuống database (PostgreSQL functions, RLS policies) thay vì xử lý ở application. AI generate SQL rất tốt, và logic ở database level đáng tin cậy hơn.
4. Iterate nhanh, đừng cầu toàn
21 migrations = 21 lần thay đổi database. Không có thiết kế hoàn hảo từ đầu. Ship MVP, nhận feedback từ chủ sân thực tế, rồi improve. Vibe coding cho phép bạn iterate cực nhanh — thay đổi một feature có thể chỉ mất vài giờ thay vì vài ngày.
5. AI giỏi generate, con người giỏi architect
AI viết code nhanh, nhưng quyết định kiến trúc vẫn là của bạn. Chọn multi-tenant hay single-tenant? SEO pages generate từ data hay hardcode? Pricing logic ở database hay application? Những quyết định này define sản phẩm, và AI không thể làm thay bạn.
Kết luận
Đây vừa là sản phẩm làm cho vui nhưng cũng là 1 sản phẩm thử build bằng Vibe Coding đúng nghĩa. Anh em dùng thử và test cho mình nhé. Mình luôn sẵn sàng đàm đạo cùng anh em và luôn Sẵn sàng nhận feedback để tự cải tiến sản phẩm.
All rights reserved