Bỏ qua đến nội dung

Usecase: Solo Dev Xây Tính Năng Authentication

Một developer làm việc một mình có thể xây dựng tính năng authentication hoàn chỉnh, an toàn, và có test coverage đầy đủ -- chỉ bằng cách tuân theo quy trình Superpowers.


Bối Cảnh

Bạn là một solo developer đang làm việc trên một project Todo App. Project đã có đầy đủ tính năng CRUD todos, filter, drag-and-drop, dark/light theme -- nhưng chưa có bất kỳ hệ thống authentication nào. Ai mở app cũng thấy tất cả todos. Yêu cầu mới là:

  • Thêm đăng ký người dùng (register)
  • Thêm đăng nhập (login) với email + password
  • Bảo vệ truy cập app (login gate) -- chưa đăng nhập thì không vào được
  • Viết test cho toàn bộ tính năng

Project chưa có hệ thống auth. Không có ai review code cho bạn. Bạn làm việc một mình từ đầu đến cuối.

Tech stack:

  • React 19 + TypeScript + Vite
  • Tailwind CSS + shadcn/ui
  • localStorage (chưa có backend)
  • Vitest + Testing Library (testing)
  • Web Crypto API (SHA-256 password hashing)

Bạn Sẽ Học Được Gì

Trong bài hướng dẫn này, bạn sẽ áp dụng năm kỹ năng cốt lõi của Superpowers:

  1. Brainstorming & Design -- Thiết kế trước khi code
  2. Writing Plans -- Chia nhỏ công việc thành các task rõ ràng
  3. TDD -- Viết test trước, implement sau
  4. Thực thi & Subagents -- Dispatch song song để tăng tốc
  5. Debugging & Verification -- Xác minh kết quả bằng bằng chứng thực tế

Mục tiêu cuối cùng: bạn sẽ có một hệ thống authentication hoàn chỉnh với 39 test cases đều pass, được xây dựng hoàn toàn theo quy trình có kỷ luật.


Từng Bước Thực Hành

Bước 1: Brainstorm Thiết Kế Auth

Trước khi viết bất kỳ dòng code nào, bạn bắt đầu bằng việc brainstorm. Bạn gọi skill brainstorming:

/superpowers:brainstorming "Tôi cần thêm authentication cho project Todo của tôi. Hãy brainstorm trước khi viết code."

AI khám phá codebase trước, nắm được tech stack hiện tại (React 19, TypeScript, Vite, Tailwind, shadcn/ui, localStorage), rồi bắt đầu hỏi từng câu hỏi một:

Câu hỏi 1: "Anh muốn authentication để làm gì?"

  • A) Chỉ để bảo vệ access vào app (login gate) -- data vẫn lưu localStorage, mỗi user trên cùng browser thấy cùng data
  • B) Mỗi user có data riêng -- cần backend/database để lưu todos theo user
  • C) Đơn giản chỉ demo flow login/register cho mục đích học tập

Bạn chọn: A) Login gate -- chỉ cần bảo vệ truy cập, data giữ nguyên ở localStorage.

Câu hỏi 2: "Anh muốn dùng phương thức đăng nhập nào?"

  • A) Email + Password (tự build form login/register)
  • B) Social login (Google, GitHub...) -- dùng Firebase Auth, Supabase Auth, Auth0
  • C) Cả hai

Bạn chọn: A) Email + Password -- tự build, không dependency bên ngoài.

Câu hỏi 3: "Anh có cần Register (đăng ký tài khoản mới) không?"

  • A) Cần cả Register + Login -- user tạo tài khoản mới, lưu vào localStorage
  • B) Chỉ Login -- dùng tài khoản mock/hardcoded

Bạn chọn: A) Cần cả Register + Login.

Câu hỏi 4: "Anh có cần chức năng Quên mật khẩu không?"

  • A) Có -- hiển thị form reset password (mock)
  • B) Không cần -- giữ đơn giản

Bạn chọn: B) Không cần -- giữ đơn giản chỉ Login + Register.

Câu hỏi 5: "Về UI, anh muốn trang Login/Register trông như thế nào?"

  • A) Trang riêng biệt (full page) -- redirect đến trang login nếu chưa đăng nhập
  • B) Modal/Dialog -- hiện overlay trên app hiện tại
  • C) Để em đề xuất

Bạn chọn: A) Trang riêng biệt.

Sau khi thu thập đủ thông tin, AI trình bày 3 cách tiếp cận:

## Approach A: React Context + localStorage (Recommended)
- Tạo AuthContext quản lý state đăng nhập
- Users lưu trong localStorage (email + hashed password dùng Web Crypto API)
- Protected route bằng một wrapper component đơn giản
- Login/Register là full-page, khi authenticated mới render App
- Pros: Đơn giản, không thêm dependency, phù hợp kiến trúc hiện tại
- Cons: Không có routing thật (chỉ conditional render)

