careermate 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +22 -17
  2. package/THIRD_PARTY_NOTICES.md +15 -0
  3. package/apps/mcp/src/index.ts +4 -3
  4. package/apps/web/DESIGN_GUIDE.md +2 -2
  5. package/apps/web/demo/demo-shim.js +536 -0
  6. package/apps/web/demo/demo.css +75 -0
  7. package/apps/web/demo/seed.js +269 -0
  8. package/apps/web/public/app.js +34 -2
  9. package/apps/web/public/icon-180.png +0 -0
  10. package/apps/web/public/index.html +14 -3
  11. package/apps/web/public/lib.js +135 -23
  12. package/apps/web/public/pages/applications.js +18 -9
  13. package/apps/web/public/pages/documents.js +66 -50
  14. package/apps/web/public/pages/home.js +12 -11
  15. package/apps/web/public/pages/interview.js +9 -12
  16. package/apps/web/public/pages/jobs.js +39 -36
  17. package/apps/web/public/pages/profile.js +66 -86
  18. package/apps/web/public/pages/settings.js +21 -14
  19. package/apps/web/public/styles.css +105 -38
  20. package/apps/web/src/http.ts +31 -4
  21. package/apps/web/src/info.ts +9 -22
  22. package/apps/web/src/routes.ts +19 -14
  23. package/apps/web/src/server.ts +34 -29
  24. package/apps/web/src/settings.ts +35 -17
  25. package/bin/careermate.mjs +8 -5
  26. package/dist/doctor.mjs +78908 -0
  27. package/dist/install-page/.omc/state/agent-replay-55a58c0d-bb6e-43ea-8a05-4b6c93b80b34.jsonl +12 -0
  28. package/dist/install-page/.omc/state/idle-notif-cooldown.json +3 -0
  29. package/dist/install-page/.omc/state/sessions/55a58c0d-bb6e-43ea-8a05-4b6c93b80b34/mission-state.json +147 -0
  30. package/dist/install-page/.omc/state/sessions/55a58c0d-bb6e-43ea-8a05-4b6c93b80b34/pre-tool-advisory-throttle.json +22 -0
  31. package/dist/install-page/.omc/state/sessions/55a58c0d-bb6e-43ea-8a05-4b6c93b80b34/subagent-tracking-state.json +44 -0
  32. package/dist/install-page/favicon.svg +1 -0
  33. package/dist/install-page/icon-180.png +0 -0
  34. package/dist/install-page/icon-512.png +0 -0
  35. package/dist/install-page/index.html +328 -225
  36. package/dist/install-page/landing.js +54 -0
  37. package/dist/install-page/llms-install.txt +202 -0
  38. package/dist/install-page/og.png +0 -0
  39. package/dist/install-page/shots/applications-dark.png +0 -0
  40. package/dist/install-page/shots/applications-light.png +0 -0
  41. package/dist/install-page/shots/documents-dark.png +0 -0
  42. package/dist/install-page/shots/documents-light.png +0 -0
  43. package/dist/install-page/shots/home-dark.png +0 -0
  44. package/dist/install-page/shots/home-light.png +0 -0
  45. package/dist/install-page/shots/interview-dark.png +0 -0
  46. package/dist/install-page/shots/interview-light.png +0 -0
  47. package/dist/install-page/shots/jobs-dark.png +0 -0
  48. package/dist/install-page/shots/jobs-light.png +0 -0
  49. package/dist/install-page/shots/settings-dark.png +0 -0
  50. package/dist/install-page/shots/settings-light.png +0 -0
  51. package/dist/install-page/start.html +323 -0
  52. package/dist/install-page/style.css +128 -4
  53. package/dist/mcp.mjs +74225 -2007
  54. package/dist/{mcpb-stage/dist/web.mjs → migrate.mjs} +142 -2660
  55. package/dist/pdf.worker.min.mjs +28 -0
  56. package/dist/public/app.js +34 -2
  57. package/dist/public/icon-180.png +0 -0
  58. package/dist/public/index.html +14 -3
  59. package/dist/public/lib.js +135 -23
  60. package/dist/public/pages/applications.js +18 -9
  61. package/dist/public/pages/documents.js +66 -50
  62. package/dist/public/pages/home.js +12 -11
  63. package/dist/public/pages/interview.js +9 -12
  64. package/dist/public/pages/jobs.js +39 -36
  65. package/dist/public/pages/profile.js +66 -86
  66. package/dist/public/pages/settings.js +21 -14
  67. package/dist/public/styles.css +105 -38
  68. package/dist/web.mjs +39950 -369
  69. package/docs/ARCHITECTURE.md +5 -5
  70. package/docs/DECISIONS.md +1 -1
  71. package/docs/DEMO.md +6 -6
  72. package/docs/MCP_TOOLS.md +68 -9
  73. package/docs/ROADMAP.md +11 -10
  74. package/docs/RUNTIME_DISTRIBUTION_RESEARCH.md +135 -0
  75. package/docs/START_WORKFLOW.md +19 -7
  76. package/docs/SUPPORTED_AI_APPS.md +85 -33
  77. package/docs/TODO.md +1 -1
  78. package/docs/WORKFLOWS.md +8 -6
  79. package/docs/superpowers/specs/2026-06-16-demo-dashboard-deploy-design.md +64 -0
  80. package/package.json +8 -3
  81. package/packages/core/src/services.ts +42 -1
  82. package/packages/db/src/connection.ts +30 -0
  83. package/packages/db/src/index.ts +1 -0
  84. package/packages/db/src/paths.ts +11 -0
  85. package/packages/db/src/repositories.ts +109 -63
  86. package/packages/db/src/schema.ts +118 -0
  87. package/packages/exporters/src/html.ts +9 -12
  88. package/packages/mcp-tools/src/bridge.ts +55 -32
  89. package/packages/mcp-tools/src/index.ts +9 -0
  90. package/packages/mcp-tools/src/tools.ts +269 -65
  91. package/packages/mcp-tools/src/update.ts +330 -0
  92. package/packages/parsers/src/documents.ts +521 -0
  93. package/packages/parsers/src/index.ts +8 -5
  94. package/packages/prompts/src/onboarding.ts +2 -2
  95. package/packages/shared/src/build-info.ts +22 -0
  96. package/packages/shared/src/enums.ts +39 -0
  97. package/packages/shared/src/index.ts +1 -0
  98. package/packages/shared/src/schemas.ts +24 -3
  99. package/packages/workflows/src/definitions.ts +4 -2
  100. package/scripts/build-demo.mjs +130 -0
  101. package/scripts/build-dist.mjs +46 -8
  102. package/scripts/build-mcpb.mjs +60 -4
  103. package/scripts/doctor.ts +16 -3
  104. package/scripts/gen-og.mjs +86 -0
  105. package/scripts/init.ts +32 -3
  106. package/scripts/seed.ts +5 -5
  107. package/scripts/shots-seed.ts +192 -0
  108. package/scripts/shots.ts +89 -0
  109. package/tsconfig.json +3 -1
  110. package/dist/careermate.mcpb +0 -0
  111. package/dist/mcp-smoke.err +0 -3
  112. package/dist/mcpb-stage/README.md +0 -219
  113. package/dist/mcpb-stage/dist/install-page/index.html +0 -434
  114. package/dist/mcpb-stage/dist/install-page/style.css +0 -407
  115. package/dist/mcpb-stage/dist/install-page/vercel.json +0 -20
  116. package/dist/mcpb-stage/dist/mcp.mjs +0 -23704
  117. package/dist/mcpb-stage/dist/public/app.js +0 -118
  118. package/dist/mcpb-stage/dist/public/index.html +0 -41
  119. package/dist/mcpb-stage/dist/public/lib.js +0 -282
  120. package/dist/mcpb-stage/dist/public/pages/applications.js +0 -98
  121. package/dist/mcpb-stage/dist/public/pages/documents.js +0 -446
  122. package/dist/mcpb-stage/dist/public/pages/home.js +0 -263
  123. package/dist/mcpb-stage/dist/public/pages/interview.js +0 -230
  124. package/dist/mcpb-stage/dist/public/pages/jobs.js +0 -494
  125. package/dist/mcpb-stage/dist/public/pages/profile.js +0 -576
  126. package/dist/mcpb-stage/dist/public/pages/settings.js +0 -233
  127. package/dist/mcpb-stage/dist/public/styles.css +0 -420
  128. package/dist/mcpb-stage/manifest.json +0 -40
  129. package/docs/INSTALL.md +0 -148
  130. package/docs/INSTALL_AND_USAGE.md +0 -99
  131. package/install-page/index.html +0 -474
  132. package/install-page/style.css +0 -391
  133. package/install-page/vercel.json +0 -20
  134. /package/dist/{mcpb-stage/dist/public → install-page}/fonts/PretendardVariable.woff2 +0 -0
