← Cockpit Wireframes Pages by level Navigation map
Pages — sign-in and onboarding▾
Shipped app (old grammar)Components · 공유 키트상세 페이지 — 플랫 언어Session Card · 밴드 없는 카드
홈 · Home
Home · 홈
시작 · Entry
Onboarding · 시작
ArchiveStrip Map · 세션 스트립 전체 시나리오Headers · 헤더 아이콘Card Continuity · 카드 = 상세의 예고편Session Hero · 더 조용한 공유 카드 (제안)Session Share Card · 히어로 = 공유 카드Session List Frame · 날짜 섹션 · 패널 필터 · 2+2 카드Compaction — 일정 · 코트 · 스코어카드Compaction — 클럽 상세 · 홈Compaction — 기록 · 프로필Live anchor — 진행 중 밴드Density · 카드 밀도토스트 — 리디자인 제안Club List · 클럽Clubs · 클럽클럽 상세 — 여섯 탭 플랫운영 섹션 — 플랫 목표위저드 내비게이션 — 결정 보드드래프트 복원 — 무음 복원클럽 조 편성 — 모델 결정 보드게스트 → 회원 — 심사 흐름Page polish — titled postsWeb app — desktop layoutProduct questions — openWeb app — desktop adaptation, round 2Visual tone — pure white, flat rows, one Tag, a colour budgetLibrary — chrome, surfaces, rows, labelsLibrary — controls, overlays, states, formsLibrary — page patterns, scaling, motionLibrary — additions from the pagesEmpty-once — 프로필 빈 섹션Notification groups — 할 일 밴드 그룹화Profile Cockpit · 프로필 압축Session Detail — Redesign · 일정Venue Detail — Redesign · 테니스장Profile Detail — Redesign · 프로필Tournament Detail — Redesign · 대항전Applicant Detail — Redesign · 가입 심사Canvas Migration — 회비 · 멤버 · 규칙Record Detail — Redesign · 기록Venue Finder · 코트 찾기Venue Filters · 코트 필터 재구성Notifications · 알림Panel Placement · 하단 고정
For owner review — 1 open question, below

Pages — sign-in and onboarding

Sign-in, the three onboarding steps, the version gate and the pages a shared link opens, in the app and on the web.

Open for you
  • 본인인증, in the owner’s order (owner review 4, confirmed by the page review of 2026-10-28): 본인인증, then 약관 동의, then 첫 시작. The four providers (PASS, 토스, 네이버, 카카오) are our own buttons and go straight to that provider’s app on the KG이니시스 통합인증 channel of PortOne v2 (directAgency); 다른 방법으로 인증 opens the vendor’s window for the rest, and Danal 휴대폰 본인확인 is the fallback channel (D3). Still open with the vendor (EXT-19): whether the 통합인증 CI may key a person, and Kakao’s own CI paperwork. Under 14 is refused inside the vendor window where the channel allows it (D5); a foreigner’s country is ZZ or one tap (D6); at sign-up for everyone (D8); the display name is the verified name or the nickname (D9); the vendor-facing name stays neutral (D10). Approve, or change?
  • Shared links: the card is the page’s own Block, full-bleed ink with the lockup in the door’s place (D1); no live count on the image (D2); the fee on the page (D3); dues and join method on the invite page (D4); /lb stays a club teaser (D5); no host on the signed-in preview (D6); names out of the share text (D7); a revocable token for /p later (D8). Approve, or change?

L0-01시작

The first screen when signed out: the provider buttons (Kakao and Naver, then Apple on iOS or Google on Android and the web), and email sign-in as the quiet second route.

DABUSI

코트 위에서 만나요

카카오 로그인
네이버 로그인
Apple로 로그인
이메일로 로그인
이용약관개인정보 처리방침
9:41
iOS Kakao, Naver and Apple, equal in size; email is the quiet link (not built: the start page and provider sign-in wait for W5)
9:41
DABUSI

코트 위에서 만나요

카카오 로그인
네이버 로그인
Google 로그인
이메일로 로그인
이용약관개인정보 처리방침
Android and web Kakao, Naver and Google; a 24 gesture inset (not built: the start page and provider sign-in wait for W5)
States
DABUSI

코트 위에서 만나요

카카오 로그인
네이버 로그인
Apple로 로그인
이메일로 로그인
이용약관개인정보 처리방침
9:41
Busy Only the tapped provider spins; the rest wait inert (not built: the start page and provider sign-in wait for W5)
DABUSI

코트 위에서 만나요

카카오 로그인을 취소했어요
카카오 로그인
네이버 로그인
Apple로 로그인
이메일로 로그인
이용약관개인정보 처리방침
9:41
Cancelled A danger line above the button, no Notice (not built: the start page and provider sign-in wait for W5)
로그인이 필요해요
DABUSI

코트 위에서 만나요

카카오 로그인
네이버 로그인
Apple로 로그인
이메일로 로그인
이용약관개인정보 처리방침
9:41
From a link A Notice states that sign-in is needed; the link’s destination is kept (built on the email sign-in page for now: the start page waits for W5)
DABUSI

코트 위에서 만나요

카카오 로그인
네이버 로그인
Apple로 로그인
이메일로 로그인
이용약관개인정보 처리방침
9:41
오프라인이에요
다시 시도
Offline The strip under the status bar; buttons off (built on the email sign-in page for now: the start page waits for W5)
Email sign-in
이메일로 로그인
이메일
minjun@example.com
비밀번호
•••••••••
로그인
9:41
L0-02Ready 로그인 is the one action; no back yet, because the start page it returns to waits for W5
이메일로 로그인
이메일
name@example.com
이메일을 입력해 주세요
비밀번호
비밀번호를 입력해 주세요
로그인
9:41
qwertyuiop
asdfghjkl
⇧zxcvbnm⌫
123spacereturn
L0-02Empty, pressed Both fields marked, focus on the first
이메일로 로그인
이메일
minjun@example.com
비밀번호
•••••••••
이메일 또는 비밀번호가 맞지 않아요
로그인
9:41
L0-02Doesn’t match One line for either field, plain words under the password, input kept
이메일로 로그인
StackHeader 56 (no back until the start page exists, W5; the title 이메일로 로그인: a pushed page’s title lives in its Header, never as a heading in the content), 24, Field 이메일 70, 32, Field 비밀번호 70 (92 with its line), CTA band 102.ReadssignInWithEmail(email, password); the same two fields on web /login. The server error keeps the input.Taps로그인: signs in and replaces to the destination. The eye shows the password. With a field empty a press marks both and focuses the first: two inputs are pending, so the primary stays enabled. No back until the start page exists (W5); then back is 시작. Typing in the password clears the mismatch line. In the app a dev-credentials button sits in the page body below the fields, only when its env pair exists (not drawn: a fixed band has no slot under it).Spokenh1 이메일로 로그인, the Header’s title; the fields are named "이메일, 필수" and "비밀번호, 필수"; an error adds "입력 오류" to the name and is announced when it appears. First stops: "뒤로", "이메일", "비밀번호".RulingsThe one field grammar; validate on press with two or more inputs pending. Paste and password managers are allowed. The mismatch error is the one support line: no line under it sends a Kakao account back to Kakao (a line under a field is a meta line, §1.16; the cohesion pass (the owner, 2026-10-25)).
Interim: email sign-up
DABUSI

코트 위에서 만나요

이메일로 가입
이메일로 로그인
이용약관개인정보 처리방침
9:41
L0-03Start The ball button starts an email sign-up (not built: email sign-up and its mail wait for W5)
이메일로 가입
이메일
minjun@example.com
비밀번호
•••••••••
인증 메일 받기
9:41
L0-03Sign up Two fields; the password rule shows only as the error once it is broken (not built: email sign-up and its mail wait for W5)
이메일로 가입
메일을 보냈어요minjun@example.com으로 메일을 보냈어요. 메일의 안내를 따라 주세요. 메일이 없으면 스팸함을 확인해 주세요
메일 다시 보내기
9:41
L0-03Sent The same screen for every address, so it never says whether one has an account; one way forward: send again (not built: email sign-up and its mail wait for W5)
앱 이름

이미 가입한 이메일이에요

