尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
RescueWalk — 유기견 산책 매칭 MVP 🐾 산책이 필요한 아이와, 함께 걸어줄 당신을 연결합니다. 유기견 보호소의 강아지와 산책 봉사자를 연결하는 반응형 웹앱 MVP입니다. Golden Path — 한 사이클이 끝까지 동작하고, 각 단계가 실제 상태를 바꿉니다. • 신청하면 신청 내역에 생기고, 새로고침해도 유지됩니다. • 방문예정 신청에서 "산책 완료 기록하기"를 누르면 신청이 산책완료로 바뀌고, 활동 기록에 일지가 추가되며 통계와 배지가 즉시 다시 계산됩니다. • 취소는 확인 다이얼로그를 거쳐 상태가 바뀌고, 같은 시간대가 다시 열립니다. • Next.js 14 (App Router) + TypeScript • Tailwind CSS — Soft Green / Cream / Warm White / Orange Accent 디자인 토큰 • Lucide Icons • 상태: React Context + localStorage 영속화 (데모 모드) • 배포: Vercel 바로 배포 가능 (vercel 또는 GitHub 연동)查看完整 README ↗
산책이 필요한 아이와, 함께 걸어줄 당신을 연결합니다.
보호소가 승인하는 유기견 산책 봉사 매칭 플랫폼입니다. 사진만 보고 고르는 서비스가 아니라, 신뢰(보호소 승인·운영 정보) + 안전(성향 공개·경험 매칭) + 참여 동기(내가 만든 영향) + 감정적 연결(다시 만나는 아이) 을 제품 루프 안에 넣었습니다.
탐색(오늘·이번 주 가능, 나에게 맞는 조건) → 상세(누구에게 맞는지·가능한 일정·반응·주의사항)
→ 신청 3단계(일정 → 참여자 정보 → 확인·약속) → 접수
→ 승인 → 방문 예정(만나는 곳·준비물·연락 흐름) → 산책 → 완료 기록(관찰 포함)
→ 활동 기록(함께 걸은 시간·다시 만난 아이·보호소에 전한 관찰) → 다시 산책
localStorage 영속화 (데모 모드)vercel 또는 GitHub 연동)npm install
npm run dev # http://localhost:3000
npm run build # 프로덕션 빌드
npm run check # lint + typecheck + 단위 테스트 (커밋 전 한 번)
npm test # 단위 테스트 (Vitest, 도메인 규칙)
npm run test:e2e # E2E (Playwright, 데스크톱·모바일) — build 후 실행
E2E 는 next start 를 직접 띄웁니다. 이미 서버가 떠 있으면 E2E_PORT=3000 npm run test:e2e 로 재사용합니다.
처음 한 번은 npx playwright install chromium 이 필요합니다.
화면(app·components)과 규칙(lib/domain)을 나눴습니다. 규칙은 React·브라우저에 의존하지 않는 순수 함수라서 단위 테스트로 고정하고, 화면은 그 결과를 그리기만 합니다.
app/ 라우트 (App Router)
dogs/page.tsx 목록 — 필터·정렬 상태는 URL 쿼리가 원본
dogs/[id]/apply/
useApplyFlow.ts 신청 흐름 상태·URL 단계·임시 저장·제출
steps.tsx 단계별 화면 (표현만)
error.tsx, not-found.tsx 오류·404 화면
sitemap.ts, robots.ts, manifest.ts
components/ 공용 UI (Dialog: 포커스 트랩·Esc·스크롤 잠금 / DogRail / Stepper …)
lib/
domain/
schedule.ts 운영 일정 — 휴무일·산책 요일·운영 시간·당일 마감·중복 → 가능한 시간, 다음 일정, 2주 창
dogSearch.ts 필터(언제·나에게 맞는 조건·지역…), URL ↔ 필터 직렬화, 정렬(빠른 일정 순, 쉬는 아이는 항상 뒤)
apply.ts 3단계 진입 조건, 연락처 형식·검증, 경험 매칭(경험자만), 안전 약속, 임시 저장 복원·미리 고른 일정
requests.ts 신청 상태 전이(승인·취소·완료+관찰), 진행 5단계 계산, 목록 묶기, 다음 산책
impact.ts 활동 영향(함께 걸은 시간·다시 만난 아이·보호소·관찰), 아이별 관계, 이정표
persist.ts 브라우저 저장값 검증 (깨진 항목만 걸러냄)
*.test.ts 위 규칙의 단위 테스트
store.tsx React Context 스토어 — 액션은 domain 함수를 호출만, 탭 간 동기화
storageKeys.ts 저장소 키 + 막힌 환경에서도 안전한 접근자
data/ 정적 데이터(보호소 운영·방문 안내, 아이별 매칭 정보)와 일정 규칙에 맞는 상대 날짜 시드
data.test.ts 데이터 무결성 — 모든 시간이 운영 시간 안, 시드가 휴무일에 잡히지 않음
labels.ts, visitGuide.ts 매칭 정보 표기, 방문 안내 공통 문구
calendar.ts 방문 일정 → 캘린더 파일(.ics, RFC 5545) — 한국 시각을 UTC 로, 하루 전 알림, 긴 줄 접기
useClock.ts 방문자의 지금 시각(서버 렌더 날짜와 다를 수 있어 브라우저에서만)
routes.ts 집중 화면(상세·신청) — 모바일에서 공용 헤더·하단 내비를 빼는 경로
e2e/ 사용자 흐름 E2E + 접근성·레이아웃·콘솔 기준
설계 메모
schedule.ts 로 계산해 화면마다 다르지 않습니다.
시각은 인자로 받고, 화면은 브라우저에서만 넣어 정적 페이지의 빌드 날짜가 섞이지 않게 합니다.?when=today&need=beginner)과 신청 단계(?step=2)를 주소에 둬서
공유·새로고침·브라우저 뒤로가기가 모두 자연스럽게 동작합니다. 알 수 없는 쿼리 값은 버립니다.localStorage 는 이전 버전·직접 수정으로 깨져 있을 수 있어
불러올 때 항목 단위로 검증합니다. 다른 탭의 변경은 storage 이벤트로 반영합니다.| 경로 | 화면 |
|---|---|
/ | 홈 — 지금 나에게 필요한 것 하나(다가오는 내 산책 / 다시 만나기 / 처음이라면), 지금 산책 가능한 아이(오늘·이번 주, 관심 지역 우선 — PC 는 좌우 화살표로 넘기는 한 줄), 안전 운영 방식, 보호소, 후기 |
/dogs | 강아지 목록 — 이름·품종·보호소 검색(?q=, 띄어쓰기 무시), 카드에서 난이도·사람 친화·필요한 경험·다음 일정·위치를 바로 비교(모바일은 가로형 행). 필터: 언제(오늘·이번 주) · 나에게 맞는 조건(초보 가능·힘이 약한 편·다른 강아지 OK·아이 동반, AND) · 지역·보호소 · 크기 · 난이도 · 성격(OR) |
/dogs/[id] | 강아지 상세 — 공유(휴대폰 공유 시트, 안 되면 링크 복사), 모바일은 사진을 지나면 이름·뒤로·찜과 섹션 목차(추천·일정·성격·산책·주의·보호소)가 위에 붙음. 이런 분께 추천(필요한 경험·리드줄 힘·사람·다른 강아지) → 가능한 일정(시간을 누르면 바로 신청) → 성격·이야기 → 산책할 때 모습 → 사람·동물 반응 → 꼭 지켜주세요 → 챙겨 오세요 → 보호소 안내 |
/dogs/[id]/apply | 신청 3단계 — 일정(7칸 달력: 같은 열 = 같은 요일이라 휴무 요일이 세로로 줄지어 보임, 날짜·시간이 스크롤 없이 한 화면) → 참여자 정보(각 칸이 왜 필요한지, 경험 매칭) → 확인·안전 약속 3가지. 상세에서 고른 일정은 채워진 채 시작, ?step= 뒤로가기, 새로고침 복원, 접수 후 뒤로가기 중복 방지 |
/complete/[rid] | 신청 접수 — 아이 얼굴 위 완료 표시, 진행 단계(지금은 승인 대기), 방문 정보·만나는 곳, 준비물, 캘린더에 추가([승인 대기] 표시) |
/requests | 신청 내역 — 진행 중 / 지난 신청, 방문일 지난 신청 표시 |
/requests/[id] | 신청 상세 — 접수·승인·방문 예정·산책·완료 진행 단계와 지금 할 일 하나, 바로가기(길찾기·보호소 전화·캘린더에 추가), 방문 정보(만나는 곳·오시는 길·주차·연락처·지도), 준비물 체크리스트(신청별로 이 브라우저에 기억), 연락 흐름, 기록(관찰 포함)·다시 산책 |
/activity | 활동 기록 — 함께 걸은 시간, 산책·만난 아이·다시 만난 아이·보호소, 보호소에 전한 관찰, 함께 걸은 아이 사진 카드와 다시 산책, 이정표(진행 막대), 달마다 묶은 타임라인 일지 |
/shelters, /shelters/[id] | 보호소 — 지금 운영 여부, 휴무, 바로가기(길찾기·전화·아이들 보기), 특징, 이번 주 날짜별 산책 가능 아이 수, 산책을 기다리는 아이, 방문 안내 전체 |
/guide | 봉사 가이드 — 참여 방법, 준비물, 현장 가이드, FAQ (목차가 헤더 아래 붙어 지금 읽는 곳을 표시) |
/me | 마이페이지 — 요약, 찜한 아이들(작은 사진 카드), 설정과 안내 목록(관심 지역·가이드·보호소·활동 기록·데모 데이터 초기화) |
localStorage에 저장됩니다.lib/data/seed.ts). 고정 날짜를 쓰면 "지난 날짜인데 방문예정", "휴무일에 방문" 같은 모순이 생기기 때문입니다.실제 사진이 적용되어 있으며, 모두 WebP로 최적화되어 총 2.6MB입니다.
public/images/
├── dogs/ 강아지 전신 사진 18장 (900×900)
│ └── face/ 얼굴 중심 크롭 썸네일 18장 (320×320) — 작은 아바타용
├── shelters/ 보호소 외관 사진 5장 (1200×900)
├── guide/ 봉사 가이드 사진 7장 (1200×900)
└── brand/ 제작사(미래에이아이랩) 로고 — 원본 그대로, 투명 배경
교체·추가 방법:
public/images/dogs/ 에 넣고 lib/data/dogs.ts 의 image 필드에 파일명 지정.
작은 아바타에 쓰이는 얼굴 썸네일은 같은 파일명으로 dogs/face/ 에 함께 넣습니다.public/images/shelters/ + lib/data/shelters.ts 의 image 필드.object-fit: cover 로 크롭되므로 레이아웃이 무너지지 않습니다.image 가 null 이면 자동 폴백: 강아지는 팔레트 기반 일러스트, 보호소는 소속 아이들의 얼굴 콜라주.
(현재 '행복한 쉼터'만 외관 사진이 없어 이 폴백이 적용되어 있습니다.)서비스 브랜드는 RescueWalk, 제작사 브랜드는 미래에이아이랩으로 층을 나눠 씁니다. 한 화면에 제작사 표기가 반복되지 않도록 두 곳으로만 제한했습니다.
| 위치 | 형태 |
|---|---|
| 모든 페이지 하단 | SampleBridgeCTA — 제작 표기 + 소개 + 상담 CTA (텍스트만, 로고 없음) |
| 푸터 | MiraeWordmark — 원본 로고 1회 (밝은 배경 전용: 로고가 짙은 남색) |
app/layout.tsx 의 metadata(creator/publisher/OpenGraph)에도 제작사를 명시해
링크 공유 시 노출됩니다.
샘플을 다 본 사용자를 제작사 인지 → 상담 전환 → 다른 샘플·홈페이지로 이어주는
공통 섹션입니다. app/layout.tsx 에 한 번 삽입되어 모든 페이지 하단(푸터 위)에
동일하게 노출됩니다.
components/SampleBridgeCTA.tsx CTA 섹션 본문 (다른 샘플에 그대로 복사 가능)
components/SampleBridgeSlot.tsx 경로별 노출 제어 (신청 폼 단계에서만 숨김)
lib/brand.ts 링크 · 문구 상수 ← 여기만 고치면 전체 반영
링크를 바꾸려면 → lib/brand.ts 의 MIRAE_LINKS
| 키 | 현재 값 | 쓰이는 곳 |
|---|---|---|
consult | miraeailab.com/business-diagnosis | 메인 CTA "우리 회사도 만들어보기" |
samples | miraeailab.com/business-services | 서브 "다른 샘플 보기" |
home | miraeailab.com/ | 서브 "미래AI랩 홈페이지" |
문구를 바꾸려면 → lib/brand.ts 의 MIRAE_CTA_COPY
(eyebrow 배지 / kicker 제작 표기 / title 헤드라인 / description 회사 소개 /
note 버튼 보조문구 / consultLabel·samplesLabel·homeLabel 버튼 라벨).
특정 페이지에서만 다르게 쓰려면 <SampleBridgeCTA title="..." consultHref="..." />
처럼 같은 이름의 props 로 덮어쓸 수 있습니다.
노출 경로를 바꾸려면 → components/SampleBridgeSlot.tsx 의 HIDDEN_PATHS.
현재 /dogs/[id]/apply 만 제외되어 있습니다(3단계 신청 폼 진행 중에 외부 링크를
노출하면 샘플의 핵심 전환 흐름을 중간에 이탈시키기 때문). 신청이 끝난
/complete/[rid] 에서는 정상 노출되어, 흐름을 다 본 직후에 CTA를 만납니다.
디자인·모션 원칙
prefers-reduced-motion 에서는 sweep이 숨고 무한 애니메이션이 모두 정지모바일 하단 sticky mini CTA는 넣지 않았습니다. 이 샘플은 이미 하단 Bottom Navigation과 강아지 상세의 Sticky 신청 버튼을 쓰고 있어, 세 번째 고정 바가 겹치면 핵심 전환(산책 신청)을 가립니다.
MVP는 데모 모드로 동작하지만, 데이터 계층이 교체 가능하게 분리되어 있습니다.
lib/types.ts — shelters, dogs, walk_slots(availableTimes), walk_requests, favorites, activity_logs, testimonialslib/store.tsx 의 addRequest / cancelRequest / confirmRequest / completeWalk /
toggleFavorite / toggleInterestRegion 액션을 Supabase 쿼리로 대체
(confirmRequest 는 데모 전용 — 실제 서비스에서는 보호소 관리자 화면이 호출)lib/domain/*)은 저장소와 무관하므로 그대로 재사용합니다. 서버로 옮길 때도 같은 함수로
입력을 검증하면 화면과 서버의 판단이 어긋나지 않습니다.lib/data/*.ts → Supabase 테이블 fetch로 대체pending(신청완료) ─ confirmRequest ─▶ confirmed(방문예정) ─ completeWalk ─▶ completed(산책완료)
└──────────── cancelRequest ────────┴──▶ cancelled(취소)
구현과 테스트: lib/domain/requests.ts, lib/domain/requests.test.ts
completeWalk 는 activity_logs 에 기록(requestId 연결, 관찰 포함)을 추가해 활동 영향·이정표에 바로 반영됩니다.
각 전이 시각(confirmedAt / completedAt / cancelledAt)을 저장해 신청 상세의 진행 단계에 씁니다.
화면의 진행 단계는 저장 상태 + 방문 시각으로 계산합니다(visitStages):
pending→승인 대기, confirmed+방문 전→방문 예정, confirmed+방문 시각 이후→산책(기록 대기), completed→완료.
Dog Availability: available(일정에 따라 신청 가능) / unavailable(치료·휴식으로 신청 중단)
lib/routes.ts).
상세는 사진을 지나면 접히는 앱 바 + 섹션 목차(지금 읽는 섹션 표시, 이동해도 주소에 #을 남기지 않음)DateCell)·같은 표기(휴무/마감/–)tangerine-600 #B9520C 위 흰 글자 4.9:1,
보조 글자 ink-400 #766C62 는 크림 배경에서 5.0:1. 밝은 tangerine-500 은 장식(아이콘·하트)에만:focus-visible),
신청 단계가 바뀌면 새 단계 제목으로 포커스 이동, 대화상자는 포커스 트랩·Esclib/store.tsx), 그래도 화면 오류가 나면
app/error.tsx에서 다시 시도 / 데모 데이터 되돌리기를 제공hoverOnlyWhenSupported로 탭한 버튼에 hover 색이 남지 않게withJosa()로 받침에 맞게("장군과", "보리와")body[data-modal-open]),
푸터 하단은 그 버튼 높이만큼 여백 확보app/globals.css 상단 주석에 정리(radius 12/16/20/24, shadow card/card-hover/overlay,
= 숫자·날짜 한 덩어리의 줄바꿈 금지 — 여러 항목이 이어지는 목록에는 쓰지 않음)CI(.github/workflows/ci.yml)가 push·PR 마다 아래를 모두 통과해야 합니다.
| 단계 | 내용 |
|---|---|
| Lint · Typecheck | ESLint(next/core-web-vitals), tsc --noEmit (strict) |
| 단위 테스트 | lib/**/*.test.ts 165개 — 캘린더 파일(시간대 변환·글자 이스케이프·75바이트 접기·[승인 대기]), 이정표 진행률, 검색(이름·품종·보호소·지역, 띄어쓰기 무시, 다른 조건과 AND), 운영 일정(휴무·산책 요일·당일 마감·중복·다음 일정), 필터·정렬·URL 왕복(이전 주소 호환), 3단계 진입·경험 매칭·약속, 임시 저장 복원·미리 고른 일정, 상태 전이 멱등성·진행 5단계, 활동 영향·이정표, 저장값 검증, 데이터 무결성(모든 시간이 운영 시간 안, 시드가 휴무일에 잡히지 않음) |
| E2E (데스크톱 1280 · 모바일 Pixel 7, 45개 × 2) | 신규 사용자 전체 여정(처음 방문 → 초보 가능한 아이 → 상세에서 일정 선택 → 신청 → 승인 → 기록 → 첫 이정표), 캘린더 파일 내려받기·준비물 체크 유지, 찜 해제 되돌리기, 바텀시트 끌어 닫기, 칸을 떠날 때 검증·고른 일정 바꾸기, 이정표 진행 막대·달별 일지, 가이드 목차, 카드 판단 정보, 검색(새로고침 유지·칩으로 해제), 모바일 상세 목차, 필터 주소 유지, 경험자만 아이 신청 차단, 휴무일 선택 불가(같은 요일은 같은 열), 뒤로/앞으로·새로고침 복원, 중복 신청 방지, 진행 단계, 관찰 기록, 다시 만난 친구, 취소(Esc), 초기화, 빈·깨진 데이터, 404 |
| 접근성 | axe-core WCAG 2.1 AA + best-practice 위반 0건 (주요 11개 화면 × 2개 기기, 별도 점검 22개 화면 × 2개 기기 + 대화상자 + 목차가 펼쳐진 모바일 상세) |
| 레이아웃 · 콘솔 | 360 |
.tnum