@@ -1,13 +1,50 @@
1
1
  <!DOCTYPE html>
2
- <html lang="ko" data-theme="">
2
+ <html lang="ko" data-theme="dark">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <!-- Resolve the saved theme before first paint (default: dark) to avoid a flash. -->
7
+ <script>
8
+ (function () {
9
+ try {
10
+ var t = window.localStorage.getItem('careermate-theme') || window.localStorage.getItem('cf-theme');
11
+ document.documentElement.setAttribute('data-theme', t === 'light' || t === 'dark' ? t : 'dark');
12
+ } catch (e) { document.documentElement.setAttribute('data-theme', 'dark'); }
13
+ })();
14
+ </script>
6
15
  <title>CareerMate — 내 AI를 커리어 비서로</title>
7
16
  <meta name="description" content="Claude Desktop·Claude Code·Codex 같은 로컬 AI 앱에 연결하세요. CareerMate가 이력서·자기소개서·지원 현황을 이 컴퓨터에만 저장하고 MCP로 당신의 AI에 연결합니다." />
17
+ <link rel="canonical" href="https://careermate.life/" />
18
+ <meta name="theme-color" content="#faf8f4" media="(prefers-color-scheme: light)" />
19
+ <meta name="theme-color" content="#14130f" media="(prefers-color-scheme: dark)" />
20
+
21
+ <!-- icons -->
22
+ <link rel="icon" href="favicon.svg" type="image/svg+xml" />
23
+ <link rel="apple-touch-icon" href="icon-180.png" />
24
+
25
+ <!-- Open Graph -->
26
+ <meta property="og:type" content="website" />
27
+ <meta property="og:site_name" content="CareerMate" />
28
+ <meta property="og:locale" content="ko_KR" />
29
+ <meta property="og:url" content="https://careermate.life/" />
30
+ <meta property="og:title" content="CareerMate — 내 AI를 커리어 비서로" />
31
+ <meta property="og:description" content="이력서·자기소개서·지원 현황을 이 컴퓨터 안에서 관리하세요. 분석·글쓰기는 평소 쓰던 AI가, 데이터 보관은 CareerMate가 맡습니다." />
32
+ <meta property="og:image" content="https://careermate.life/og.png" />
33
+ <meta property="og:image:width" content="1200" />
34
+ <meta property="og:image:height" content="630" />
35
+ <meta property="og:image:alt" content="CareerMate — 로컬 전용 MCP 커리어 워크스페이스" />
36
+
37
+ <!-- Twitter / X -->
38
+ <meta name="twitter:card" content="summary_large_image" />
39
+ <meta name="twitter:title" content="CareerMate — 내 AI를 커리어 비서로" />
40
+ <meta name="twitter:description" content="이력서·자기소개서·지원 현황을 이 컴퓨터 안에서. 데이터는 외부로 나가지 않습니다." />
41
+ <meta name="twitter:image" content="https://careermate.life/og.png" />
42
+
43
+ <link rel="preload" href="fonts/PretendardVariable.woff2" as="font" type="font/woff2" crossorigin />
8
44
  <link rel="stylesheet" href="style.css" />
9
45
  </head>
10
46
  <body>
47
+ <a class="skip-link" href="#top">본문으로 건너뛰기</a>
11
48
  <!-- ============================================================ nav -->
12
49
  <nav class="nav">
13
50
  <a class="nav__brand" href="#top">
@@ -17,7 +54,9 @@
17
54
  <div class="nav__links">
18
55
  <a href="#how">동작 방식</a>
19
56
  <a href="#features">기능</a>
57
+ <a href="#preview">화면</a>
20
58
  <a href="#install">설치</a>
59
+ <a href="start.html">처음이세요?</a>
21
60
  <a href="#privacy">개인정보</a>
22
61
  </div>
23
62
  <div class="nav__actions">
@@ -29,33 +68,40 @@
29
68
  </div>
30
69
  </nav>
31
70
 
32
- <main id="top">
71
+ <main id="top" tabindex="-1">
33
72
 
34
73
  <!-- ========================================================== hero -->
35
74
  <header class="hero">
36
75
  <span class="pill-badge">
37
76
  <span class="pill-badge__dot" aria-hidden="true"></span>
38
- 로컬 전용 · 오픈소스 · Claude Desktop 원클릭
77
+ 로컬 전용 · 무료
39
78
  </span>
40
79
  <h1 class="hero__title">
41
80
  내가 쓰던 <span class="accent">AI</span>를<br />
42
81
  나만의 <span class="accent">커리어 비서</span>로
43
82
  </h1>
44
83
  <p class="hero__lede">
45
- 이력서·자기소개서·지원 현황을 <strong>이 컴퓨터 안에서</strong> 관리하세요.<br />
46
- 분석과 글쓰기는 평소 쓰던 AI가, 데이터 보관은 CareerMate가 맡습니다.
84
+ <strong>공고 분석 · 맞춤 자기소개서 · 지원 현황 추적</strong>을 평소 쓰던 AI에게 말로 시키면,<br />
85
+ 결과가 이 컴퓨터 안에 쌓이고, 한 번 정리한 경력은 대화마다 다시 붙여넣지 않아도 돼요.
47
86
  </p>
48
87
 
88
+ <ul class="trust-strip" aria-label="안심 포인트">
89
+ <li>내 컴퓨터에만 저장</li>
90
+ <li>외부 업로드 없음</li>
91
+ <li>계정·API 키 불필요</li>
92
+ <li>언제든 삭제</li>
93
+ </ul>
94
+
49
95
  <div class="hero__cta">
50
- <a class="btn btn--primary" href="#install">
96
+ <a class="btn btn--primary" href="start.html">처음이세요? — 내게 맞는 설치법 찾기</a>
97
+ <a class="btn btn--ghost" href="#install">
51
98
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
52
- 설치 방법 보기
99
+ 바로 설치 방법 보기
53
100
  </a>
54
- <a class="btn btn--ghost" href="#install-other">기타 MCP 클라이언트</a>
55
101
  </div>
56
102
 
57
103
  <p class="hero__note">