이 이메일로 가입한 계정이 있어요. 아래 버튼을 누르면 바로 로그인할 수 있어요.
로그인하기
비밀번호 재설정
요청한 적이 없다면 이 메일은 무시해도 괜찮아요
9:41
L0-03Already registered: the mail The only place that says the address has an account: one line, 로그인하기 (a one-tap link), 비밀번호 재설정 (not built: email sign-up and its mail wait for W5)
이메일로 가입 (only if the OAuth route slips)
StackStart: the entry band with the ball 이메일로 가입 (lg) and the ghost 이메일로 로그인 (the email route reads the same in every variant, §1.19; the cohesion pass (the owner, 2026-10-25)). Sign-up: the header with its title 이메일로 가입, Field 이메일, Field 비밀번호 (its one rule, 8 or more characters with a letter and a number, is the error’s text once it is broken), CTA band 인증 메일 받기. Sent: the same header over an EmptyState with one tonal button, shown for every address, so the screen never says whether it has an account. Already registered is the mail, not a screen of the app (read in the mail app): the name slot, the h1 이미 가입한 이메일이에요, one reading line, one lg button 로그인하기, the quiet link 비밀번호 재설정 and the foot line for a mail nobody asked for.ReadsA client signUp and Supabase email confirmation; the profile row is created at the first sign-in (unverified).Taps인증 메일 받기: the sent state; 메일 다시 보내기 resends; the mail's link opens the app and continues to 본인인증. In the already-registered mail 로그인하기 is a one-tap sign-in link (it replaces to the destination) and 비밀번호 재설정 starts a reset.RulingsDrawn only as the alternative if the provider route slips (EXT-11): the ball button is then the screen's one coloured action. The target frames have no self-serve email sign-up.
English, 200% and dark
DABUSI

See you on the court

Login with Kakao
Login with Naver
Sign in with Apple
Sign in with email
TermsPrivacy
9:41
English Each provider keeps its own label (not built: the start page and provider sign-in wait for W5)
DABUSI

코트 위에서 만나요

카카오 로그인
네이버 로그인
Apple로 로그인
이메일로 로그인
이용약관개인정보 처리방침
9:41
200% text The buttons grow with their labels; the lockup does not (not built: the start page and provider sign-in wait for W5)
DABUSI

코트 위에서 만나요

카카오 로그인
네이버 로그인
Apple로 로그인
이메일로 로그인
이용약관개인정보 처리방침
9:41
Dark Brand fills stay as they are; Apple turns white (not built: the start page and provider sign-in wait for W5)
시작 · AuthGate, LoginScreen
StackStatus 44 (Android: 24, in flow), then the stacked lockup (180 wide, 194 with its clear space) and the tagline 17/24·600 secondary, centred above the band. CTA band, entry: 16, the provider buttons 52 each and 12 apart, 12, ghost 이메일로 로그인 md 44, 12, links row 18 (44 targets), then max(16, inset). Three providers: 316 on iOS (inset 34) and 306 on Android (inset 24); one provider (the interim email contingency) 188. No header, no tab bar. A cancelled flow adds the danger line (22 + 8) above the first button.ReadsAuthGate renders LoginScreen while unauthenticated (web twin /login). Today useAuth().signInWithEmail; the target adds signInWithOAuth(provider) for Kakao and Naver (Supabase PKCE, no native SDK; Naver is a custom provider) and for Google on Android and the web, and the native Apple sign-in on iOS. Errors go through getAuthErrorMessage, never the raw message.TapsA provider: its own page and back, then the destination for a known account or 본인인증 for a new one. 이메일로 로그인: the email form (push). 이용약관 and 개인정보 처리방침: the document page (push). A signed-out deep link keeps its destination (returnTo on web, the path on mobile).SpokenThe tagline is the h1; the lockup is an image named 다붓이. First stops: "카카오 로그인", "네이버 로그인", "Apple로 로그인" (Android and web: "Google 로그인"), "이메일로 로그인", "이용약관".RulingsProvider buttons (CTA band, entry): Kakao #FEE500 with a black symbol, Naver #03A94D with a white N, Apple black (white on dark), Google white with a 1 stroke; all 52 tall, radius 12, full width and 12 apart, in the provider’s own system font. iOS shows Kakao, Naver, Apple (App Review 4.8: an app with a social sign-in must offer Sign in with Apple); Android and the web show Kakao, Naver, Google. Same size and shape for all, so no provider is more prominent; the brand fills are exempt from the one-ball rule. Email is sign-in only. Cancelled is a 15/22·600 danger line, never a Notice. Offline: the strip under the status bar and every button off.

L0-04온보딩

Three steps after the first provider login, in the owner’s order: 본인인증, 약관 동의, then the first action. 1/3 says why we verify and offers PASS, 토스, 네이버 and 카카오 as four equal buttons, each going straight to that provider’s app, with 다른 방법으로 인증 as the quiet link to the vendor’s own window; the provider’s app and the vendor’s window follow in grey (not ours), and the app checks the result and moves on with no result screen of its own. 2/3 is the consent group; 3/3 is the first action. The verified name and birth date fill the profile.

Ideal: the check in order (ours in colour, the provider’s and the vendor’s in grey)
1/3
본인인증을 해 주세요
한 사람이 한 계정만 쓰도록 확인해요. 클럽 회비와 경기 기록을 믿을 수 있게요.
주민등록번호는 받지 않아요
받는 정보는 이름, 생년월일, 휴대폰 번호, 중복 가입 확인용 정보예요
PASS로 인증
토스로 인증
네이버로 인증
카카오로 인증
다른 방법으로 인증
9:41
1 Ours: 1/3 본인인증 Why first, then four providers of equal weight; 주민등록번호 is never asked (not built: waits for the identity vendor (EXT-19))
토스 앱토스 앱에서 인증 요청을 승인하면 끝나요. 끝나면 이 앱으로 돌아와요
9:41
2 Not ours: the 토스 app The provider’s own app asks once: 인증 요청, one approval. PASS, 네이버 and 카카오 look the same; the app switch and the return are the system’s (not built: waits for the identity vendor (EXT-19))
KG이니시스 통합인증
네이버
PASS
토스
금융인증서
카카오
신한
KB모바일
삼성패스
휴대폰 본인확인
9:41
2, or not ours: the vendor’s window Behind 다른 방법으로 인증: the vendor lists its methods, 휴대폰 본인확인 among them. Drawn only to show the step (not built: waits for the identity vendor (EXT-19))
1/3
본인인증을 해 주세요
한 사람이 한 계정만 쓰도록 확인해요. 클럽 회비와 경기 기록을 믿을 수 있게요.
주민등록번호는 받지 않아요
받는 정보는 이름, 생년월일, 휴대폰 번호, 중복 가입 확인용 정보예요
PASS로 인증
확인 중…
네이버로 인증
카카오로 인증
다른 방법으로 인증
9:41
3 Ours: back, checking No result screen: the provider already said done. The tapped button spins while the server checks (not built: waits for the identity vendor (EXT-19))
2/3
약관에 동의해 주세요
전체 동의
[필수] 서비스 이용약관에 동의합니다
보기
[필수] 개인정보 처리방침에 동의합니다
보기
[필수] 개인정보 국외 이전에 동의합니다
보기
[선택] 위치 정보 수집·이용에 동의합니다
보기
[선택] 마케팅 푸시 알림 수신에 동의합니다
보기
동의하고 계속
9:41
4 Ours: 2/3 약관 동의 Required ticked by the person; none pre-ticked
건너뛰기
3/3
어떻게 시작할까요?
클럽에 가입할래요
초대 코드로 가입하거나 클럽을 찾아요
매치로 칠래요
근처에서 모이는 매치에 참석해요
클럽을 만들래요
총무가 되어 우리 클럽을 시작해요
9:41
5 Ours: 3/3 첫 시작 Three Cells; the header’s 건너뛰기 leaves; no ball action
1/3 states
1/3
본인인증을 해 주세요
한 사람이 한 계정만 쓰도록 확인해요. 클럽 회비와 경기 기록을 믿을 수 있게요.
주민등록번호는 받지 않아요
받는 정보는 이름, 생년월일, 휴대폰 번호, 중복 가입 확인용 정보예요
PASS로 인증
여는 중…
네이버로 인증
카카오로 인증
다른 방법으로 인증
9:41
Busy: opening the provider The tapped provider spins while its app opens; the other three and the link wait (not built: waits for the identity vendor (EXT-19))
1/3
본인인증을 해 주세요
한 사람이 한 계정만 쓰도록 확인해요. 클럽 회비와 경기 기록을 믿을 수 있게요.
주민등록번호는 받지 않아요
받는 정보는 이름, 생년월일, 휴대폰 번호, 중복 가입 확인용 정보예요
본인인증을 취소했어요
PASS로 인증
토스로 인증
네이버로 인증
카카오로 인증
다른 방법으로 인증
9:41
Cancelled The provider’s app was closed or backed out of: one quiet danger line, no error page (not built: waits for the identity vendor (EXT-19))
1/3