## Approach B: React Router + Context
- Thêm react-router-dom để có routing thật (/login, /register, /)
- Pros: URL-based navigation, mở rộng thêm pages sau
- Cons: Thêm dependency mới, phức tạp hơn cho app đơn giản

## Approach C: TanStack Router + Context
- Type-safe routing cho React
- Pros: Type-safe, modern
- Cons: Overkill cho scope hiện tại

## Khuyến nghị
Approach A. Project hiện tại là single-page app, không có routing.
Thêm router chỉ để có 2 page (login + app) thì hơi thừa.
Conditional render với AuthContext là đủ và giữ project đơn giản.

Bạn đồng ý với Approach A. AI tiếp tục trình bày thiết kế chi tiết từng phần:

Phần 1 -- Architecture & Data Model:

User type:
  - id: string (crypto.randomUUID)
  - email: string
  - passwordHash: string (SHA-256 via Web Crypto API)
  - createdAt: string

AuthContext provides:
  - user: User | null
  - isAuthenticated: boolean
  - isLoading: boolean
  - login(email, password) → success/error
  - register(email, password) → success/error
  - logout()

localStorage keys:
  - todo-app-users — mảng users đã đăng ký
  - todo-app-session — user ID của session hiện tại
  - todo-app-todos — giữ nguyên (shared giữa tất cả users)

Phần 2 -- Component Structure:

<StrictMode>
  <AuthProvider>
    <App>
      ├── isLoading = true → Loading indicator
      │
      ├── isAuthenticated = false → <AuthPage>
      │     ├── <LoginForm />
      │     └── <RegisterForm />
      │
      └── isAuthenticated = true → <TodoApp>
            ├── <Header> (+ logout button, user email)
            ├── <FilterBar>
            ├── <TodoInput>
            ├── <TodoList>
            └── <EditTodoDialog>
    </App>
  </AuthProvider>
</StrictMode>

Phần 3 -- UI Design: AI show 2 mockup trực tiếp trên browser qua visual companion: Centered Card vs Split Layout. Bạn chọn Split Layout -- chia đôi màn hình, bên trái branding + bên phải form.

Phần 4 -- Validation & Error Handling:

  • Register: email format, email trùng, password 6-128 ký tự, confirm password khớp
  • Login: email/password không rỗng, sai thì hiện toast error (dùng Sonner có sẵn)
  • Session: check khi app mount, tự động logout nếu user ID invalid

Phần 5 -- Testing Strategy: Vitest + Testing Library, mock localStorage cho storage tests.

AI viết design spec vào docs/superpowers/specs/2026-03-18-authentication-design.md và chạy spec review tự động 3 vòng -- phát hiện 7 issues (thiếu loading state, thiếu password max length, thiếu stale session handling...) và fix hết trước khi chuyển sang viết plan.

Lưu ý Superpowers: Spec review tự động là một phần quan trọng của quy trình. AI dispatch một code-reviewer agent để review spec trước khi bạn approve. Điều này đảm bảo spec không thiếu sót. Xem thêm Brainstorming để biết chi tiết.


Bước 2: Superpowers Viết Plan Chi Tiết

Dựa trên design spec đã được phê duyệt, AI gọi skill writing-plans và chia công việc thành 8 task:

## Plan: Authentication Implementation

### Task 1: Hash Utility
- File: src/lib/hash.ts, src/lib/hash.test.ts
- SHA-256 hashing bằng Web Crypto API
- Verification: npx vitest run src/lib/hash.test.ts

### Task 2: Auth Storage
- File: src/lib/auth-storage.ts, src/lib/auth-storage.test.ts
- CRUD users + session management trong localStorage
- Verification: npx vitest run src/lib/auth-storage.test.ts

### Task 3: Auth Context
- File: src/contexts/auth-context.tsx, src/contexts/auth-context.test.tsx
- AuthProvider + useAuth hook
- Login, register, logout, session restore, isLoading, stale session
- Verification: npx vitest run src/contexts/auth-context.test.tsx

### Task 4: Login Form
- File: src/components/login-form.tsx, src/components/login-form.test.tsx
- Form validation, submit, error display
- Verification: npx vitest run src/components/login-form.test.tsx

### Task 5: Register Form
- File: src/components/register-form.tsx, src/components/register-form.test.tsx
- Validation, duplicate email, password too long, submit
- Verification: npx vitest run src/components/register-form.test.tsx

### Task 6: Auth Page
- File: src/components/auth-page.tsx
- Split layout container, switch giữa login/register
- Không cần test riêng (covered bởi form tests + auth-context tests)