58
- CareerMate는 <strong>내 컴퓨터에서 도는 로컬 도구</strong>라, 내 컴퓨터의 프로그램을 실행할 수 있는 AI에서 동작합니다 — <strong>Claude Desktop · Claude Code · Codex</strong>.
104
+ CareerMate는 <strong>내 컴퓨터에서 도는 로컬 도구</strong>예요. 그래서 <span class="nowrap">Claude&nbsp;Desktop · Claude&nbsp;Code · Codex</span>처럼 내 컴퓨터의 프로그램을 띄울 수 있는 AI에서 동작합니다.<br />
59
105
  설치를 마쳤다면 대시보드 <code>http://127.0.0.1:4319</code>에서 내 데이터를 확인하세요.
60
106
  </p>
61
107
  </header>
@@ -79,8 +125,8 @@
79
125
  <div class="feature__icon">
80
126
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 12h6"/><path d="M9 12a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3"/><path d="M15 12a3 3 0 0 0 3 3v2a3 3 0 0 1-3 3"/></svg>
81
127
  </div>
82
- <h3>2. MCP로 연결</h3>
83
- <p>표준 프로토콜 MCP가 AI와 CareerMate를 잇는 “USB-C” 역할을 합니다.<br />AI가 24개 도구로 당신의 커리어 DB를 읽고 씁니다.</p>
128
+ <h3>2. 안전하게 연결</h3>
129
+ <p>표준 연결 방식(MCP)이 AI와 CareerMate를 잇는 다리가 됩니다.<br />AI가 당신의 커리어 기록을 직접 읽고 정리해 저장합니다.</p>
84
130
  </article>
85
131
  <article class="feature">
86
132
  <div class="feature__icon">
@@ -109,232 +155,290 @@
109
155
  </div>
110
156
  </section>
111
157
 
158
+ <!-- ======================================================= preview -->
159
+ <section id="preview" class="section">
160
+ <div class="section__head">
161
+ <span class="eyebrow">대시보드</span>
162
+ <h2>내 데이터를 <span class="accent">눈으로</span> 확인</h2>
163
+ <p>모든 기록은 이 컴퓨터의 대시보드(<code>127.0.0.1:4319</code>)에 모입니다.<br>아래는 실제 화면 — 설치 없이 바로 둘러볼 수 있어요.</p>
164
+ <div class="section__cta">
165
+ <a class="btn btn--primary" href="demo/">데모 둘러보기 →</a>
166
+ <span class="section__cta-note">샘플 데이터로 클릭해 보는 미리보기 · 설치·로그인 불필요</span>
167
+ </div>
168
+ </div>
169
+
170
+ <div class="carousel" id="dash-carousel" role="group" aria-roledescription="캐러셀" aria-label="대시보드 화면 미리보기" tabindex="0">
171
+ <div class="carousel__viewport">
172
+ <div class="carousel__track" id="carousel-track">
173
+ <figure class="slide">
174
+ <div class="browser">
175
+ <div class="browser__bar">
176
+ <span class="browser__dots" aria-hidden="true"><i></i><i></i><i></i></span>
177
+ <span class="browser__url">127.0.0.1:4319</span>
178
+ </div>
179
+ <div class="browser__body">
180
+ <img class="shot__img shot__img--light" src="shots/home-light.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 홈 대시보드 — 지원 파이프라인과 할 일, 최근 활동" />
181
+ <img class="shot__img shot__img--dark" src="shots/home-dark.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 홈 대시보드 (다크) — 지원 파이프라인과 할 일, 최근 활동" />
182
+ </div>
183
+ </div>
184
+ <figcaption><strong>홈</strong> — 파이프라인·할 일·활동을 한 화면에</figcaption>
185
+ </figure>
186
+
187
+ <figure class="slide">
188
+ <div class="browser">
189
+ <div class="browser__bar">
190
+ <span class="browser__dots" aria-hidden="true"><i></i><i></i><i></i></span>
191
+ <span class="browser__url">127.0.0.1:4319/#/applications</span>
192
+ </div>
193
+ <div class="browser__body">
194
+ <img class="shot__img shot__img--light" src="shots/applications-light.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 지원 현황 — 상태별로 정리된 지원 목록" />
195
+ <img class="shot__img shot__img--dark" src="shots/applications-dark.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 지원 현황 (다크) — 상태별로 정리된 지원 목록" />
196
+ </div>
197
+ </div>
198
+ <figcaption><strong>지원 현황</strong> — 8단계 상태별로 한눈에</figcaption>
199
+ </figure>
200
+
201
+ <figure class="slide">
202
+ <div class="browser">
203
+ <div class="browser__bar">
204
+ <span class="browser__dots" aria-hidden="true"><i></i><i></i><i></i></span>
205
+ <span class="browser__url">127.0.0.1:4319/#/jobs</span>
206
+ </div>
207
+ <div class="browser__body">
208
+ <img class="shot__img shot__img--light" src="shots/jobs-light.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 채용공고 — 적합도 점수와 진행 상태" />
209
+ <img class="shot__img shot__img--dark" src="shots/jobs-dark.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 채용공고 (다크) — 적합도 점수와 진행 상태" />
210
+ </div>
211
+ </div>
212
+ <figcaption><strong>채용공고</strong> — 적합도 점수와 진행 상태</figcaption>
213
+ </figure>
214
+
215
+ <figure class="slide">
216
+ <div class="browser">
217
+ <div class="browser__bar">
218
+ <span class="browser__dots" aria-hidden="true"><i></i><i></i><i></i></span>
219
+ <span class="browser__url">127.0.0.1:4319/#/documents</span>
220
+ </div>
221
+ <div class="browser__body">
222
+ <img class="shot__img shot__img--light" src="shots/documents-light.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 문서 — 자기소개서와 이력서를 버전과 함께 보관" />
223
+ <img class="shot__img shot__img--dark" src="shots/documents-dark.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 문서 (다크) — 자기소개서와 이력서를 버전과 함께 보관" />
224
+ </div>
225
+ </div>
226
+ <figcaption><strong>문서</strong> — 자기소개서·이력서를 버전과 함께</figcaption>
227
+ </figure>
228
+
229
+ <figure class="slide">
230
+ <div class="browser">
231
+ <div class="browser__bar">
232
+ <span class="browser__dots" aria-hidden="true"><i></i><i></i><i></i></span>
233
+ <span class="browser__url">127.0.0.1:4319/#/interview</span>
234
+ </div>
235
+ <div class="browser__body">
236
+ <img class="shot__img shot__img--light" src="shots/interview-light.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 면접 준비 — 예상 질문과 STAR, 1분 자기소개" />
237
+ <img class="shot__img shot__img--dark" src="shots/interview-dark.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 면접 준비 (다크) — 예상 질문과 STAR, 1분 자기소개" />
238
+ </div>
239
+ </div>
240
+ <figcaption><strong>면접 준비</strong> — 예상 질문·STAR·1분 자기소개</figcaption>
241
+ </figure>
242
+
243
+ <figure class="slide">
244
+ <div class="browser">
245
+ <div class="browser__bar">
246
+ <span class="browser__dots" aria-hidden="true"><i></i><i></i><i></i></span>
247
+ <span class="browser__url">127.0.0.1:4319/#/settings</span>
248
+ </div>
249
+ <div class="browser__body">
250
+ <img class="shot__img shot__img--light" src="shots/settings-light.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 설정 — 데이터 저장 위치와 연결 상태, 테마" />
251
+ <img class="shot__img shot__img--dark" src="shots/settings-dark.png" width="1360" height="940" loading="lazy" decoding="async" alt="CareerMate 설정 (다크) — 데이터 저장 위치와 연결 상태, 테마" />
252
+ </div>
253
+ </div>
254
+ <figcaption><strong>설정</strong> — 데이터 위치·내보내기·테마</figcaption>
255
+ </figure>
256
+ </div>
257
+ </div>
258
+
259
+ <button class="carousel__arrow carousel__arrow--prev" id="carousel-prev" type="button" aria-label="이전 화면">
260
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6"/></svg>
261
+ </button>
262
+ <button class="carousel__arrow carousel__arrow--next" id="carousel-next" type="button" aria-label="다음 화면">
263
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 18l6-6-6-6"/></svg>
264
+ </button>
265
+ </div>
266
+ <div class="carousel__dots" id="carousel-dots" role="tablist" aria-label="화면 선택"></div>
267
+ </section>
268
+
112
269
  <!-- ======================================================= install -->