본인인증을 해 주세요

한 사람이 한 계정만 쓰도록 확인해요. 클럽 회비와 경기 기록을 믿을 수 있게요.
주민등록번호는 받지 않아요
받는 정보는 이름, 생년월일, 휴대폰 번호, 중복 가입 확인용 정보예요
PASS로 인증
토스로 인증
네이버로 인증
카카오로 인증
다른 방법으로 인증
9:41
오프라인이에요
다시 시도
Offline The strip under the status bar; the buttons are off (not built: waits for the identity vendor (EXT-19))
1/3
본인인증을 해 주세요
한 사람이 한 계정만 쓰도록 확인해요. 클럽 회비와 경기 기록을 믿을 수 있게요.
주민등록번호는 받지 않아요
받는 정보는 이름, 생년월일, 휴대폰 번호, 중복 가입 확인용 정보예요
PASS로 인증
토스로 인증
네이버로 인증
카카오로 인증
다른 방법으로 인증
9:41
가입을 그만둘까요?입력한 내용은 저장되지 않고 로그아웃돼요.
계속하기로그아웃
Close × Leaving signs out, so a Dialog asks
1/3 본인인증
JourneySocial login (시작, approved) → this screen → the provider’s own app (토스 is drawn; PASS, 네이버 and 카카오 look the same) → back here, checking → 약관 동의 → 첫 시작. The quiet link 다른 방법으로 인증 opens the vendor’s own window instead (금융인증서, the banks, 휴대폰 본인확인). The order is 본인인증 → 약관 → 첫 시작 (owner review 4, confirmed by the owner’s page review of 2026-10-28). Our screens are in colour; the provider’s app and the vendor’s window are grey storyboard frames, not ours and drawn only to show where the person goes. There is no result screen of our own: the provider already says it is done, so the app checks the result and moves on. Taps on our screens: the 시작 provider 1, the 본인인증 provider 1, 전체 동의 1, 동의하고 계속 1, 첫 시작 1 = 5. The provider’s app adds about 1 to 2 touches (an 인증 요청 and one approval), not ours; the vendor window adds about 6 to 8.RoutePortOne v2 identity verification on the KG이니시스 통합인증 channel. Each of the four buttons names its provider in bypass.inicisUnified.directAgency (PASS, 토스, 네이버, 카카오), so the person goes straight to that provider’s app and the main path has no vendor picker of ours. 다른 방법으로 인증 opens the vendor’s window without directAgency: it lists 네이버, PASS, 토스, 금융인증서, 카카오, 신한, KB모바일, 삼성패스 and 휴대폰 본인확인. Danal 휴대폰 본인확인 is the fallback channel (only the channel key changes). Still open with the vendor (EXT-19): whether the 통합인증 CI, a 간편인증 service by Inicis’s own page, may key a person, and Kakao’s own CI paperwork. We never receive or type a 주민등록번호. Quotes are pending (EXT-19).ReadsNothing is read on the client. It saves the pending identityVerificationId before the provider opens and sends it back afterwards; an edge function, modelled on verify-portone-payment, calls PortOne with the secret, checks VERIFIED, computes the age from the verified birth date in full years, checks the CI hash for an existing account, writes, and returns only ok, under_14, duplicate (with the first provider) or failed. Stored server-side: a keyed hash of the CI (unique), the real name, the birth date, the phone and the foreigner flag. Not stored: the 주민등록번호, the DI, anything of an under-14, the vendor’s raw payload. Only the masked name and birth date show, in 설정 › 계정. The verified name and birth date fill the display name and the age that the old name and birth-year steps asked.StackStatus 44, wizard header 124 (56 bar with ×, 20 progress row 1/3, 16, title 24/32), 8, the reason line 16/24 secondary, 16, two quiet facts 15/22 tertiary 4 apart (the 주민등록번호 line, then what we receive). CTA band, entry: 16, the four provider buttons 52 and 12 apart, 12, the link 다른 방법으로 인증 (44 target), then max(16, inset): 328 at inset 34 (358 with the cancel line). The kit has no PASS or 토스 button, so those two are drawn with the provider button’s geometry in a neutral fill and a plain text label, no logo; the build uses each service’s own asset. The storyboard frames sit on a grey ground with the phone’s own status bar and no band.StatesBusy opening the provider (the tapped button spins, 여는 중…; the other three and the link wait inert); busy checking after the return (확인 중…, the same button); cancelled (the provider’s app was closed or backed out of: one quiet danger line above the buttons, no error page); offline (the strip under the status bar, every button off); the exit Dialog. The app killed while in the provider’s app is not a screen: the pending attempt is re-checked silently on relaunch and the person lands on 약관 동의, or here with no message if the attempt did not succeed.TapsA provider button: opens that provider’s app (an app switch by redirect on a phone), and on the return the app checks and moves on to 약관 동의. 다른 방법으로 인증: the vendor’s window (a WebView, by redirect on a phone). ×: the exit Dialog, then 로그아웃. A cancelled return stays here with its line; a failed one opens the failed screen.Spokenh1 본인인증을 해 주세요; the buttons read "PASS로 인증", "토스로 인증", "네이버로 인증" and "카카오로 인증", then the link "다른 방법으로 인증" ("여는 중" or "확인 중" while one runs). First stops: "닫기", the reason, "주민등록번호는 받지 않아요", "PASS로 인증".RulingsSay why before asking (Toss: the one change that raised completion): the reason line, 주민등록번호는 받지 않아요 and what we receive come before the buttons. Four providers of the same size, shape and weight, so none is more prominent; the brand fills are exempt from the one-ball rule. Each goes straight to its own app, which people already hold and trust, with no method picker of ours. One person, one account, keyed by the CI hash. The provider collects its own consent on its own screen; ours only names what we receive. The result is read only on the server, never trusted from the client. 본인인증 once, at sign-up, before our consent: the age is known before anything is asked (PIPA 22-2). Needs counsel: whether consent may follow the check, CI storage and retention, the privacy policy listing the new items.Open decisionsD3 channel: KG이니시스 통합인증 with directAgency per provider, Danal the fallback, as in Route; EXT-19 stays open on the 통합인증 CI and on Kakao’s CI paperwork. D5 under 14: refuse inside the vendor window with AGELIMIT=14 where the channel allows it and the refusal can be told apart in a test (nothing about the child reaches us), else accept the result and discard it at once. D6 foreigners: the phone check returns only a flag, so nationality_code stays KR for a domestic person and a foreign one gets ZZ (unknown) or one tap to choose a country after sign-up. D8 timing: at sign-up for everyone (ruled; recommended) against the first trust action for invite-link arrivals. D9 display name: the verified real name or the provider nickname (the owner’s call; not drawn). D10 vendor-facing name and logo: a neutral placeholder until the app name is filed (owner review 47).
When the check does not pass
1/3
본인인증을 마치지 못했어요이름, 생년월일이 휴대폰 가입 정보와 같아야 해요. 잠시 후 다시 시도해 주세요
본인 명의 휴대폰이 없어요
다시 시도
9:41
Failed One 다시 시도 that re-checks the last attempt first; a link to the next case (not built: waits for the identity vendor (EXT-19))
1/3
본인 명의 휴대폰이 필요해요본인 명의 휴대폰으로 인증할 수 있어요. 외국인은 외국인등록을 한 국내 휴대폰으로 인증할 수 있어요
다른 방법으로 인증
9:41
본인 명의 휴대폰이 필요해요 A family line, or a foreigner without a Korean line, on the 휴대폰 본인확인 path; the way out is 다른 방법으로 인증 (not built: waits for the identity vendor (EXT-19))
1/3
본인 명의 휴대폰이 필요해요본인 명의 휴대폰으로 인증할 수 있어요. 외국인은 외국인등록을 한 국내 휴대폰으로 인증할 수 있어요
문의하기
9:41
Same, on the Danal fallback channel Danal offers no other method, so the way out is 문의하기 (not built: waits for the identity vendor (EXT-19))
1/3
만 14세부터 쓸 수 있어요보호자 동의 가입은 아직 지원하지 않아요
로그아웃
9:41
Under 14 A stop: nothing is stored; 로그아웃 or the header’s × leaves. 14 to 18 simply continue
1/3
이미 가입한 계정이 있어요카카오로 가입한 계정이에요. 카카오로 로그인하면 방금 쓴 방법도 함께 연결돼요.
카카오로 로그인하기
9:41
이미 가입한 계정이 있어요 A second provider, the same person: the first provider is named (not built: needs 본인인증, account linking and provider sign-in)
본인인증 stops
FailedAn error EmptyState with the likeliest cause in one line (이름, 생년월일이 휴대폰 가입 정보와 같아야 해요), the band 다시 시도 and, under it, one quiet link 본인 명의 휴대폰이 없어요 that opens the next screen. 다시 시도 re-checks the last attempt before it opens the provider again: the attempt may have succeeded, and a success cannot be redone and is billed once. Attempts are capped per account and per day on the server.Own-name phoneOne screen for a family line and for a foreigner without a Korean line, reached on the 휴대폰 본인확인 path (the vendor window’s method, or the Danal fallback channel). The way out is the band: 다른 방법으로 인증 on the 통합인증 channel, which reopens the vendor window on its certificate methods, and 문의하기 (L3-43) on the Danal fallback channel, which offers no other method. Both are drawn.Under 14A stop on the first step: the header’s × (the exit Dialog first), the title and 로그아웃. Nothing is stored. 14 to 18 simply continue, with no frame; the under-19 card rule is stated where it bites, in the payment gate (payAge 19), not at sign-up.Existing accountA stop that names the first sign-in provider (카카오로 가입한 계정이에요); its band signs in with that provider and connects this login in 설정 › 연결된 계정, never a silent merge. If the first login was an email the body reads 다른 방법으로 가입한 계정이에요.
Interim 1/3, until 본인인증 exists (replaces the 본인인증 step)
1/3
기본 정보를 알려 주세요
나이대가 맞는 클럽과 경기를 보여 드리려고 물어봐요.
출생 연도
1990
년
이름
다음
9:41
1/3 Ours: 기본 정보 Interim: typed in place of 본인인증, which replaces this step when the vendor exists; 다음 stays soft until both are valid
1/3
기본 정보를 알려 주세요
나이대가 맞는 클럽과 경기를 보여 드리려고 물어봐요.
출생 연도
1990
년
출생 연도를 입력해 주세요
이름
이름을 입력해 주세요
다음
9:41
다음 pressed, nothing entered Each field carries its own line and focus goes to the first
1/3 기본 정보 (interim)
StackWizard header 1/3 with the title 기본 정보를 알려 주세요 (× leaves through the exit Dialog), 8, the reason line 15/22 secondary, 24, Field 출생 연도 (a year, numeric, unit 년), 32, Field 이름, CTA band 다음 (single footer CTA).ReadsWrites profile.birthYear and the display name at the end of the wizard, as the steps do today; the under-14 stop reads the year (vi-u14). Replaced by 본인인증, which fills the verified name and birth date, when the vendor exists (EXT-19).Taps다음 is soft until both fields are valid and stays pressable: a press marks each missing or invalid field with its own line and focuses the first. Valid: goes to 2/3.SpokenThe wizard header names the step ("1/3"); the fields are named "출생 연도, 필수" and "이름, 필수"; an error adds "입력 오류" to the name and is announced when it appears.
2/3 약관 동의
2/3
약관에 동의해 주세요
전체 동의
[필수] 서비스 이용약관에 동의합니다
보기
[필수] 개인정보 처리방침에 동의합니다
보기
[필수] 개인정보 국외 이전에 동의합니다
보기
[선택] 위치 정보 수집·이용에 동의합니다
보기
[선택] 마케팅 푸시 알림 수신에 동의합니다
보기
동의하고 계속
9:41
Nothing ticked Three missing: the button validates on press
2/3
약관에 동의해 주세요
전체 동의
[필수] 서비스 이용약관에 동의합니다
보기
[필수] 개인정보 처리방침에 동의합니다
보기
[필수] 개인정보 국외 이전에 동의합니다
보기
[선택] 위치 정보 수집·이용에 동의합니다
보기
[선택] 마케팅 푸시 알림 수신에 동의합니다
보기
동의하고 계속
9:41
One required left Soft-disabled, with no line; a press marks the missing row
2/3
약관에 동의해 주세요
전체 동의
[필수] 서비스 이용약관에 동의합니다
보기
[필수] 개인정보 처리방침에 동의합니다
보기
[필수] 개인정보 국외 이전에 동의합니다
보기
개인정보 국외 이전에 동의해 주세요
[선택] 위치 정보 수집·이용에 동의합니다
보기
[선택] 마케팅 푸시 알림 수신에 동의합니다
보기
동의하고 계속
9:41
Soft-disabled, pressed The missing row gets its danger line
2/3
약관에 동의해 주세요
전체 동의
[필수] 서비스 이용약관에 동의합니다
보기
[필수] 개인정보 처리방침에 동의합니다
보기
[필수] 개인정보 국외 이전에 동의합니다
보기
[선택] 위치 정보 수집·이용에 동의합니다
보기
[선택] 마케팅 푸시 알림 수신에 동의합니다
보기
동의하고 계속
9:41
All ticked The master is ticked; unticking one returns it to mixed
개인정보 처리방침
2026년 5월 18일 시행버전 KR-1.0.0
제1조 (개인정보의 처리 목적)투모(이하 "회사")는 다음의 목적을 위하여 개인정보를 처리합니다. 처리한 개인정보는 다음의 목적 이외의 용도로는 사용되지 않으며, 목적이 변경될 경우 개인정보보호법 제18조에 따라 별도의 동의를 받는 등 필요한 조치를 이행합니다.① 회원 가입 및 관리: 회원 가입 의사 확인, 이용자 식별·인증, 회원 자격 유지·관리, 서비스 부정이용 방지, 각종 고지·통지, 고충 처리 등② 서비스 제공: 테니스 클럽 관리, 일정 등록 및 참가(RSVP) 처리, 경기 기록, 회비 관리, 순위·통계 제공, 파트너 매칭 및 동호인 추천③ 위치 기반 서비스: 코트 주변 동호인 검색, GPS 출석 체크, 지역 기반 일정 추천 (위치기반서비스사업자 신고번호: 신고 진행 중 — 신고 완료 후 본 처리방침에 갱신 게시)
제2조 (개인정보의 처리 항목)회사는 서비스 제공을 위하여 아래의 개인정보 항목을 처리합니다.[필수]• 이메일 주소 (소셜 로그인 시 해당 플랫폼 제공 이메일)• 닉네임(표시 이름)• 테니스 실력 등급(ELO 점수)• 활동 지역(시·도 단위)
제3조 (개인정보의 처리 및 보유 기간)회사는 법령에 따른 개인정보 보유·이용 기간 또는 정보주체로부터 개인정보를 수집 시에 동의받은 개인정보 보유·이용 기간 내에서 개인정보를 처리·보유합니다.① 회원 정보: 회원 탈퇴 시까지. 탈퇴 후 30일 이내 완전 파기(삭제 요청 처리 기간 감안). 단, 아래 각 호의 경우 해당 기간 동안 보관합니다.
9:41
보기 › A pushed page, not a sheet; back returns here
2/3 약관 동의
StackStatus 44, wizard header 124 (progress row 2/3, the title), 24, consent group: 전체 동의 48, 16, hairline, four rows (48, 68 when a label wraps), 16, hairline, the marketing row; CTA band 102 (132 with its helper).ReadsgetRequiredConsentsForJurisdiction("KR") filtered by showAtSignup; labels from onboarding.consent.purposeLabels; areRequiredConsentsGranted; buildConsentGrants at finish. The profile timestamps and the consent grants are written together at the end.Taps전체 동의: ticks every row. 동의하고 계속: 첫 시작. 보기 ›: the document page (push): /legal/terms for the terms, /legal/privacy for the privacy policy, the transfer, location and marketing rows. Back: does not repeat the check, which is already done.SpokenEach row is a checkbox named with its prefix ("[필수] 서비스 이용약관에 동의합니다"); 보기 is its own stop ("서비스 이용약관 보기"); the master reads "전체 동의, 일부 선택됨". First stops: "뒤로", "전체 동의", "[필수] 서비스 이용약관에 동의합니다".RulingsNothing pre-ticked; required and optional kept apart; marketing last in its own group (labels are the shipped legal strings until counsel; (광고) goes on the advertising push itself); 보기 opens a page, not a sheet; the primary needs only the three required rows: validate on press while several remain, soft-disabled while one does. The order after 본인인증 is the owner’s (review 4, confirmed 2026-10-28); needs counsel on whether consent may follow the check.
3/3 첫 시작
건너뛰기
3/3
어떻게 시작할까요?
클럽에 가입할래요
초대 코드로 가입하거나 클럽을 찾아요
매치로 칠래요
근처에서 모이는 매치에 참석해요
클럽을 만들래요
총무가 되어 우리 클럽을 시작해요
9:41
Busy The tapped Cell shows a spinner; the rest and 건너뛰기 are inert
건너뛰기
3/3
어떻게 시작할까요?
시작하지 못했어요
다시 시도
클럽에 가입할래요
초대 코드로 가입하거나 클럽을 찾아요
매치로 칠래요
근처에서 모이는 매치에 참석해요
클럽을 만들래요
총무가 되어 우리 클럽을 시작해요
9:41
Failed A Notice that stays, with the way to retry
건너뛰기
3/3
어떻게 시작할까요?
클럽에 가입할래요
초대 코드로 가입하거나 클럽을 찾아요
매치로 칠래요
근처에서 모이는 매치에 참석해요
클럽을 만들래요
총무가 되어 우리 클럽을 시작해요
9:41
오프라인이에요
다시 시도
Offline The strip under the progress; every Cell and 건너뛰기 inert
3/3 첫 시작
StackStatus 44, wizard header 124 (the bar with 건너뛰기 at its right, the progress row 3/3, the title), 12, three two-line nav Cells 68. No CTA band: a choice whose answers are equal has no coloured answer, and the way out is the header’s 건너뛰기.ReadsThe finish writes one useGrantConsent per ticked shown row (buildConsentGrants), then useUpdateProfile, both silent and in that order, so the consents are on record before the profile marks the onboarding complete; a rejected write fails the finish like a failed profile write (the Notice, 다시 시도 sends every write again). Then completeOnboarding and appRouter.replace(destination) from resolveOnboardingDestination.Taps클럽에 가입할래요: 클럽 tab, whose empty state leads with 클럽 찾기 and 초대 코드. 매치로 칠래요: 경기 › 매치 찾기. 클럽을 만들래요: 클럽 만들기. 건너뛰기 (the header): 홈, with no first action. Each writes first; a failed write stays here. A sign-up that began from an invite code or a share link skips this step.CountThe progress reads 1/3 to 3/3. When 첫 시작 is skipped (the destination the gate resolved is not home: an invite code or a share link) it reads 1/2 and 2/2, and 동의하고 계속 on 2/2 finishes and goes to that destination; a failed finish shows the band’s danger helper there.Spokenh1 어떻게 시작할까요?; each Cell is one stop ("클럽에 가입할래요, 초대 코드로 가입하거나 클럽을 찾아요"). A busy Cell is spoken "처리 중". First stops: "뒤로", "건너뛰기", "클럽에 가입할래요".RulingsThe first-action chooser replaces the play-style step; nav Cells with an ink label, the way out as the header’s 건너뛰기 (a departure lives in the header, the WizardShell header law; it replaces the ghost 나중에 할게요), the failure in a Notice that stays. It is step 3 of 3, after 본인인증 and 약관 동의.
English, 200% and dark
1/3
Verify your identity
We check that each person has one account, so club dues and match records can be trusted.
We never ask for your resident registration number
We receive your name, birth date, phone number and a code that checks for duplicate accounts
Verify with PASS
Verify with Toss
Verify with Naver
Verify with Kakao
Verify another way
9:41
English 1/3 The reason and the facts wrap; each provider keeps its own name (not built: waits for the identity vendor (EXT-19))
1/3
You need a phone in your own nameYou can verify with a phone in your own name. Foreign residents can verify with a Korean line in their own name
Verify another way
9:41
English, own-name phone Two sentences, one way out (not built: waits for the identity vendor (EXT-19))
1/3
You already have an accountYou signed up with Kakao. Sign in with it and the sign-in you just used is connected too.
Sign in with Kakao
9:41
English, existing account The first provider is named (not built: needs 본인인증, account linking and provider sign-in)
2/3
Agree to continue
Agree to all
[Required] I agree to the Terms of Service
View
[Required] I agree to the Privacy Policy
View
[Required] I consent to international data transfer
View
[Optional] I consent to collection and use of location information
View
[Optional] I consent to marketing push notifications
View
Agree and continue
9:41
English 2/3 The legal sentences wrap; the link reads View
Skip
3/3
How do you want to start?
Join a club
Join with an invite code, or look for a club
Play a pickup
Join a pickup near you
Start a club
Become the admin and start your own
9:41
English 3/3 Reasons stay on two lines; the header reads Skip
1/3
본인인증을 해 주세요
한 사람이 한 계정만 쓰도록 확인해요. 클럽 회비와 경기 기록을 믿을 수 있게요.
주민등록번호는 받지 않아요
받는 정보는 이름, 생년월일, 휴대폰 번호, 중복 가입 확인용 정보예요
PASS로 인증
토스로 인증
네이버로 인증
카카오로 인증
다른 방법으로 인증
9:41
844 FOLD
200% 1/3 The text grows and the buttons with it; the band keeps all four and the link (not built: waits for the identity vendor (EXT-19))
1/3
본인 명의 휴대폰이 필요해요본인 명의 휴대폰으로 인증할 수 있어요. 외국인은 외국인등록을 한 국내 휴대폰으로 인증할 수 있어요
다른 방법으로 인증
9:41
200% own-name phone The text grows; the button stays in the band (not built: waits for the identity vendor (EXT-19))
2/3
약관에 동의해 주세요
전체 동의
[필수] 서비스 이용약관에 동의합니다
보기
[필수] 개인정보 처리방침에 동의합니다
보기
[필수] 개인정보 국외 이전에 동의합니다
보기
[선택] 위치 정보 수집·이용에 동의합니다
보기
[선택] 마케팅 푸시 알림 수신에 동의합니다
보기
동의하고 계속
9:41
844 FOLD
200% 2/3 Rows grow; 보기 keeps its 44 target
건너뛰기
3/3
어떻게 시작할까요?
클럽에 가입할래요
초대 코드로 가입하거나 클럽을 찾아요
매치로 칠래요
근처에서 모이는 매치에 참석해요
클럽을 만들래요
총무가 되어 우리 클럽을 시작해요
9:41
200% 3/3 The Cells grow and the chevron centres; the header buttons stop at 1.3×
1/3
본인인증을 해 주세요
한 사람이 한 계정만 쓰도록 확인해요. 클럽 회비와 경기 기록을 믿을 수 있게요.
주민등록번호는 받지 않아요
받는 정보는 이름, 생년월일, 휴대폰 번호, 중복 가입 확인용 정보예요
PASS로 인증
토스로 인증
네이버로 인증
카카오로 인증
다른 방법으로 인증
9:41
Dark 1/3 카카오 and 네이버 keep their fills; PASS and 토스 follow the canvas (not built: waits for the identity vendor (EXT-19))
1/3
본인인증을 마치지 못했어요이름, 생년월일이 휴대폰 가입 정보와 같아야 해요. 잠시 후 다시 시도해 주세요
본인 명의 휴대폰이 없어요
다시 시도
9:41
Dark, failed One retry in the band, one quiet link (not built: waits for the identity vendor (EXT-19))
2/3
약관에 동의해 주세요
전체 동의
[필수] 서비스 이용약관에 동의합니다
보기
[필수] 개인정보 처리방침에 동의합니다
보기
[필수] 개인정보 국외 이전에 동의합니다
보기
[선택] 위치 정보 수집·이용에 동의합니다
보기
[선택] 마케팅 푸시 알림 수신에 동의합니다
보기
동의하고 계속
9:41
Dark 2/3 Checkbox edge and hairlines in dark

