- Cấu hình Git, tạo repo cho project và commit checkpoint đầu tiên
- Nhận lời mời vào repo TicTac, clone về và chạy được trên máy của bạn, làm việc trên branch cá nhân và biết cập nhật code khi khóa học đổi
- 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, nhận lời mời và clone app TicTac (quyền chỉ đọc) chạy trên máy thật, làm việc trên branch cá nhân, cập nhật code khi khóa học đổi, và khai stack của khóa trong rules file cho AI coding tool.
Trong 10 ngày tới bạn sẽ sửa code liên tục, tự tay hoặc nhờ AI, và sẽ 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 chuyện đó xảy ra: Git để quay lại bất kỳ lúc nào. Sau đó bạn tải app đích của khóa về chạy thử, và cuối bài viết một rules file để AI biết khóa này dùng stack nào.
Phần 1: Cấu Hình Git Và Commit Đầu Tiên
Bạn đã cài Git ở mục "Chuẩn bị" của bài 1. Bỏ qua bài đó thì quay lại cài Git theo bảng ở mục ấy trước. Giờ khai báo tên và email một lần, Git ghi chúng vào mỗi commit:
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, bạn 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
Khóa đi kèm một repo hoàn chỉnh, dan-tech-academy/flutter-tictac-101: app TicTac thật, 5 màn hình, chạy trên cả Android lẫn iOS. Bạn không gõ lại nó từ đầu. Từ module 3, mỗi bài mở đúng phần repo bài đó dạy, bạn đọc rồi tự sửa một thứ nhỏ.
Repo này là repo riêng. Ở chế độ đọc thử, link trên trả 404.
Mua khóa xong, hệ thống tự gửi lời mời vào repo cho đúng tên tài khoản GitHub bạn nhập lúc mua. Bấm View invitation trong email GitHub gửi tới, hoặc đăng nhập đúng tài khoản ấy, mở github.com/notifications (hay vào thẳng https://github.com/dan-tech-academy/flutter-tictac-101/invitations) rồi bấm Accept invitation. Lời mời hết hạn sau 7 ngày, nên nhận sớm.
Đã mua mà vẫn 404? Lời mời đến vài phút sau khi thanh toán. Kiểm hộp thư (cả mục spam) và xem bạn có đăng nhập đúng tài khoản đã nhập lúc mua không. Quá 30 phút chưa thấy, hoặc lời mời đã hết hạn, thì liên hệ hỗ trợ kèm tên tài khoản GitHub để được gửi lại.
Nhận lời mời xong, clone repo vào cùng thư mục development đang chứa Flutter từ bài 1:
# macOS, Linux
mkdir -p ~/development && cd ~/development
git clone https://github.com/dan-tech-academy/flutter-tictac-101.git
cd flutter-tictac-101
# Windows (PowerShell)
New-Item -ItemType Directory -Force -Path $HOME\development | Out-Null
Set-Location $HOME\development
git clone https://github.com/dan-tech-academy/flutter-tictac-101.git
Set-Location flutter-tictac-101
Repo private nên lần clone đầu Git có thể hỏi đăng nhập. Mật khẩu GitHub gõ thẳng trong terminal sẽ không được nhận. Cài GitHub CLI, chạy gh auth login một lần bằng đúng tài khoản đã nhận lời mời (chọn HTTPS, và Yes khi được hỏi có dùng tài khoản này cho Git không), rồi clone lại. Báo Repository not found dù đã nhận lời mời nghĩa là máy đang nhớ tài khoản khác: chạy lại gh auth login bằng đúng tài khoản.
Kiểm môi trường bằng script của khóa
Repo có sẵn script kiểm tra máy theo yêu cầu của khóa. Trong thư mục flutter-tictac-101, chạy bản kiểm tra trước. Bản này chỉ báo cáo, không cài gì:
bash scripts/init.sh --check # macOS, Linux
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\init.ps1 -Check # Windows
Script in kế hoạch đánh số: làm gì, trong thư mục nào, tải từ URL nào. Đã cài Flutter ở bài 1 thì kế hoạch dùng luôn bản đó. ExecutionPolicy Bypass chỉ áp dụng cho đúng lệnh này.
Đã làm bài 1 và mở terminal mới thì kết quả trông như sau (đã lược bớt, đường dẫn là của máy bạn):
flutter on PATH: /home/<bạn>/development/flutter/bin/flutter (channel stable)
Flutter version: 3.47.7 (lessons were tested on 3.47.7 or newer)
Numbered plan
-------------
1. Use the Flutter already on PATH. No download.
2. Flutter's bin folder is already on PATH. Nothing needs adding.
3. Run: flutter --version
4. Run: flutter doctor
5. Run: flutter pub get
Check only (--check).
Nothing was installed. No file was changed.
Result: Flutter stable is already on this machine. A normal run would still run flutter doctor and flutter pub get.
Bước 2 có thể khác, tùy máy:
/home/<bạn>/.bashrc already has the PATH line. Open a new terminal so that line is picked up. Nothing needs adding.: dòng PATH của bài 1 đã nằm trong file shell nhưng terminal này mở từ trước. Mở terminal mới rồi kiểm lại.Line to add yourself: export PATH="/home/<bạn>/development/flutter/bin:$PATH": máy chưa có Flutter. Khi đó bước 1 làgit clone --depth 1 --branch stable https://github.com/flutter/flutter.gitvào~/development/flutter, và dòng cuối bắt đầu bằngResult: Flutter is not installed yet. This machine can install it.
Flutter cũ hơn 3.47.7 thì script vẫn dùng bản đó và nhắc bạn tự chạy flutter upgrade. Dòng cuối bắt đầu bằng Result: This run will not install Flutter. thì đọc lý do in ngay sau, ví dụ máy chưa có git, sửa xong rồi chạy lại.
Đồng ý thì chạy lại, bỏ --check (Windows: -Check), gõ y khi được hỏi. Bấm Enter là dừng, máy giữ nguyên. Script chạy flutter doctor rồi flutter pub get cho repo. Lệnh sau có thể sửa pubspec.lock hoặc analysis_options.yaml, chạy git status để xem.
Script không tự sửa PATH. Muốn nó thêm giúp, chạy kèm cờ:
bash scripts/init.sh --add-to-path # macOS, Linux
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\init.ps1 -AddToPath # Windows
Trên macOS và Linux, script ghi một dòng PATH vào file shell, kẹp giữa hai dòng comment đánh dấu, và bỏ qua nếu file đã có dòng đó. Trên Windows, script hỏi thêm một câu riêng, Add Flutter's bin folder to your user PATH? [y/N]. Gõ y thì nó chỉ đổi PATH của tài khoản bạn. PATH của cả máy không bao giờ bị đổi. Xong thì mở terminal mới.
Không chạy script cũng được: flutter pub get trong thư mục repo là đủ để tải package.
Rồi mở app trên máy ảo hoặc máy thật bằng một trong hai script dưới đây. Cả hai giữ phiên ở foreground, nên phím r (hot reload) và R (hot restart) của 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 # macOS, Linux: bật Android emulator rồi chạy debug
Hai script này viết bằng bash nên chỉ chạy trên macOS và Linux. Trên Windows, dùng flutter run như bài trước.
Chơi vài ván: đổi kích thước bàn, đổi độ khó, thắng một ván để xem màn kết quả. 6 module tới bạn sẽ đọc hiểu code của mọi thứ vừa thấy.
Script iOS dùng simulator đang bật nếu có. Nếu không, nó ưu tiên "iPhone 15 Pro" rồi "iPhone 14 Pro" (393x852, đúng kích thước bản thiết kế), sau đó "iPhone 16 Pro" (402x874). Simulator khác vẫn chạy, bố cục co giãn hơi khác bản gốc.
Trước khi sửa dòng nào, tạo một branch cá nhân. Mọi thay đổi của bạn nằm trên đó, còn master giữ nguyên làm bản gốc để đối chiếu:
git checkout -b hoc-tictac
git branch --show-current # in ra: hoc-tictac
Branch này chỉ nằm trên máy bạn, và bạn dùng nó suốt khóa. Quyền của bạn trên repo là chỉ đọc: clone và kéo code mới được, nhưng không đẩy lên và không fork được. Thử git push thì Git có thể báo branch chưa có upstream trước; làm theo gợi ý của nó thì GitHub trả lỗi kiểu:
remote: Permission to dan-tech-academy/flutter-tictac-101.git denied to <tên-bạn>.
fatal: unable to access 'https://github.com/dan-tech-academy/flutter-tictac-101.git/': The requested URL returned error: 403
Lỗi 403 này là bình thường. Mọi commit vẫn nằm nguyên trên máy bạn, và chỉ ở đó, nên hãy commit thường xuyên theo quy tắc dưới đây.
Phần 3: Quy Tắc Checkpoint
Cả khóa chỉ có một quy tắc:
Commit mỗi khi app ở trạng thái chạy được và bạn sắp thay đổi thứ gì đó.
Quy tắc này cà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, khỏi gỡ tay từng thay đổi. git log --onelinelà nhật ký học của bạn: đã đổi gì, theo thứ tự nào, và bạn quay về được mốc nào. Commit càng đều thì nhật ký càng đủ.
Hai lệnh 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ó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à ở giai đoạn đầu, tự gõ là cách học nhanh nhất.
Nếu đã dùng một tool (Claude Code, Cursor, Gemini CLI, Codex...), bạn nhờ nó giải thích đoạn code chưa hiểu, việc bạn sẽ làm nhiều khi đọc repo TicTac, và sinh phần code lặp lại. Tool cần đọc được cả project và làm 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. Thiếu 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, hoặc một package đã ngừng bảo trì.
Tạo file ở gốc project (tên tùy tool: CLAUDE.md, .cursorrules, AGENTS.md...). Tạo trong hello_flutter để dùng ngay ở Phần 6, rồi chép một bản sang gốc flutter-tictac-101, nơi bạn làm việc từ module 3:
# Project Rules
- Flutter >= 3.47.7, Dart >= 3.13.5, 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.
Khối "Stack cố định" chặn AI kéo Riverpod hoặc BLoC vào. Cả hai đều tốt, nhưng gộp state và dependency injection làm một, trong khi khóa này cần bạn thấy hai thứ đó tách rời: module 3 dạy MVVM không dùng package nào, module 4 mới đưa provider vào.
Con số 3 cũng có lý do. pubspec.yaml của repo TicTac có đúng ba dependency runtime, vậy mà app vẫn có 5 màn hình, lưu thành tích, dark mode và animation. Thêm package nào là thêm một thứ phải nâng cấp mỗi lần Flutter đổi version.
Dòng cuối bắt AI giải thích từng thay đổi, và lời giải thích đó 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, chữ to, kèm một dòng phụ nhỏ hơn. Tự gõ hay nhờ AI đều được, miễn giữ trình tự sau:
- Đọ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, cứ tận dụng.
- Nếu tốt: chạy
git add .rồigit commit -m "feat: centered greeting". - Nếu hỏng:
git checkout .và làm lại. Cùng lắm bạn mất vài phút.
Từ module 3, bạn chạy đúng vòng lặp này trong thư mục flutter-tictac-101, trên branch cá nhân của bạn (hoc-tictac).
Phần 7: Cập Nhật Code Khi Khóa Học Đổi
Thỉnh thoảng repo và bài học được cập nhật cùng lúc. Khi nhận thông báo cập nhật, làm ba bước sau trong thư mục flutter-tictac-101.
1. Lưu phần đang làm trên branch cá nhân của bạn:
git add -A
git commit -m "bai lam cua toi"
git add -A gom mọi thay đổi trong cả repo, kể cả file bạn đã xóa. Git báo nothing to commit nghĩa là bạn đã lưu hết, đi tiếp.
2. Về master và kéo code mới:
git checkout master
git pull
Bạn chưa sửa gì trên master, nên git pull không gặp conflict. Sau đó chạy lại flutter pub get phòng khi bản mới đổi pubspec.yaml.
3. Tạo branch mới từ master để học tiếp:
git checkout -b hoc-tiep
Lần cập nhật sau, đặt tên khác (hoc-tiep-2...) vì tên cũ đã có.
Rules file ở Phần 5 đã được commit vào branch cũ ở bước 1, nên branch mới chưa có nó. Mang nó sang (đổi CLAUDE.md thành tên file của tool bạn dùng, bỏ qua nếu bạn không dùng AI tool):
git checkout hoc-tictac -- CLAUDE.md
Lần cập nhật sau, thay hoc-tictac bằng tên branch bạn vừa rời.
Branch cũ (hoc-tictac) vẫn nằm trên máy bạn với đủ commit, xem lại bằng git log --oneline hoc-tictac. Đừng học tiếp trên branch cũ: bài trên web đã theo code mới, nên code trong bài sẽ không còn khớp với code trên máy bạn.
Module setup kết thúc ở đây. Từ module sau bạn học Dart, với mục tiêu đọ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).