113
270
  <section id="install" class="section">
114
271
  <div class="section__head">
115
272
  <span class="eyebrow">설치</span>
116
- <h2>세 가지 AI 앱에 연결</h2>
117
- <p>지원하는 로컬 AI 앱은 <strong>Claude Desktop · Claude Code · Codex</strong> 셋입니다. 어느 쪽이든 같은 코어(로컬 DB + 도구 24개)를 씁니다.</p>
273
+ <h2>내 <span class="accent">AI 앱</span>에 연결하기</h2>
274
+ <p>빈 폴더 잡고 <strong>한 문장이면 끝.</strong><br />
275
+ 터미널이 익숙하면 한 줄 설치, 싫으면 파일 하나로 — <strong>무료도 있습니다.</strong></p>
118
276
  </div>
119
277
 
278
+ <a class="note" href="start.html" style="display:block;text-decoration:none;border-left-color:var(--accent);background:var(--accent-soft)">
279
+ <strong style="color:var(--text)">완전 처음이세요?</strong> 터미널·구독이 뭔지 몰라도 괜찮아요 — 쓰는 AI와 컴퓨터만 고르면 <strong>맞는 길 하나</strong>를 알려드려요. <strong style="color:var(--accent)">길 찾기 →</strong>
280
+ </a>
281
+
120
282
  <div class="note">
121
- <strong>어떤 AI에서 되나요?</strong> CareerMate는 데이터를 내 컴퓨터에만 두는 <strong>로컬 MCP 도구</strong>입니다.
122
- 그래서 <strong>내 컴퓨터에서 실행되며 로컬 프로그램을 띄울 수 있는 AI</strong>에서 동작합니다 — Claude Desktop · Claude Code · Codex(그 외 Cursor·Cline·Windsurf 등도 가능).
123
- ChatGPT·Gemini·Claude의 <strong>웹/모바일 앱</strong>은 클라우드에서 돌아 내 컴퓨터의 로컬 서버에 직접 연결할 수 없습니다(원격 URL 기반 MCP만 지원).
283
+ <strong>어떤 AI에서 되나요?</strong> 내 컴퓨터에서 프로그램을 띄울 수 있는 AI에서만 됩니다.<br />
284
+ <strong style="color:var(--accent)">✓</strong> Claude Desktop · Claude Code · Codex · Cursor 등 &nbsp;/&nbsp; <strong style="color:var(--warn-text)">✗</strong> ChatGPT·Gemini·Claude의 <strong>웹·모바일</strong>(클라우드라 내 컴퓨터 서버에 못 닿음).
124
285
  </div>
125
286
 
126
- <!-- track 1 · Claude Desktop -->
127
- <div class="track">
128
- <div class="track__head">
129
- <span class="track__tag">1 · Claude Desktop</span>
130
- <h3>원클릭 <code>.mcpb</code> 설치</h3>
131
- <p>터미널도, Node 설치도 필요 없습니다. 파일 하나를 더블클릭하면 끝납니다.</p>
132
- </div>
133
- <ol class="steps">
287
+ <!-- track 1 · 앱에서 직접 설치 (비개발자 메인) -->
288
+ <details class="acc" open>
289
+ <summary><span class="track__tag">추천 · 앱에서 한 문장</span> 내 AI 앱에서 빈 폴더 잡고 한 문장</summary>
290
+ <div class="acc__body">
291
+ <p class="track-desc"><strong>Claude 데스크톱의 “Code” 탭</strong>처럼 폴더를 잡고 작동하는 AI 앱이면 <strong>별도 터미널 없이</strong> 앱 안에서 끝납니다(Codex는 <strong>CLI</strong> 권장 — 데스크톱 앱은 등록이 사라질 수 있습니다). 작업 폴더 하나를 정하고 아래 문장만 주면, 에이전트가 공개 안내(<code>careermate.life/llms-install.txt</code>)를 읽고 <strong>그 폴더 안에</strong> 설치·연결합니다. 데이터까지 그 폴더에 모여(<code>.cm/data</code>) 백업·이동이 폴더 하나로 끝.</p>
292
+ <ol class="steps">
134
293
  <li class="step">
135
294
  <div class="step__no">1</div>
136
295
  <div class="step__body">
137
- <h3>설치 파일 받기</h3>
138
- <p><code>careermate.mcpb</code> 파일이 필요합니다. <strong>(Release <code>v0.1.0</code>에 있으나 저장소가 비공개라 공개 다운로드 링크는 아직 없습니다.)</strong></p>
139
- <!-- TODO: 저장소를 public으로 전환하면 https://github.com/osntak/CareerMate/releases/latest 의 .mcpb로 이 버튼을 활성화. 현재는 private repo라 공개 다운로드 불가. -->
140
- <button class="btn btn--primary" type="button" disabled aria-disabled="true">
141
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
142
- careermate.mcpb 다운로드 (비공개 저장소)
143
- </button>
144
- <p class="step__tip">접근 권한이 있으면 Release <code>v0.1.0</code>에서 받고, 없으면 터미널에서 <code>npx -y careermate init</code>로 설치하거나 소스에서 <code>npm run build:mcpb</code>로 빌드하세요.</p>
296
+ <h3>앱 열고 빈 폴더 선택</h3>
297
+ <p><strong>Claude 데스크톱</strong> → <strong>Code</strong> 탭에서 빈 폴더를 작업 폴더로 선택(<strong>Pro 이상</strong> 구독, <strong>Windows는 Git 먼저</strong>). <strong>Codex</strong>는 빈 폴더에서 <code>codex</code>(CLI, <strong>ChatGPT Plus 이상</strong>)로 실행하세요 — <strong>데스크톱 앱은 등록이 사라질 수 있어</strong> 권장하지 않습니다.</p>
145
298
  </div>
146
299
  </li>
147
300
  <li class="step">
148
301
  <div class="step__no">2</div>
149
302
  <div class="step__body">