L0-05업데이트가 필요해요

Replaces the whole app when this build is below the server’s minimum; it fails open, so offline and errors never show it.

DABUSI
업데이트가 필요해요새 버전에서 계속 이용할 수 있어요
업데이트
9:41
Ideal A store link exists: 업데이트 is the one action
DABUSI
업데이트가 필요해요새 버전에서 계속 이용할 수 있어요. 스토어에서 앱을 업데이트해 주세요
9:41
No store link yet No button, so the body says where to update
업데이트가 필요해요 · AppVersionGate
StackNo header, no tab bar. An EmptyState, full, centred in the screen: the stacked lockup, 32, title 17/24·600, 8, body 16/24 secondary, 24, one md primary button. Without a store link there is no button and the body names the store, never an app name (the name is open until it is filed).ReadsuseAppVersionGate compares the runtime version with get_app_version_policy and fails open; the store URL comes from the policy row and is empty until the stores list the app (EXT-8).Taps업데이트: the store, through openExternalUrl. There is no way past the gate. The word is 업데이트, not 업데이트하기: the house style refuses 하기 outside its sanctioned idioms.Spokenh1 업데이트가 필요해요; the lockup is hidden. First stops: the title, the body, "업데이트".

L0-06공유 링크

A link opened in the app: members, profiles and leaderboards redirect; a signed-in non-member sees the public preview of a session or a match. It answers “is this for me?” with what, when, where, level and seats, and never who: counts, not people.