### Task 7: Wire Up
- Sửa: src/main.tsx, src/App.tsx, src/components/header.tsx
- Wrap App trong AuthProvider, conditional render, logout button
- Verification: npx tsc --noEmit && npx vitest run

### Task 8: Smoke Test
- Chạy full test suite + TypeScript check
- Verification: npx tsc --noEmit && npx vitest run

Mỗi task có file cụ thể, có lệnh verification cụ thể, và test code chi tiết sẵn trong plan.

Plan cũng được review tự động 2 vòng -- phát hiện issues (thiếu crypto.subtle polyfill cho test environment, thiếu stale session test case, thiếu password > 128 chars test...) và fix hết.

Lưu ý Superpowers: Plan thực tế chứa đầy đủ code cho từng test file và từng implementation file, với format checkbox - [ ] cho mỗi step. Xem thêm Writing Plans để biết chi tiết format chuẩn.

AI hỏi bạn:

"Plan đã hoàn chỉnh với 8 task. Anh muốn thực thi bằng Subagent-Driven (song song) hay Inline Execution (tuần tự)?"

Bạn chọn: Subagent-Driven -- dispatch nhiều agent song song để tăng tốc.


Bước 3: Implement Bằng Subagent-Driven Development

AI sử dụng skill subagent-driven-development để thực thi plan. Thay vì làm tuần tự từng task, AI phân tích dependency giữa các task và dispatch song song khi có thể.

Batch 1: Task 1 + Task 2 (Song song)

Task 1 (Hash Utility) và Task 2 (Auth Storage) không phụ thuộc nhau, nên được dispatch song song cho 2 agent riêng biệt:

AgentTaskTest CasesKết quả
Agent 1Hash Utility (hash.ts + hash.test.ts)3 tests: hash consistency, different inputs → different hashes, returns hex string3/3 PASS
Agent 2Auth Storage (auth-storage.ts + auth-storage.test.ts)6 tests: get/save users, add user, find by email, session CRUD, user validation6/6 PASS

Cả 2 agent hoàn thành, AI verify tests và commit:

git commit -m "feat: add SHA-256 password hashing utility"
git commit -m "feat: add auth storage with user and session management"

Batch 2: Task 3 + Task 4/5 (Song song)

Task 3 (Auth Context) cần Task 1+2, nhưng Task 4 (Login Form) và Task 5 (Register Form) chỉ cần props interface, nên có thể chạy song song:

AgentTaskTest CasesKết quả
Agent 3Auth Context (auth-context.tsx + test)6 tests: initial state, register + auto-login, login after register, session restore, logout, stale session cleanup6/6 PASS
Agent 4Login + Register Forms12 tests: validation, submit, error display, duplicate email, password too long12/12 PASS

Commit sau khi verify:

git commit -m "feat: add AuthContext with login, register, session management"
git commit -m "feat: add login and register form components"

Batch 3: Task 6 + Task 7 (Tuần tự, inline)

Task 6 (Auth Page) và Task 7 (Wire Up) nhỏ và phụ thuộc nhau nên AI implement trực tiếp:

  • Tạo auth-page.tsx -- split layout container
  • Sửa main.tsx -- wrap App trong <AuthProvider>
  • Sửa App.tsx -- conditional render AuthPage / TodoApp + loading state
  • Sửa header.tsx -- thêm user email + logout button
git commit -m "feat: add AuthPage with split layout"
git commit -m "feat: wire up authentication — AuthProvider, conditional render, header logout"

Quy trình TDD ở mỗi task: Mỗi agent đều tuân theo chu kỳ: viết test trước (RED) → implement code tối thiểu (GREEN) → verify tests PASS → commit. Xem thêm TDD để hiểu chi tiết.


Bước 4: Verification -- Xác Minh Toàn Bộ

Tất cả 8 task trong plan đã hoàn thành. Bây giờ Task 8: Smoke Test -- chạy full verification.

TypeScript Check

npx tsc --noEmit
# (No output) — Clean, no errors

Full Test Suite

npx vitest run
✓ src/lib/hash.test.ts (3 tests)
✓ src/lib/auth-storage.test.ts (6 tests)
✓ src/contexts/auth-context.test.tsx (6 tests)
✓ src/components/login-form.test.tsx (5 tests)
✓ src/components/register-form.test.tsx (7 tests)
  ... (và các test files khác của project)

Test Files  8 passed
Tests       39 passed

Git Log -- 7 commits sạch sẽ

6b92624 feat: wire up authentication — AuthProvider, conditional render, header logout
37d68f1 feat: add AuthPage with split layout
...     feat: add login and register form components
...     feat: add AuthContext with login, register, session management
...     feat: add auth storage with user and session management
878af65 feat: add SHA-256 password hashing utility
cc6e2f9 initial: todo app before authentication

39/39 tests PASS. TypeScript clean. 7 commits. Đây là tuyên bố hợp lệ vì dựa trên bằng chứng thực tế.