150
- <h3>더블클릭으로 설치</h3>
151
- <p>내려받은 <code>careermate.mcpb</code>를 더블클릭하면 Claude Desktop이 설치 창을 엽니다. <strong>설치</strong>를 누르세요.
152
- (또는 Claude Desktop → <strong>Settings → Extensions</strong>에 파일을 끌어다 놓아도 됩니다.)</p>
303
+ <h3>이 문장 붙여넣기</h3>
304
+ <p class="paste-note">💬 위에서 연 <strong>AI 앱의 대화창에</strong> 붙여넣으세요 — 터미널 명령이 아니에요. 이 문장은 공개 안내 페이지만 읽어 설치하며, <strong>당신의 이력서·개인정보는 외부로 올라가지 않아요.</strong></p>
305
+ <div class="code">
306
+ <button class="copy-btn" type="button" data-copy-target="code-prompt-agent">복사</button>
307
+ <pre id="code-prompt-agent">https://careermate.life/llms-install.txt 를 읽고, 그 안내대로 CareerMate를 이 폴더에 설치하고 연결해줘. 데이터도 이 폴더의 .cm/data 안에 저장하고, Node 설치처럼 시스템에 바꿀 게 있으면 실행 전에 먼저 알려줘. 설치가 끝나면 앱 재시작 방법과 이력서를 주는 법, 대시보드 주소(http://127.0.0.1:4319)도 알려줘.</pre>
308
+ </div>
309
+ <p class="step__tip">준비물은 <strong>Node.js 22.5 이상</strong> 하나뿐. 없으면 에이전트가 <strong>먼저 확인하고</strong> 설치를 도와줍니다. 데이터는 작업 폴더의 <code>.cm/data</code>에만 저장됩니다. (Codex CLI는 설치 단계에서 네트워크 허용을 한 번 물을 수 있어요 — 허용하면 됩니다.)</p>
153
310
  </div>
154
311
  </li>
155
312
  <li class="step">
156
313
  <div class="step__no">3</div>
157
314
  <div class="step__body">
158
- <h3>재시작하고 확인</h3>
159
- <p>Claude Desktop을 완전히 종료했다 다시 켜세요. 그다음 Claude에게
160
- <strong>“<code>get_onboarding_status</code> 호출해서 연결됐는지 확인해줘”</strong>라고 말해 결과가 돌아오면 정상입니다.</p>
315
+ <h3>재시작 후 확인</h3>
316
+ <p>AI 앱을 완전히 종료했다 다시 켜고(처음 한 번 승인을 물으면 허용), <strong>“커리어메이트 연결됐는지 확인해줘”</strong>라고 말해 보세요. Codex는 <code>/mcp</code>로도 확인됩니다.</p>
161
317
  </div>
162
318
  </li>
163
- </ol>
164
- <p class="step__tip">Claude Desktop이 Node를 내장하므로 따로 설치할 게 없습니다. 드물게 내장 Node가 22.5 미만이라 설치가 막히면 아래 <a href="#install-other">터미널 방식</a>을 쓰세요.</p>
165
- </div>
166
-
167
- <!-- track 2 · Claude Code -->
168
- <div class="track">
169
- <div class="track__head">
170
- <span class="track__tag">2 · Claude Code</span>
171
- <h3>CareerMate 폴더에서 한 문장으로</h3>
172
- <p>루트 <code>CLAUDE.md</code>가 설치 안내 역할을 합니다. 폴더를 열고 아래 문장만 말하세요.</p>
319
+ </ol>
173
320
  </div>
174
- <ol class="steps">
321
+ </details>
322
+
323
+ <!-- track 2 · npx 한 줄 -->
324
+ <details class="acc">
325
+ <summary><span class="track__tag">터미널 · 한 줄 설치</span> npx 한 줄로 자동 연결</summary>
326
+ <div class="acc__body">
327
+ <p class="track-desc">준비물은 <strong>Node.js 22.5 이상</strong> 하나. 감지된 AI 앱(Claude Desktop·Codex·Cursor)의 MCP 설정에 CareerMate를 자동 등록합니다.</p>
328
+ <ol class="steps">
175
329
  <li class="step">
176
330
  <div class="step__no">1</div>
177
331
  <div class="step__body">
178
- <h3>CareerMate 폴더에서 Claude Code 열기</h3>
179
- <p>CareerMate 폴더에서 <code>claude</code>를 실행한 뒤, 아래 문장을 그대로 입력합니다. Claude가 <code>INSTALL.md</code>를 따라 등록까지 진행합니다.</p>
332
+ <h3>한 줄 실행</h3>
333
+ <p>터미널(Windows는 PowerShell)에 붙여넣고 실행하세요. 클론도 빌드도 필요 없습니다. <code>node --version</code>이 22.5 미만이면 <a href="https://nodejs.org/" rel="noopener" target="_blank">nodejs.org</a>에서 LTS를 먼저 설치하세요.</p>
180
334
  <div class="code">
181
- <button class="copy-btn" type="button" data-copy-target="code-prompt-cc">복사</button>
182
- <pre id="code-prompt-cc">CareerMate를 설치하고 설정해줘. INSTALL.md를 따라 진행해줘.</pre>
335
+ <button class="copy-btn" type="button" data-copy-target="code-npx">복사</button>
336
+ <pre id="code-npx">npx -y careermate init</pre>
183
337
  </div>
338
+ <p class="step__tip">특정 클라이언트만 등록하려면 <code>npx -y careermate init --client cursor</code>, 설정 JSON·명령만 보고 직접 붙여넣으려면 <code>npx -y careermate init --print</code>. (클라이언트: <code>claude</code> · <code>claude-code</code> · <code>codex</code> · <code>cursor</code>)</p>
184
339
  </div>
185
340
  </li>
186
341
  <li class="step">
187
342
  <div class="step__no">2</div>
188
343
  <div class="step__body">
189
- <h3>한 번만 승인하고 확인</h3>
190
- <p>Claude Code가 프로젝트 MCP 서버 등록을 <strong>한 번 승인</strong> 요청하면 허용하세요. 그다음 <strong>“<code>get_onboarding_status</code> 호출해서 연결됐는지 확인해줘”</strong>로 점검합니다.</p>
191
- </div>
192
- </li>
193
- </ol>
194
- </div>
195
-
196
- <!-- track 3 · Codex -->
197
- <div class="track">
198
- <div class="track__head">
199
- <span class="track__tag">3 · Codex</span>
200
- <h3>CareerMate 폴더에서 한 문장으로</h3>
201
- <p>루트 <code>AGENTS.md</code>가 설치 안내 역할을 합니다. 폴더를 열고 같은 문장을 말하세요.</p>
202
- </div>
203
- <ol class="steps">
204
- <li class="step">
205
- <div class="step__no">1</div>
206
- <div class="step__body">
207
- <h3>CareerMate 폴더에서 Codex 열기</h3>
208
- <p>CareerMate 폴더에서 <code>codex</code>를 실행한 뒤, 아래 문장을 그대로 입력합니다. Codex가 <code>INSTALL.md</code>를 따라 등록까지 진행합니다.</p>
209
- <div class="code">
210
- <button class="copy-btn" type="button" data-copy-target="code-prompt-codex">복사</button>
211
- <pre id="code-prompt-codex">CareerMate를 설치하고 설정해줘. INSTALL.md를 따라 진행해줘.</pre>
212
- </div>
344
+ <h3>AI 앱 재시작 후 확인</h3>
345
+ <p>연결한 AI 앱을 <strong>완전히 종료했다 다시 켜고</strong>, <strong>“커리어메이트 연결됐는지 확인해줘”</strong>라고 말해 결과가 돌아오면 정상입니다.</p>
213
346
  </div>
214
347
  </li>
215
348
  <li class="step">
216
- <div class="step__no">2</div>
349
+ <div class="step__no">3</div>
217
350
  <div class="step__body">