강남 라켓클럽

올림픽공원 테니스장

10월 17일 (토)09:00~11:00
정보
자리
6/8, 2자리 남음
종목
복식
대상
NTRP 3.0–4.0
경기 방식
친선
참가비
10,000원
참석 방식
승인 후 참석
신청 마감
10월 17일 (토) 07:00
주소
송파구 올림픽로 424
참석 신청하기
9:41
/s, non-member Counts, never people: no avatars, no host. 참석 신청하기 is the one action
강남 라켓클럽

올림픽공원 테니스장

결과
점수
6-4
종목
복식
완료
10월 10일 (토) 10:42
9:41
/m, no access The result only; nothing to act on, so no band
강남 라켓클럽

올림픽공원 테니스장

결과
점수검토 중
6-4
종목
복식
완료
10월 10일 (토) 10:42
9:41
/m, under review The score stands and the Tag 검토 중 says so; the word 분쟁 is never printed
강남 라켓클럽

올림픽공원 테니스장

결과
점수
기록 제외
종목
복식
완료
10월 10일 (토) 10:42
9:41
/m, not counted The Tag 기록 제외 and no numerals
States
마감된 일정이에요
매치 찾기
강남 라켓클럽

올림픽공원 테니스장

10월 17일 (토)09:00~11:00
정보
자리
6/8, 2자리 남음
종목
복식
대상
NTRP 3.0–4.0
경기 방식
친선
참가비
10,000원
참석 방식
승인 후 참석
신청 마감
10월 17일 (토) 07:00
주소
송파구 올림픽로 424
9:41
/s, closed The Notice says it and offers 매치 찾기; nothing to apply for, so no band
서울 강남 올림픽공원 주말 아침 테니스 동호회

