尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
식재료 등록 + 신체 지표 기반 AI 개인화 식단 PWA Phase 1 — 기반 세팅 ✅ 완료 • ✅ Next.js App Router + TypeScript strict 초기 세팅 • ✅ PWA 설정 (@serwist/next, viewport-fit=cover, iOS safe-area) • ✅ IndexedDB 스키마 설계 (userProfile, ingredients, bodyMetrics, mealHistory) • ✅ 4개 탭 라우팅 + BottomNav 레이아웃 • ✅ vitest + @testing-library 단위 테스트 환경 구성 • ✅ 단위 테스트 23개 (7개 파일) 전부 PASS • ✅ tdd-guard 훅 (최소 예외: app/sw.ts, lib/db, lib/ai, e2e) • ✅ Codex 3라운드 적대적 리뷰 완료 — 버그 5건 수정檢視完整 README ↗
식재료 등록 + 신체 지표 기반 AI 개인화 식단 PWA
| 영역 | 기술 |
|---|---|
| 프레임워크 | Next.js 16.2.6 (App Router, TypeScript strict) |
| PWA | @serwist/next 9.5.11 |
| 로컬 DB | IndexedDB via idb 8.0.3 |
| AI | Google Gemini (@google/genai 1.52.0, gemini-2.5-flash) |
| 린트/포맷 | Biome 2.x |
| 단위 테스트 | vitest 3.x + @testing-library/react + happy-dom |
| E2E 테스트 | Playwright 1.60.0 (시각 회귀) |
| 패키지 매니저 | pnpm 9.x |
| 배포 | Vercel |
app/
├── layout.tsx # 루트 레이아웃 (PWA 메타, viewport-fit=cover)
├── page.tsx # AI 채팅 탭 (홈)
├── api/chat/ # Gemini 스트리밍 API Route
├── onboarding/ # 온보딩 (성별·목표 입력)
├── ingredients/ # 식재료 등록 탭
├── body/ # 신체 지표 탭
├── settings/ # 설정 탭
└── sw.ts # Service Worker (serwist)
components/
└── layout/
└── BottomNav.tsx # 하단 탭 네비게이션
lib/
├── ai/
│ ├── types.ts # AI 타입 (UserContext, ChatSseEvent)
│ └── context.ts # 동적 시스템 프롬프트 생성
└── db/
├── index.ts # IndexedDB 초기화 (getDB, getLocalDateString)
├── types.ts # DB 타입 정의
├── userProfile.ts # 사용자 프로필 CRUD
├── ingredients.ts # 식재료 CRUD
├── bodyMetrics.ts # 신체 지표 CRUD
└── mealHistory.ts # 식사 기록 CRUD
pnpm dev # 개발 서버 (Turbopack)
pnpm build # 프로덕션 빌드 (webpack)
pnpm typecheck # TypeScript 타입 검사
pnpm check # Biome lint + format 검사
pnpm check:fix # Biome 자동 수정
pnpm test:unit # vitest 단위 테스트
pnpm test:unit:watch # vitest watch 모드
pnpm test:visual # Playwright 시각 회귀 테스트
✅ Next.js App Router + TypeScript strict 초기 세팅
✅ PWA 설정 (@serwist/next, viewport-fit=cover, iOS safe-area)
✅ IndexedDB 스키마 설계 (userProfile, ingredients, bodyMetrics, mealHistory)
✅ 4개 탭 라우팅 + BottomNav 레이아웃
✅ vitest + @testing-library 단위 테스트 환경 구성
✅ 단위 테스트 23개 (7개 파일) 전부 PASS
✅ tdd-guard 훅 (최소 예외: app/sw.ts, lib/db, lib/ai, e2e)
✅ Codex 3라운드 적대적 리뷰 완료 — 버그 5건 수정
| 수정 항목 | 내용 |
|---|---|
| iOS safe-area | env(safe-area-inset-bottom) 적용 (BottomNav + page) |
getRecentMealHistory 오프바이원 | days → days - 1 커트오프 수정 |
userProfile 경쟁 조건 | 고정 키 "user-profile" + db.get() 직접 조회 |
viewport-fit=cover 누락 | Next.js Viewport 메타에 viewportFit: "cover" 추가 |
| IndexedDB 프로미스 캐시 오염 | 실패 시 dbPromise = null 리셋 추가 |
✅ Gemini 스트리밍 API Route (/api/chat, SSE)
✅ 동적 context 주입 — 성별·목표·식재료·신체 지표를 시스템 프롬프트에 반영
✅ 채팅 UI (메시지 버블, 스트리밍 타이핑 인디케이터, "새 대화" 버튼)
✅ 오늘 대화 IndexedDB 저장 및 앱 재진입 시 복원
✅ 에러 분류 (429/RESOURCE_EXHAUSTED, 401/403, SAFETY, 503)
✅ AbortController 연동 — 새 대화 시 진행 중인 스트림 취소
✅ Codex 3라운드 적대적 리뷰 완료 — 버그 3건 수정
| 수정 항목 | 내용 |
|---|---|
| DB 에러 시 온보딩 강제 이동 | 프로필 에러만 리다이렉트, 나머지는 빈 값 처리 |
| streaming 상태 경쟁 조건 | abortRef 비교 가드로 이전 요청이 새 요청 상태 덮어쓰기 방지 |
| UTF-8 flush 누락 | done 시 decoder.decode() 호출로 잔여 바이트 처리 |
mealHistory 지원 추가)# .env.local (gitignore됨 — commit 금지)
GEMINI_API_KEY=AIza... # Google AI Studio에서 발급
# GEMINI_MODEL=gemini-2.5-flash # 선택: 모델 오버라이드
| 날짜 | 내용 |
|---|---|
| 2026-06-30 | Phase 3 완료: Gemini AI 채팅, SSE 스트리밍, context 주입, Codex 리뷰 3건 수정 / Phase 4 완료: VRT 8개 스냅샷 (채팅 화면 포함) |
| 2026-06-27 | Phase 1 완료: 기반 세팅, DB 스키마, 라우팅, 단위 테스트 23개, Codex 리뷰 5건 수정 / Phase 2 완료: 온보딩·식재료·신체지표·설정 실 기능, 단위 테스트 31개 |