218
- <h3><code>/mcp</code>로 확인</h3>
219
- <p>Codex 안에서 <code>/mcp</code> 명령으로 <code>careermate</code>가 등록됐는지 확인하고, <strong>“<code>get_onboarding_status</code> 호출해서 연결됐는지 확인해줘”</strong>로 점검합니다.</p>
351
+ <h3>대시보드 열기 (선택)</h3>
352
+ <p>내 데이터를 눈으로 보려면 <code>npx -y careermate start</code> 실행 → <code>http://127.0.0.1:4319</code>. 종료는 <kbd>Ctrl</kbd>+<kbd>C</kbd>.</p>
220
353
  </div>
221
354
  </li>
222
- </ol>
223
- </div>
224
-
225
- <!-- track · 기타 MCP 클라이언트 (터미널) -->
226
- <div class="track" id="install-other">
227
- <div class="track__head">
228
- <span class="track__tag">기타 MCP 클라이언트 · 터미널</span>
229
- <h3>Cursor 등 — 직접 등록</h3>
230
- <p>Cursor · Cline · Windsurf 등 다른 로컬 stdio MCP 클라이언트는 터미널에서 직접 설치·등록합니다.</p>
231
- </div>
232
-
233
- <div class="note">
234
- <strong>준비물은 Node.js 22.5 이상</strong> 하나뿐입니다. 내장 SQLite를 쓰므로 별도 컴파일러·빌드 도구가 필요 없습니다.
235
- 터미널(Windows는 PowerShell)에서 <code>node --version</code>으로 확인하고, 낮으면
236
- <a href="https://nodejs.org/" rel="noopener" target="_blank">nodejs.org</a>에서 LTS를 설치하세요.
355
+ </ol>
237
356
  </div>
357
+ </details>
238
358
 
239
- <ol class="steps">
359
+ <!-- track 3 · .mcpb (데모트) -->
360
+ <details class="acc">
361
+ <summary><span class="track__tag">Claude Desktop · <code>.mcpb</code></span> 설치 파일로 추가 (터미널 없이)</summary>
362
+ <div class="acc__body">
363
+ <p class="track-desc">터미널·Node 없이 파일 하나로 끝나지만, <strong>Claude Desktop 내장 Node 버전에 따라 불안정할 수 있습니다.</strong> 잘 안 되면 위 <strong>에이전트가 직접 설치</strong> 또는 <strong>터미널 한 줄</strong>을 쓰세요.</p>
364
+ <ol class="steps">
240
365
  <li class="step">
241
366
  <div class="step__no">1</div>
242
367
  <div class="step__body">
243
- <h3>코드 받기</h3>
244
- <p>CareerMate 저장소를 내려받습니다. (Git이 없으면 <em>Code → Download ZIP</em>으로 받아 압축을 풀어도 됩니다.)</p>
245
- <!-- 저장소(osntak/CareerMate)는 현재 비공개라 clone에 접근 권한이 필요합니다. 권한이 없으면 위 npx 방식을 쓰세요. -->
246
- <div class="code">
247
- <button class="copy-btn" type="button" data-copy-target="code-clone">복사</button>
248
- <pre id="code-clone">git clone https://github.com/osntak/CareerMate.git
249
- cd CareerMate</pre>
250
- </div>
368
+ <h3>설치 파일 받기</h3>
369
+ <p>아래 버튼으로 <code>careermate.mcpb</code>를 내려받으세요. (약 2&nbsp;MB)</p>
370
+ <a class="btn btn--ghost" href="careermate.mcpb" download="careermate.mcpb">
371
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
372
+ careermate.mcpb 다운로드
373
+ </a>
251
374
  </div>
252
375
  </li>
253
376
  <li class="step">
254
377
  <div class="step__no">2</div>
255
378
  <div class="step__body">
256
- <h3>설치</h3>
257
- <p>의존성을 한 번만 설치합니다. (빌드 단계 없음) — 또는 클론 없이 <strong><code>npx -y careermate init</code></strong> 한 줄로도 등록됩니다(<code>careermate</code> npm 게시 완료).</p>
258
- <div class="code">
259
- <span class="code__label">프로젝트 폴더에서</span>
260
- <button class="copy-btn" type="button" data-copy-target="code-install">복사</button>
261
- <pre id="code-install">npm install</pre>
262
- </div>
379
+ <h3>Claude Desktop 설정에서 추가</h3>
380
+ <p>Claude Desktop → <strong>Settings(설정) → Extensions(확장)</strong>에서 <strong>Advanced settings(고급 설정)</strong>를 누르면 나오는 <strong>Install extension…</strong>으로 내려받은 <code>careermate.mcpb</code>를 선택하세요.</p>
381
+ <p class="step__tip">더블클릭·드래그는 Windows에서 파일 연결이 안 잡혀 <strong>반응이 없을 수 있으니</strong>, 위 설정 메뉴 경로를 쓰세요. (확장을 처음 설치하면 <strong>Advanced settings</strong>를 먼저 눌러야 버튼이 보입니다.)</p>
263
382
  </div>
264
383
  </li>
265
384
  <li class="step">
266
385
  <div class="step__no">3</div>
267
386
  <div class="step__body">
268
- <h3>AI 클라이언트에 자동 연결</h3>
269
- <p>감지된 클라이언트의 MCP 설정에 CareerMate를 자동 등록하고, Claude Code 프로젝트 설정(<code>.mcp.json</code>)은 항상 함께 작성합니다. 끝나면 해당 AI 클라이언트를 <strong>완전히 종료했다 다시 켜세요.</strong></p>
270
- <div class="code">
271
- <span class="code__label">자동 등록</span>
272
- <button class="copy-btn" type="button" data-copy-target="code-init">복사</button>
273
- <pre id="code-init">npm run init</pre>
274
- </div>
275
- <p class="step__tip">직접 붙여넣고 싶다면 <code>npm run init -- --print</code>로 설정 JSON·명령만 출력해 클라이언트에 추가하세요. 특정 클라이언트만 등록하려면 <code>npm run init -- --client cursor</code>처럼 지정합니다. 클라이언트별 설정 파일 위치는 아래 탭을 참고하세요.</p>
276
-
277
- <div class="tabs" role="tablist" aria-label="설정 파일 위치">
278
- <button class="tab is-active" id="tab-claude" role="tab" aria-controls="panel-claude" aria-selected="true">Claude Desktop</button>
279
- <button class="tab" id="tab-cursor" role="tab" aria-controls="panel-cursor" aria-selected="false" tabindex="-1">Cursor / 기타</button>
280
- </div>
281
- <div class="panel" id="panel-claude" role="tabpanel" aria-labelledby="tab-claude" data-active="true">
282
- <p class="path-note">Windows: <code>%APPDATA%\Claude\claude_desktop_config.json</code> · macOS: <code>~/Library/Application Support/Claude/claude_desktop_config.json</code><br />(Settings → Developer → Edit Config 로도 열 수 있습니다. <code>npm run init</code>이 이 파일을 자동으로 수정합니다.)</p>
283
- </div>
284
- <div class="panel" id="panel-cursor" role="tabpanel" aria-labelledby="tab-cursor" data-active="false" hidden>
285
- <p class="path-note">프로젝트별: <code>.cursor/mcp.json</code> · 전역: <code>~/.cursor/mcp.json</code> — Cursor·Cline·Windsurf 등 대부분 같은 형식입니다. 추가 후 클라이언트를 다시 시작하세요.</p>
286
- </div>
387
+ <h3>재시작하고 확인</h3>
388
+ <p>Claude Desktop을 완전히 종료했다 다시 켜고, <strong>“커리어메이트 연결됐는지 확인해줘”</strong>라고 말해 보세요.</p>
287
389
  </div>