서울 송파구 올림픽공원 국제 테니스장 센터코트 1번 코트

10월 17일 (토)09:00~11:00
정보
자리
6/8, 2자리 남음
종목
복식
대상
NTRP 3.0–4.0
경기 방식
친선
참가비
10,000원
참석 방식
승인 후 참석
신청 마감
10월 17일 (토) 07:00
주소
송파구 올림픽로 424
참석 신청하기
9:41
Long names Club and venue wrap; nothing is cut
9:41
Loading One skeleton; the same for all four links
이 일정을 찾을 수 없어요삭제됐거나 주소가 바뀌었어요
홈으로 가기
돌아가기
9:41
Not found /s, /m, /p and /lb differ only in the title
강남 라켓클럽

올림픽공원 테니스장

10월 17일 (토)09:00~11:00
정보
자리
6/8, 2자리 남음
종목
복식
대상
NTRP 3.0–4.0
경기 방식
친선
참가비
10,000원
참석 방식
승인 후 참석
신청 마감
10월 17일 (토) 07:00
주소
송파구 올림픽로 424
참석 신청하기
9:41
오프라인이에요
다시 시도
844 FOLD
/s, offline, cached The strip under the header; the preview stays and 참석 신청하기 reads disabled
강남 라켓클럽

올림픽공원 테니스장

결과
점수
6-4
종목
복식
완료
10월 10일 (토) 10:42
9:41
오프라인이에요
다시 시도
/m, offline, cached The strip under the header; the result stays (nothing to act on, so no band)
오프라인이에요연결되면 자동으로 다시 불러와요
다시 시도
9:41
Offline, cold start Never the not-found state
불러오지 못했어요연결을 확인하고 다시 시도해 주세요
다시 시도
9:41
Failed to load The cause and one way forward
공유 링크 · /s /m /p /lb
The ruleA preview answers “is this for me?” with what, when, where, level and seats, and never who: no faces, names, initials or host, on the web and in the app (owner ruling 2026-10-11, M6-3). Three bands of information, decided once: the thing (club, day, time, venue, format, level, capacity, score, member count) shows; people (faces, names, initials, host, roster, win rate, session count, attendance) never show to a stranger; terms and place detail (fee, approval mode, deadline) show, the street address and map only in the app after sign-in.Fields, /sShows: the venue as the title, the club as the eyebrow (a pickup has no club line), the day and times, 자리 as the count with the spots left (never avatars), 종목, 대상 (the NTRP band; the any-level word, 수준 무관, when both tiers are open, the rule 일정 상세 uses), 경기 방식, 참가비, 참석 방식 (바로 참석 or 승인 후 참석; shown only when the session takes applications), 신청 마감, and 주소 as a Cell that opens 장소 상세 (the place owner override: amateurs pick by travel time). The six anonymous avatars of the earlier frame are gone: they implied people. Never: the host, the roster, faces, initials, the host’s free text and chat links.Fields, /mShows: the venue, the club (none for a 매치 of a pickup, as /s), the result 6-4, 종목, the day and time. A score under review keeps its numerals and carries the Tag 검토 중; a match that does not count carries the Tag 기록 제외 and no numerals. Never the word 분쟁, never team names, faces, ELO changes or set scores. /p, /lb and /join-club have no preview in the app: a member’s /p replaces to the profile, /lb to the club’s 기록 pane, and a non-member’s /lb to the club page; an invite opens 클럽 가입하기.Offline (decision 16, 2026-11-10)A warm link opens the cached preview under the offline strip (rc-s-stale, rc-m-stale): the page stays and the join and apply door, 참석 신청하기, reads disabled. /p and /lb are doors without a page of their own: a warm one replaces to the cached profile or 클럽 홈 (prof-stale, club-stale), a cold one is the offline state of rc-off. Never the not-found state.Stack/s: header 56 (back, no title), hero (the club as the eyebrow, the venue as the title, the date and times), 정보 head, seven Cells (자리, 종목, 대상, 경기 방식, 참가비, 참석 방식, 신청 마감), the nav Cell 주소, CTA band 102. Closed: the Notice 마감된 일정이에요 with its one action 매치 찾기, 8 under the header, and no band. A session that takes no applications (public invites off) shows neither the band nor the Notice, and no 참석 방식 Cell. /m: header, hero, 결과 head, three Cells, no band.ReadsusePublicSharePreview(kind, id) over the RPC get_public_share_preview: club, venue, date, times, format, tier band, deadline and counts, never a name. It gains participationFee, publicInviteApproval, isPickup and the venue’s district on a session and the venue, format and day on a match (share-research C4); venueName is a linked venue only, never the free-text location. useSessionQuery decides member or not.Taps참석 신청하기: the apply states of 매치 미리보기. 주소: 장소 상세 (push). 매치 찾기 (the closed Notice): 경기 › 매치 찾기. Back: the previous screen, or the tab root on a cold link. A member replaces to /sessions/{id}; /p replaces to the profile; /lb to the club’s 기록 pane (a non-member sees the club page with its public 소식, review 41). A signed-out visitor meets 시작 first and the path is kept.SpokenThe hero title is the h1; the Cell 자리 reads “6/8, 2자리 남음”; the band reads “참석 신청하기”. Not found, offline and failure are EmptyStates with their title as the h1.RulingsA non-member can apply from a shared link (IA ruling 17). A cold offline start is never drawn as not found. A closed session shows the Notice with its action and draws no disabled band: one place says it (the cohesion pass (the owner, 2026-10-25), §1.18). The band’s verb is the verb with 하기, never the noun (§1.19). One skeleton for all four links. A session is named as its own page names it (library § 5 MediaRow, Content): the venue is the title, the club and the day are the lines.Open decisionD6 host on the signed-in preview: none (drawn; the rule above) or the host’s name and 신뢰 점수 as a 호스트 Cell with initials only and no face. The research leans to the second; the owner decides.

L0-07웹 공유 페이지

A link opened without the app, and the card it unfurled to. The card is the page’s own Block drawn as an image; the page leads with it, then the live facts a stranger needs and one link into the app. /join-club is the app’s own screen on a public path. Nothing about people: no faces, names, initials or host.

