- Cài Git, tạo repo cho project và commit checkpoint đầu tiên
- Clone app TicTac của khóa và chạy được nó trên máy của bạn
- Viết rules file khai báo stack của khóa để AI coding tool không sinh code lệch hướng
Git checkpoint, clone app đích và rules file cho AI
Commit theo checkpoint, clone app TicTac chạy trên máy thật, và khai stack của khóa trong rules file cho AI coding tool.
Bạn sắp sửa code liên tục trong 10 ngày tới - tự tay hoặc nhờ AI. Cả hai đều có lúc làm hỏng thứ đang chạy tốt. Bài này dựng lưới an toàn trước khi điều đó xảy ra: Git để quay lại bất kỳ lúc nào. Có Git rồi, bạn tải luôn app đích của khóa về chạy thử. Cuối bài là một rules file để AI biết khóa này dùng stack nào.
Phần 1: Cài Git Và Commit Đầu Tiên
Nếu chưa có Git, tải từ git-scm.com. Cấu hình identity một lần:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
flutter create đã sinh sẵn .gitignore chuẩn cho Flutter, chỉ cần khởi tạo repo:
cd hello_flutter
git init
git add .
git commit -m "chore: project setup, app runs on device"
Phần 2: Clone Và Chạy App Đích
Vừa có Git, việc đầu tiên đáng làm với nó: tải app bạn sẽ học suốt khóa về máy.
Khóa này đi kèm một repo hoàn chỉnh - dan-tech-academy/flutter-tictac-101. Đó là app TicTac thật, 5 màn hình, chạy được trên cả Android lẫn iOS. Bạn không gõ lại nó từ đầu. Từ module 3 trở đi, mỗi bài sẽ mở đúng phần repo mà bài đó dạy, đọc, rồi bạn tự sửa một thứ nhỏ trong đó.
Repo này là repo riêng. Quyền đọc được mở cho bạn sau khi mua khóa, qua một lời mời gửi vào email GitHub của bạn. Nếu bạn đang xem bài này ở chế độ đọc thử, link trên sẽ trả 404 - đó không phải link hỏng.
Đã mua mà vẫn 404: lời mời được gửi tự động vài phút sau khi thanh toán xong, nên kiểm hộp thư (cả mục spam) và trang github.com/notifications. Quá 30 phút chưa thấy thì liên hệ hỗ trợ - đừng nghĩ bạn gõ sai lệnh.
Tải về và chạy:
git clone https://github.com/dan-tech-academy/flutter-tictac-101.git
cd flutter-tictac-101
flutter pub get
Rồi mở nó trên máy ảo hoặc máy thật. Repo có sẵn hai script, cả hai giữ phiên ở foreground nên phím r (hot reload) và R (hot restart) bạn vừa học ở bài trước vẫn dùng được:
scripts/run-ios.sh # macOS: bật iOS Simulator rồi chạy debug
scripts/run-android.sh # bật Android emulator rồi chạy debug
Không dùng script cũng được - flutter run như bài trước là đủ.
Chơi vài ván trước khi đi tiếp. Đổi kích thước bàn, đổi độ khó, thắng một ván để xem màn kết quả. Mọi thứ bạn vừa thấy trên màn hình đều có code trong repo vừa clone, và 6 module tới bạn sẽ đọc hiểu đúng số code đó.
Script iOS ưu tiên simulator "iPhone 15 Pro" / "iPhone 14 Pro" / "iPhone 16 Pro" vì bản thiết kế của app được vẽ ở đúng kích thước 393x852. Dùng simulator khác vẫn chạy, chỉ là bố cục co giãn khác bản gốc một chút.
Phần 3: Quy Tắc Checkpoint
Một quy tắc duy nhất, theo bạn cả khóa:
Commit mỗi khi app ở trạng thái chạy được và bạn sắp thay đổi thứ gì đó.
Vì sao quy tắc này sống còn khi làm việc với AI:
- AI có thể sửa 5 file một lần. Kết quả hỏng thì
git checkout .đưa bạn về trạng thái tốt trong 2 giây, thay vì gỡ tay từng thay đổi. - Lịch sử commit sạch là bằng chứng portfolio: người xem repo thấy bạn làm việc có kỷ luật.
Hai lệnh cứu mạng cần thuộc lòng:
git checkout . # vứt mọi thay đổi chưa commit, quay về checkpoint gần nhất
git log --oneline # xem danh sách checkpoint
Phần 4: Công Cụ AI Là Tùy Chọn, Không Bắt Buộc
Khóa này không yêu cầu AI coding tool nào. Mọi bài đều có code đầy đủ để bạn tự gõ, và tự gõ ở giai đoạn đầu là cách học nhanh nhất.
Nếu bạn đã dùng một tool (Claude Code, Cursor, Gemini CLI, Codex...), nó giúp được ở hai việc: giải thích đoạn code bạn chưa hiểu, và sinh phần code lặp đi lặp lại. Việc đầu tiên bạn sẽ làm rất nhiều khi đọc repo TicTac. Điều kiện duy nhất: tool phải đọc được cả project và tuân theo một rules file.
Phần 5: Rules File - Khai Báo Stack Một Lần
Rules file là văn bản AI tool tự đọc trước mỗi lần làm việc. Không có nó, AI sinh code Flutter theo "thói quen trung bình của internet": mỗi lần một thư viện state management khác nhau, hoặc một package đã ngừng bảo trì. Với nó, mọi đoạn code sinh ra trong 10 ngày tới đều cùng một hướng.
Tạo file ở gốc project (tên tùy tool: CLAUDE.md, .cursorrules, AGENTS.md...):
# Project Rules
- Flutter >= 3.44, Dart >= 3.12, Material 3.
- Kiến trúc MVVM: domain/ (model + thuật toán, KHÔNG import Flutter),
data/ (repository + service), ui/<feature>/view_model/ (ChangeNotifier),
ui/<feature>/widgets/ (widget). View không chứa phép tính.
- Stack cố định - đúng 3 dependency runtime, không hơn:
- State + dependency injection: package `provider` (^6.1.5)
- Lưu local: `shared_preferences` (^2.5.5) - không ORM, không codegen
- Icon: `material_symbols_icons` (^4.2960.0)
- dev_dependencies: `flutter_lints` (^6.0.0), `fake_async` (^1.3.1)
- KHÔNG thêm package state management khác (riverpod, bloc), service
locator, ORM, router, sinh code bằng codegen, hay package gọi mạng.
- Ưu tiên StatelessWidget; chỉ dùng StatefulWidget khi state thuần cục bộ
của UI (ví dụ animation controller).
- Null safety triệt để: không dùng ! trừ khi có lý do ghi rõ bằng comment.
- Khi sửa code: chỉ sửa file liên quan trực tiếp đến yêu cầu, không refactor thứ khác.
- Khi thêm package: nói rõ thêm gì vào pubspec.yaml và vì sao.
- Giải thích ngắn gọn mỗi thay đổi bằng tiếng Việt.
Ba dòng đáng chú ý nhất:
- Khối "Stack cố định" là hàng rào. Không có nó, AI mặc định kéo Riverpod hoặc BLoC vào - đều là thư viện tốt, nhưng chúng gộp state và dependency injection thành một khái niệm, và khóa này cần bạn nhìn thấy hai khái niệm đó tách rời. Module 3 dạy MVVM không dùng package nào cả, module 4 mới đưa
providervào đúng vai trò của nó. - Con số 3 không phải để khoe tối giản. Mở
pubspec.yamlcủa repo TicTac vừa clone mà đếm: đúng ba dependency runtime, và app vẫn có 5 màn hình, lưu thành tích, dark mode, animation. Mỗi package thêm vào là một thứ nữa phải nâng cấp, phải chờ khi Flutter đổi version. Rules file giữ cho AI không âm thầm nới con số đó ra. - Dòng cuối ép AI giải thích, và lời giải thích chính là tài liệu học của bạn.
Phần 6: Chạy Thử Vòng Lặp Sửa - Xem - Commit
Thử ngay với hello_flutter: đổi màn hình chính thành một lời chào ở giữa màn hình, chữ to, kèm một dòng phụ nhỏ hơn. Tự gõ, hoặc nhờ AI - cách nào cũng được. Điều quan trọng là trình tự, và trình tự này theo bạn cả khóa:
- Đọc code trước khi chạy, kể cả khi chưa hiểu hết.
- Lưu và hot reload xem kết quả - vòng phản hồi của Flutter nhanh, tận dụng nó.
- Nếu tốt:
git add . && git commit -m "feat: centered greeting". - Nếu hỏng:
git checkout .và làm lại. Bạn mất vài phút, không mất buổi tối.
Bước 3, bước 4 là toàn bộ giá trị của bài này. Có checkpoint thì mọi thử nghiệm đều revert được dễ dàng.
Module setup kết thúc. Từ module sau, bạn học Dart thật sự - với mục tiêu rất cụ thể: đọc hiểu mọi dòng code trong app vừa chạy. Lộ trình phía trước: Dart (module 1), widget (module 2), MVVM (module 3), dependency injection với provider (module 4), navigation (module 5), rồi ráp tất cả lại (module 6).