288
390
  </li>
289
- <li class="step">
290
- <div class="step__no">4</div>
291
- <div class="step__body">
292
- <h3>대시보드 실행 (선택)</h3>
293
- <p>내 데이터를 눈으로 확인하려면 대시보드를 켭니다. 기본 주소는 <code>http://127.0.0.1:4319</code>, 포트가 사용 중이면 다음 빈 포트로 넘어갑니다. 종료는 <kbd>Ctrl</kbd>+<kbd>C</kbd>.</p>
294
- <div class="code">
295
- <span class="code__label">대시보드 시작</span>
296
- <button class="copy-btn" type="button" data-copy-target="code-start">복사</button>
297
- <pre id="code-start">npm start</pre>
298
- </div>
391
+ </ol>
392
+ </div>
393
+ </details>
394
+
395
+ <!-- 수동 등록 · 설정 파일 위치 · 소스에서 실행 -->
396
+ <details class="acc" id="install-other">
397
+ <summary>수동 등록 · 설정 파일 위치 <span class="acc__hint">Cursor·Cline·Windsurf</span></summary>
398
+ <div class="acc__body">
399
+ <p class="step__tip"><code>npx -y careermate init --print</code>로 설정 JSON·명령만 출력해 클라이언트에 직접 추가할 수 있습니다. 클라이언트별 설정 파일 위치는 아래 탭을 참고하세요.</p>
400
+
401
+ <div class="tabs" role="tablist" aria-label="설정 파일 위치">
402
+ <button class="tab is-active" id="tab-claude" role="tab" aria-controls="panel-claude" aria-selected="true">Claude Desktop</button>
403
+ <button class="tab" id="tab-cursor" role="tab" aria-controls="panel-cursor" aria-selected="false" tabindex="-1">Cursor / 기타</button>
404
+ </div>
405
+ <div class="panel" id="panel-claude" role="tabpanel" aria-labelledby="tab-claude" data-active="true">
406
+ <p class="path-note">Windows: <code>%APPDATA%\Claude\claude_desktop_config.json</code> · macOS: <code>~/Library/Application Support/Claude/claude_desktop_config.json</code><br />(Settings → Developer → Edit Config 로도 열 수 있습니다. <code>npx -y careermate init</code>이 이 파일을 자동으로 수정합니다.)</p>
407
+ </div>
408
+ <div class="panel" id="panel-cursor" role="tabpanel" aria-labelledby="tab-cursor" data-active="false" hidden>
409
+ <p class="path-note">프로젝트별: <code>.cursor/mcp.json</code> · 전역: <code>~/.cursor/mcp.json</code> — Cursor·Cline·Windsurf 등 대부분 같은 형식입니다. 추가 후 클라이언트를 다시 시작하세요.</p>
410
+ </div>
411
+ </div>
412
+ </details>
413
+
414
+ <!-- 트러블슈팅 -->
415
+ <details class="acc">
416
+ <summary>문제가 생겼을 때 <span class="acc__hint">포트 충돌 · MCP 연결 실패 · 데이터 위치 · 초기화</span></summary>
417
+ <div class="acc__body">
418
+ <div class="trouble">
419
+ <div class="trouble__item">
420
+ <h4>포트가 이미 사용 중</h4>
421
+ <p>4319가 막히면 자동으로 다음 빈 포트로 옮겨갑니다. 터미널에 출력된 실제 주소를 사용하거나, <code>CAREERMATE_PORT</code> 환경변수로 고정하세요.</p>
299
422
  </div>
300
- </li>
301
- <li class="step">
302
- <div class="step__no">5</div>
303
- <div class="step__body">
304
- <h3>연결 확인</h3>
305
- <p>AI에게 <strong>“<code>get_onboarding_status</code>를 호출해서 연결됐는지 확인해줘”</strong>라고 말해 보세요. 결과가 돌아오면 정상입니다.</p>
423
+ <div class="trouble__item">
424
+ <h4>AI에 MCP가 연결되지 않음</h4>
425
+ <p>① <code>npx -y careermate init</code>이 정상 종료됐는지 ② <code>node --version</code>이 22.5 이상인지 ③ 클라이언트를 <strong>완전히 종료 후 재시작</strong>했는지 확인하세요. 폴더를 옮기거나 이름을 바꿨다면 등록된 경로가 깨질 수 있으니 init을 다시 실행하세요.</p>
306
426
  </div>
307
- </li>
308
- </ol>
309
-
310
- <details class="acc">
311
- <summary>문제가 생겼을 때 <span class="acc__hint">포트 충돌 · MCP 연결 실패 · 데이터 위치 · 초기화</span></summary>
312
- <div class="acc__body">
313
- <div class="trouble">
314
- <div class="trouble__item">
315
- <h4>포트가 이미 사용 중</h4>
316
- <p>4319가 막히면 자동으로 다음 빈 포트로 옮겨갑니다. 터미널에 출력된 실제 주소를 사용하거나, <code>CAREERMATE_PORT</code> 환경변수로 고정하세요.</p>
317
- </div>
318
- <div class="trouble__item">
319
- <h4>AI에 MCP가 연결되지 않음</h4>
320
- <p>① <code>npm run init</code>이 정상 종료됐는지 ② <code>node --version</code>이 22.5 이상인지 ③ 클라이언트를 <strong>완전히 종료 후 재시작</strong>했는지 ④ <code>npm install</code>이 끝났는지 확인하세요. 폴더를 옮기거나 이름을 바꿨다면 등록된 경로가 깨지므로 <code>npm run init</code>을 다시 실행하세요.</p>
321
- </div>
322
- <div class="trouble__item">
323
- <h4>상태 점검</h4>
324
- <p>프로젝트 폴더에서 진단을 실행하면 Node 버전·데이터 폴더·DB 상태를 점검합니다.</p>
325
- <div class="code">
326
- <button class="copy-btn" type="button" data-copy-target="code-doctor">복사</button>
327
- <pre id="code-doctor">npm run doctor</pre>
328
- </div>
329
- </div>
330
- <div class="trouble__item">
331
- <h4>데이터 위치 / 초기화</h4>
332
- <p>기본 위치는 <code>~/.careermate/careermate.sqlite</code>(Windows: <code>%USERPROFILE%\.careermate</code>). <code>CAREERMATE_DATA_DIR</code>로 변경 가능. <code>npm run migrate</code>는 DB를 준비/업그레이드(반복 실행 안전)하고, 완전 초기화는 <code>careermate.sqlite</code> 삭제 후 재실행(백업 권장)입니다.</p>
427
+ <div class="trouble__item">
428
+ <h4>상태 점검</h4>
429
+ <p>진단을 실행하면 Node 버전·데이터 폴더·DB 상태를 점검합니다.</p>
430
+ <div class="code">
431
+ <button class="copy-btn" type="button" data-copy-target="code-doctor">복사</button>
432
+ <pre id="code-doctor">npx -y careermate doctor</pre>
333
433
  </div>
334
434
  </div>
435
+ <div class="trouble__item">
436
+ <h4>데이터 위치 / 초기화</h4>
437
+ <p>기본 위치는 <code>~/.careermate/careermate.sqlite</code>(Windows: <code>%USERPROFILE%\.careermate</code>). <code>CAREERMATE_DATA_DIR</code>로 변경 가능. 완전 초기화는 <code>careermate.sqlite</code> 삭제 후 재실행(백업 권장)입니다.</p>
438
+ </div>
335
439
  </div>