The share card is the page’s own Block
강남 라켓클럽10월 17일 (토)
DABUSI
09:00
올림픽공원 테니스장NTRP 3.0–4.0
/s Club | day, the start time, venue | level. No live count or status on the image
10월 10일 (토)올림픽공원 테니스장
DABUSI
6-4
강남 라켓클럽복식
/m Day | venue, the score, club | format. Neutral: no team names
복식 ELO김민준
DABUSI
1,482
NTRP 3.510월 27일 기준
/p 복식 ELO | name, the rating, NTRP | as-of date. No 30-day line, no session count
강남 라켓클럽클럽 순위
DABUSI
42명
강남구활동 멤버
/lb Club | 클럽 순위, the member count, region in words | 활동 멤버
클럽 초대
DABUSI
강남 라켓클럽
강남구NTRP 3.0–4.0멤버 42명
/join-club The club-identity Block: its mark and name, region | level | members. The code never shows
Card states
강남 라켓클럽10월 17일 (토)취소됨
DABUSI
취소된 일정
올림픽공원 테니스장NTRP 3.0–4.0
/s, cancelled The Block’s Tag beside the lockup and B says it in a sentence
10월 10일 (토)올림픽공원 테니스장검토 중
DABUSI
6-4
강남 라켓클럽복식
/m, under review An entered score stands: the Tag 검토 중, never 분쟁
10월 10일 (토)올림픽공원 테니스장기록 제외
DABUSI
기록 제외
강남 라켓클럽복식
/m, not counted The Tag 기록 제외 and a sentence in place of the numerals
복식 ELO주말 테니스 중독자 김민준 (강남 라켓클럽 총무)
DABUSI
1,482
NTRP 3.510월 27일 기준
Long name A person’s name wraps, it is never cut; the row grows and the card keeps its ratio
Kakao feed (the card at Kakao’s 2:1 crop, then title, description and one button)
강남 라켓클럽10월 17일 (토)
DABUSI
09:00
올림픽공원 테니스장NTRP 3.0–4.0
10월 17일 (토) 09:00 올림픽공원 테니스장
복식, 친선2자리 남음
일정 보기
/s Title up to 2 lines; the second description line is the send-time seat count
10월 10일 (토)올림픽공원 테니스장
DABUSI
6-4
강남 라켓클럽복식
경기 결과 6-4
강남 라켓클럽10월 10일 (토)
결과 보기
/m The button names the page it opens
복식 ELO김민준
DABUSI
1,482
NTRP 3.510월 27일 기준
김민준 ELO 1,482
NTRP 3.5
프로필 보기
/p One description line is enough
강남 라켓클럽클럽 순위
DABUSI
42명
강남구활동 멤버
강남 라켓클럽 순위
활동 멤버 42명강남구
순위표 보기
/lb Eight characters or fewer on the button
클럽 초대
DABUSI
강남 라켓클럽
강남구NTRP 3.0–4.0멤버 42명
강남 라켓클럽에 초대받았어요
강남구, NTRP 3.0–4.0멤버 42명
가입하기
/join-club Today this link has no image at all
The page, signed out
DABUSI
강남 라켓클럽10월 17일 (토)
DABUSI
09:00
올림픽공원 테니스장NTRP 3.0–4.0

올림픽공원 테니스장

강남 라켓클럽송파구
일시
10월 17일 (토) 09:00~11:00
자리마감 임박
6/8, 2자리 남음
종목
복식, 친선
대상
NTRP 3.0–4.0
참가비
10,000원
참석 방식
승인 후 참석
신청 마감
10월 17일 (토) 07:00
앱에서 열기
9:41
844 FOLD
/s The card, the venue, the live facts, and one link: the ball button
DABUSI
10월 10일 (토)올림픽공원 테니스장
DABUSI
6-4
강남 라켓클럽복식

올림픽공원 테니스장

강남 라켓클럽
점수
6-4
종목
복식
날짜
10월 10일 (토)
앱에서 열기
9:41
/m The result and when; no teams
DABUSI
복식 ELO김민준
DABUSI
1,482
NTRP 3.510월 27일 기준

김민준

복식 ELO
1,482
NTRP
3.5
신뢰 점수
84점
기준일
10월 27일
앱에서 열기
9:41
/p The rating and the 신뢰 점수 (84점), no photo, no count of sessions
DABUSI
강남 라켓클럽클럽 순위
DABUSI
42명
강남구활동 멤버
강남 라켓클럽
강남구NTRP 3.0–4.0활동 멤버 42명
가입 방식
바로 가입
앱에서 열기
9:41
/lb The club’s row: mark, name, region in words, level, members
DABUSI
강남 라켓클럽10월 17일 (토)취소됨
DABUSI
취소된 일정
올림픽공원 테니스장NTRP 3.0–4.0

올림픽공원 테니스장

강남 라켓클럽송파구
일시
10월 17일 (토) 09:00~11:00
상태
취소됨
앱에서 열기
9:41
/s, cancelled A cancelled or finished session shows only 일시 and its state; the link still opens the app
DABUSI
복식 ELO주말 테니스 중독자 김민준 (강남 라켓클럽 총무)
DABUSI
1,482
NTRP 3.510월 27일 기준

주말 테니스 중독자 김민준 (강남 라켓클럽 총무)

복식 ELO
1,482
NTRP
3.5
신뢰 점수
84점
기준일
10월 27일
앱에서 열기
9:41
Long name The title wraps and so does the card’s eyebrow
DABUSI

이 일정을 찾을 수 없어요

삭제됐거나 주소가 바뀌었어요
앱에서 열기
9:41
Not found A link that is gone: no card, the link still opens the app; /s says 일정, /m has its own frame (경기), /p and /lb differ only in the title
DABUSI

이 경기를 찾을 수 없어요