Kết Quả

Sau khi hoàn thành toàn bộ quy trình, bạn có:

Tính năng Authentication hoàn chỉnh:

  • Trang Login -- đăng nhập bằng email + password
  • Trang Register -- đăng ký tài khoản mới với validation đầy đủ
  • Login gate -- chưa đăng nhập thì không vào được app
  • Logout -- nút logout trên header, hiển thị email user
  • Session persistence -- reload page vẫn giữ đăng nhập

39 test cases pass 100% bao phủ các trường hợp:

  • Utility layer: hash function, localStorage CRUD
  • Context layer: login/register flow, session restore, stale session cleanup
  • UI layer: form validation, error display, submit handling
  • Edge cases: email trùng, password quá dài (>128 ký tự), session invalid

Cấu trúc file mới:

src/
  contexts/
    auth-context.tsx          ← AuthProvider + useAuth hook
  components/
    auth-page.tsx             ← Split layout container
    login-form.tsx            ← Form đăng nhập
    register-form.tsx         ← Form đăng ký
  lib/
    hash.ts                   ← SHA-256 helper
    auth-storage.ts           ← CRUD users + session trong localStorage

Files sửa:
  src/main.tsx                ← Wrap App trong AuthProvider
  src/App.tsx                 ← Conditional render auth/todo + loading state
  src/components/header.tsx   ← Thêm email + logout button

Key Takeaways

1. Solo dev vẫn cần quy trình

Khi không có ai review code cho bạn, quy trình Superpowers đóng vai trò như một "đồng nghiệp ảo." Brainstorm buộc bạn suy nghĩ kỹ trước khi code. TDD buộc bạn viết test trước khi implement. Verification buộc bạn chứng minh mọi thứ hoạt động trước khi tuyên bố xong.

Không có quy trình, solo dev dễ rơi vào bẫy: viết code tùy hứng, không có test, tuyên bố "xong" khi chưa xác minh.

2. Brainstorm trước giúp tránh over-engineering

Trong bước brainstorm, AI đã đề xuất cả React Router và TanStack Router. Nhưng vì bạn đã làm rõ yêu cầu từ đầu (login gate, single-page app, chưa có backend), bạn chọn phương án đơn giản nhất: React Context + localStorage + conditional render.

Nếu không có brainstorm, nhiều developer sẽ tự động thêm router, backend, database "cho chắc." Kết quả là mất thời gian gấp 3 lần cho một tính năng chưa cần.

3. Spec review tự động phát hiện lỗ hổng

Spec review 3 vòng đã phát hiện 7 issues mà bạn có thể bỏ sót: thiếu loading state (flash AuthPage khi reload), thiếu password max length (DoS risk), thiếu stale session handling... Những lỗ hổng này được fix trước khi viết một dòng code nào.

4. Subagent-Driven Development tăng tốc đáng kể

Thay vì implement tuần tự 8 task, AI dispatch song song: Task 1+2 cùng lúc, Task 3 + Task 4/5 cùng lúc. Tổng thời gian implementation giảm đáng kể nhờ parallelism.

5. Plan chi tiết giúp không bị lạc hướng

Với 8 task rõ ràng, mỗi task có code sẵn trong plan, bạn luôn biết task tiếp theo là gì. Không có lúc nào bạn phải ngồi suy nghĩ "bây giờ làm gì tiếp."

Đối với solo dev, đây là đặc biệt quan trọng. Khi làm việc một mình, rất dễ bị sao nhãng hoặc nhảy lung tung giữa các phần của project.

6. 39 test cases là "người review" tự động

Mỗi test case là một assertion rõ ràng. Khi bạn thay đổi code -- refactor, thêm tính năng mới, sửa bug -- bạn biết ngay lập tức nếu có gì bị phá vỡ. 39 tests chạy trong vài giây. Nhanh hơn bất kỳ cách test thủ công nào.

7. Verification gate đảm bảo không tuyên bố "xong" khi chưa thật sự xong

Bao nhiêu lần bạn nói "xong rồi" mà không chạy test? Bao nhiêu lần AI nói "đã implement xong" mà không show output?

Smoke test cuối cùng -- TypeScript clean + 39/39 test pass -- loại bỏ hoàn toàn khả năng tuyên bố sai. Bạn chỉ được nói "xong" khi có bằng chứng thực tế trong terminal.


Solo dev không có nghĩa là làm việc không kỷ luật. Superpowers cho bạn một quy trình mà ngay cả team lớn cũng phải tôn trọng: brainstorm trước khi code, plan trước khi làm, test trước khi implement, review tự động trước khi approve, và xác minh trước khi tuyên bố. Một người với quy trình tốt sẽ luôn thắng một người không có quy trình -- bất kể kinh nghiệm.