336
- </details>
337
- </div>
440
+ </div>
441
+ </details>
338
442
  </section>
339
443
 
340
444
  <!-- ======================================================= privacy -->
@@ -345,7 +449,7 @@ cd CareerMate</pre>
345
449
  </div>
346
450
  <div class="privacy-card__text">
347
451
  <h2>당신의 데이터는 당신 컴퓨터를 떠나지 않습니다</h2>
348
- <p>대시보드 서버는 <code>127.0.0.1</code>(이 컴퓨터)에만 바인딩되어 외부에서 접근할 수 없고,<br />MCP 서버는 네트워크 호출을 하지 않습니다. 분석·글쓰기는 당신이 직접 고른 AI가 수행합니다.</p>
452
+ <p>대시보드 서버는 <code>127.0.0.1</code>(이 컴퓨터)에만 바인딩되어 외부에서 접근할 수 없습니다.<br />MCP 서버가 외부로 내보내는 것은 (끌 수 있는) <strong>최신 버전 확인</strong>뿐이며, <strong>당신의 커리어 데이터는 전송하지 않습니다.</strong> 분석·글쓰기는 당신이 직접 고른 AI가 수행합니다.</p>
349
453
  <ul class="privacy-card__list">
350
454
  <li><strong>저장 위치</strong> <code>~/.careermate/careermate.sqlite</code></li>
351
455
  <li><strong>내보내기</strong> 자기소개서 등을 <code>~/.careermate/exports</code>로</li>
@@ -369,42 +473,10 @@ cd CareerMate</pre>
369
473
 
370
474
  <div class="sr-only" role="status" aria-live="polite" id="copy-status"></div>
371
475
 
476
+ <script src="landing.js"></script>
372
477
  <script>
373
478
  (function () {
374
479
  'use strict';
375
- var status = document.getElementById('copy-status');
376
-
377
- // --- generic clipboard helper ------------------------------------
378
- function legacyCopy(text) {
379
- var ta = document.createElement('textarea');
380
- ta.value = text; ta.setAttribute('readonly', '');
381
- ta.style.position = 'absolute'; ta.style.left = '-9999px';
382
- document.body.appendChild(ta); ta.select();
383
- var ok = false;
384
- try { ok = document.execCommand('copy'); } catch (e) { ok = false; }
385
- document.body.removeChild(ta);
386
- return ok;
387
- }
388
- function copyText(text, onok) {
389
- if (navigator.clipboard && navigator.clipboard.writeText) {
390
- navigator.clipboard.writeText(text).then(onok, function () { if (legacyCopy(text)) onok(); });
391
- } else if (legacyCopy(text)) { onok(); }
392
- }
393
- function announce(msg) { if (status) status.textContent = msg; }
394
-
395
- // --- copy buttons (code blocks) ----------------------------------
396
- function flashSmall(btn) {
397
- var original = btn.textContent;
398
- btn.textContent = '복사됨'; btn.classList.add('copied');
399
- announce('클립보드에 복사되었습니다.');
400
- window.setTimeout(function () { btn.textContent = original; btn.classList.remove('copied'); }, 1600);
401
- }
402
- document.querySelectorAll('.copy-btn').forEach(function (btn) {
403
- btn.addEventListener('click', function () {
404
- var src = document.getElementById(btn.getAttribute('data-copy-target'));
405
- if (src) copyText(src.textContent || '', function () { flashSmall(btn); });
406
- });
407
- });
408
480
 
409
481
  // --- config tabs -------------------------------------------------
410
482
  var tablist = document.querySelector('.tabs[role="tablist"]');
@@ -449,24 +521,55 @@ cd CareerMate</pre>
449
521
  revealEls.forEach(function (el) { io.observe(el); });
450
522
  }
451
523
 
452
- // --- theme toggle (persist) --------------------------------------
453
- var root = document.documentElement;
454
- var toggle = document.getElementById('theme-toggle');
455
- var saved = null;
456
- try { saved = window.localStorage.getItem('cf-theme'); } catch (e) {}
457
- if (saved === 'dark' || saved === 'light') root.setAttribute('data-theme', saved);
458
- function isDark() {
459
- var t = root.getAttribute('data-theme');
460
- if (t === 'dark') return true;
461
- if (t === 'light') return false;
462
- return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
463
- }
464
- if (toggle) {
465
- toggle.addEventListener('click', function () {
466
- var next = isDark() ? 'light' : 'dark';
467
- root.setAttribute('data-theme', next);
468
- try { window.localStorage.setItem('cf-theme', next); } catch (e) {}
524
+ // --- dashboard carousel (prev/next + dots + keyboard + swipe) -----
525
+ var carousel = document.getElementById('dash-carousel');
526
+ var track = document.getElementById('carousel-track');
527
+ if (carousel && track) {
528
+ var slides = Array.prototype.slice.call(track.children);
529
+ var prevBtn = document.getElementById('carousel-prev');
530
+ var nextBtn = document.getElementById('carousel-next');
531
+ var dotsWrap = document.getElementById('carousel-dots');
532
+ var idx = 0;
533
+ var captionOf = function (s) {
534
+ var f = s.querySelector('figcaption');
535
+ return f ? f.textContent.trim() : '';
536
+ };
537
+ var dots = slides.map(function (s, n) {
538
+ var b = document.createElement('button');
539
+ b.type = 'button'; b.className = 'carousel__dot';
540
+ b.setAttribute('role', 'tab');
541
+ b.setAttribute('aria-label', captionOf(s) || (n + 1) + '번째 화면');
542
+ b.addEventListener('click', function () { go(n); });
543
+ dotsWrap.appendChild(b);
544
+ return b;
545
+ });
546
+ function go(n) {
547
+ idx = Math.max(0, Math.min(slides.length - 1, n));
548
+ track.style.transform = 'translateX(' + (-idx * 100) + '%)';
549
+ dots.forEach(function (d, n2) {
550
+ var on = n2 === idx;
551
+ d.classList.toggle('is-active', on);
552
+ d.setAttribute('aria-selected', on ? 'true' : 'false');
553
+ });
554
+ slides.forEach(function (s, n2) { s.setAttribute('aria-hidden', n2 === idx ? 'false' : 'true'); });
555
+ if (prevBtn) prevBtn.disabled = idx === 0;
556
+ if (nextBtn) nextBtn.disabled = idx === slides.length - 1;
557
+ }
558
+ if (prevBtn) prevBtn.addEventListener('click', function () { go(idx - 1); });
559
+ if (nextBtn) nextBtn.addEventListener('click', function () { go(idx + 1); });
560
+ carousel.addEventListener('keydown', function (e) {
561
+ if (e.key === 'ArrowLeft') { e.preventDefault(); go(idx - 1); }
562
+ else if (e.key === 'ArrowRight') { e.preventDefault(); go(idx + 1); }
563
+ });
564
+ var x0 = null;
565
+ track.addEventListener('touchstart', function (e) { x0 = e.touches[0].clientX; }, { passive: true });
566
+ track.addEventListener('touchend', function (e) {
567
+ if (x0 === null) return;
568
+ var dx = e.changedTouches[0].clientX - x0;
569
+ if (Math.abs(dx) > 40) go(idx + (dx < 0 ? 1 : -1));
570
+ x0 = null;
469
571
  });
572
+ go(0);
470
573
  }
471
574
  })();
472
575
  </script>