삭제됐거나 주소가 바뀌었어요
앱에서 열기
9:41
Not found, /m The same page for a match link: the title says 경기 (/p and /lb differ only in the title too)
/join-club, signed out
클럽 가입하기
강남 라켓클럽
강남구NTRP 3.0–4.0멤버 42명
가입 방식
바로 가입
초대 코드
TNK-4821
로그인하기
9:41
Signed out Built (batch 52): the club’s row and 가입 방식 from the anonymous preview, above the code Field; no fee (the preview states none). 로그인하기 sends to /login with the code kept in the URL
클럽 가입하기
로그인하기
9:41
Resolving Owed, not built (W12): one skeleton for the club row while it loads
클럽 가입하기
초대 링크를 열 수 없어요클럽 총무에게 새 링크를 받아 주세요
9:41
Link matches no club Owed, not built (W12): one generic line for a wrong, an expired and an archived code; nothing to press
클럽 가입하기
강남 라켓클럽
강남구NTRP 3.0–4.0멤버 42명
정원이 다 찼어요
가입 방식
바로 가입
9:41
Club is full Owed, not built (W12): the Notice under the club row says it, as in the app; nothing to press, so no band
웹 공유 페이지 · /s /m /p /lb /join-club
The ruleSame as the in-app preview: the thing and its counts, never a person. On the open web nothing about people shows at all, and the street address, map, free text and the invite code stay out. Every link has one action.The cardThe share card is the page’s own Block drawn as an image: a full-bleed ink field #15181A (a card is not themed), the Block’s three rows scaled ×3.43 to 1200 × 630 (A the eyebrow 44/60·600 white α0.8 with the lockup 44 high at its trailing end, in the door’s place, since a card is not pressed; B the one figure 140/150·700 in ball, its unit 52·600 white; C one line 52/72·500 white α0.85; 72 of padding; all text inside the centred 1200 × 600 frame Kakao crops to). Drawn here at 350 wide with the Block’s own type roles at 1x, so what you see is the in-app Block without its door. No photo, map tile, face, emoji or progress ring, and one ball item. Only facts that cannot go stale are on the image: Facebook re-scrapes after 24 hours and Kakao caches without a stated limit, so a live count or status belongs on the page and, as a send-time snapshot, in the Kakao description. A place crops with an ellipsis; a person’s name wraps and is never cut. The Block’s accessible name is the image’s alt. The lockup slot holds the lockup the app draws today (the mark and the DABUSI wordmark; the kit’s lockup draws the mark’s slot until it is filed).Cards, by link/s the 홈 day Block, stranger edition: A club | day, B the start time, C venue | level; a cancelled session puts the Tag 취소됨 beside the lockup and B says 취소된 일정. /m the match Block without its teams: A day | venue (the place crops, so it goes last), B the score, C club | format; 검토 중 beside the lockup keeps the score, 기록 제외 replaces the numerals. /p the 기록 ELO Block, the person’s: A 복식 ELO | name (the eyebrow names the figure; the name goes last so a long one wraps, never cuts), B the rating, C NTRP | the as-of date; no 30-day line (live data), no session count, no 신뢰 점수 (the page’s rows hold it). /lb the season Block: A club | 클럽 순위, B the member count and 명, C region in words | 활동 멤버 (never a slug). /join-club the club-identity Block: A 클럽 초대 and the lockup, the club’s mark with its name (two lines, never cut), C region | level | members; no code, no ball figure.Kakao feedEvery link is sent as a feed: the card at Kakao’s 2:1 crop (15 px of ink trimmed top and bottom of 630; Kakao accepts 1:1, 2:1 and 4:3 and crops anything else), a title of up to 2 lines, a description of 2 lines, and one button of 8 characters or fewer that names the page it opens (일정 보기, 결과 보기, 프로필 보기, 순위표 보기, 가입하기; §1.19). The send-time seat count may live in the description, never on the image. Drawn at 300 wide with the Block’s roles at 1x; in KakaoTalk the bubble is about 272 wide and the card’s type renders at 10 / 32 / 11.8. Version the image URL (?v=) and send a real feed before launch.StackA server page (the metadata, the card and the status) over a client island that draws the page in the browser, in Korean only: the lockup slot 28, 24, the card as the hero (350 × 184, r16, with an alt), 24, h1 24/32·700, 8, one line of the club and the district, 24, the live facts as Cells (status as a Tag, seats left, fee, approval mode, level, deadline: for the page, never the image), 32, the one ball link lg 52. /lb leads with the club’s row (mark, name, region, level, members) in place of the h1. /join-club is the app screen on a public path: header, the club’s row (the MediaRow, as 클럽 가입하기), two Cells, CTA band; the full state adds the Notice 정원이 다 찼어요 under the row, 8 below it, and draws no band.Fields, /sShows: venue name (a linked venue only; otherwise the district), the district, the club (a pickup has none), day and start–end time, format and style, level band, seats as a count with the spots left, the recruitment state as one derived Tag beside the seats (6/8 reads 마감 임박; never hand-set), the deadline, the fee and the approval mode. A cancelled or finished session shows only 일시 and its state (취소됨 or 종료), no seats or terms. Never: street address and map (the app, after sign-in), host name, 신뢰 점수 or face, roster, the host’s free text.Fields, /mShows: venue (linked only), club, day, format and the score, neutral with no winner emphasis. The link card and the link’s description read the finish in Seoul time (one image for every viewer); the page’s 날짜 row reads the visitor’s own day, as the app does. For a device in Korea the two agree; outside Korea the card says Seoul time by design. Under review: the Tag 검토 중; not counted: the Tag 기록 제외 and no numerals. Never: team names, faces, ELO changes, set scores, the word 분쟁.Fields, /pShows: the display name (a nickname, never the legal name; it wraps), the doubles ELO labelled as such, the NTRP derived from it, the 신뢰 점수 as 84점 (none before five recorded sessions; a stranger sees the score only), the as-of date. No photo and no initials monogram: the one page whose subject is a person shows the name alone (a face never reaches an anonymous viewer). Never: total sessions, win rate, attendance, region, club.Fields, /lbShows: the club’s name, region and district in words (mapped from the slug), the active member count, the level band and the join method, and the logo or the mono initial (a club logo is not a face). Never: member names, ranks, ELO, win rates, an admin’s name, the description.Fields, /join-clubShows: the club’s name and mark, region and district, the level band, the member count, the join method (바로 가입, 승인 후 가입 or 초대 전용) and the monthly dues. A full club shows the Notice and no band. Never: the invite code on the image, in the meta tags or in the page text (a bearer secret on a forwardable image; it stays in the URL), the admin, members, the description. A wrong, an expired and an archived code read the same, 초대 링크를 열 수 없어요, so the page is no way to test codes; the reader is rate-limited.Taps앱에서 열기: twomore://{kind}/{id}; with the app installed the universal link never reaches the page. 로그인하기 (a signed-out /join-club): /login with the code and returnTo kept (the join follows on the page it returns to). A signed-in non-member on /s applies in the app (참석 신청하기). The club’s row opens its 클럽 홈. No store link and no universal-link logic are built: the door is the app’s scheme alone until the stores list the app (EXT-8) and the domain is live (EXT-13). /join-club for a signed-out visitor (jn-*) is owed (W12).SpokenThe title is the h1 (/lb has none: the club’s row leads, as drawn); the card’s alt is the Block’s rows read aloud, composed by the app from the same lines as the image (the figure spoken: 6대 4, 42명; the state Tag last unless the sentence says it); the link reads “앱에서 열기”; the page has exactly one main landmark and lang ko.NeedsFor the lead, nothing is built: get_public_share_preview gains the fee, approval mode, pickup flag, venue district and the match’s venue, format and day, and returns a linked venue name only; a new anonymous, minimal, rate-limited reader for the invite (the whole clubs row never leaves); /join-club becomes a server shell with generateMetadata and an opengraph-image; per-route robots noindex on /s /m /p /lb /join-club; og:image width and height; and today’s cards lose the 분쟁 word, the session count and the raw tier key on /p (the person’s trust reads as the 신뢰 점수), and the raw region slug on /lb.Open decisionsD1 the card is the Block, full-bleed ink with the lockup in the door’s place (recommended), against a white card with the Block inset (what the earlier frames drew: a card inside a card). D2 no live count on the image (recommended; the option is a 6/8 ring on /s, accepting a stale image). D3 the fee shows on the page, not the image (recommended), or hides until sign-in. D4 dues and join method show on the invite page (recommended), or name, region and member count only. D5 /lb stays a public club teaser (recommended), or folds into the club’s public view and stops being shared. D6 the host on the signed-in preview, as in 공유 링크. D7 names in share text: out of the /lb message, a sender’s choice on /m. D8 a revocable token in place of the raw user id in /p/{userId}: later, or before launch.
Checked in Chromium with scripts/verify-flat-v2-boards.mjs: 79 frames, rail 0, type scale 0, targets 0, shadows 0, middle dots 0, ball actions 0.
Spec (grounding, anatomy)

Sign-in, the three onboarding steps (본인인증, 약관 동의, 첫 시작), the version gate and the pages a shared link opens, composed from the shared kit. Frames and one-line captions are visible; the specs sit behind the Show specs toggle.

route · packages/app/src/presentation/screens/auth/login-screen.tsx · apps/web/app/login/page.tsx · packages/features/onboarding/src/onboarding-wizard-screen.tsx · packages/app/src/presentation/components/app-version-gate.tsx · apps/mobile/app/{s,m,p,lb}/*.tsx · apps/web/app/{s,m,p,lb}/*/page.tsx · apps/web/app/join-club/page.tsx grounded in 35 source file(s)
packages/app/src/presentation/screens/auth/login-screen.tsxapps/web/app/login/page.tsxpackages/app/src/presentation/screens/auth/auth-gate.tsxpackages/features/onboarding/src/onboarding-wizard-screen.tsxpackages/features/onboarding/src/onboarding-step-basics.tsxpackages/features/onboarding/src/onboarding-step-under-14.tsxpackages/features/onboarding/src/onboarding-step-consent.tsxpackages/features/onboarding/src/onboarding-step-start.tsxpackages/app/src/domain/rules/consent-matrix.tspackages/app/src/config/legal/policy-versions.tspackages/app/src/navigation/onboarding-intent.tspackages/app/src/presentation/components/app-version-gate.tsxpackages/app/src/presentation/components/update-required-screen.tsxpackages/app/src/domain/public-share-preview.tsapps/mobile/app/s/[sessionId].tsxapps/mobile/app/m/[matchId].tsxpackages/features/sessions/src/share-receivers/session-share-preview-screen.tsxpackages/features/sessions/src/share-receivers/match-share-preview-screen.tsxapps/mobile/app/p/[userId].tsxapps/mobile/app/lb/[clubId].tsxapps/web/app/s/[sessionId]/page.tsxapps/web/app/m/[matchId]/page.tsxapps/web/app/p/[userId]/page.tsxapps/web/app/lb/[clubId]/page.tsxapps/web/lib/share-page.tsxapps/web/components/web-share-page.tsxapps/web/components/web-share-frame.tsxapps/web/components/web-door-link.tsxapps/web/lib/og-card.tsxapps/web/lib/og-card-lines.tsxpackages/app/src/domain/share-card-lines.tsapps/web/app/join-club/page.tsxpackages/features/clubs/src/join-club-screen.tsxapps/mobile/app/legal/terms.tsxapps/mobile/app/legal/privacy.tsx