PageSourceSearch

https://vibecoding-ch07.vercel.app/

html vibecoding-ch07.vercel.app collected 2026-10-03 07:59:25 UTC 12,502 bytes, 256 lines download raw bytes

1<!DOCTYPE html>
2<html lang="ko">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <meta name="description" content="AI가 당신의 감정을 분석하고 공감해주는 디지털 다이어리. 안전하고 따뜻한 감정 기록 서비스.">
7    <meta name="keywords" content="다이어리, 감정분석, AI, 공감, 일기, 감정기록">
8    <meta name="author" content="Empathy Diary App">
9    <meta name="theme-color" content="#d4a574">
10
11    <!-- Open Graph / Facebook -->
12    <meta property="og:type" content="website">
13    <meta property="og:title" content="공감 AI 다이어리">
14    <meta property="og:description" content="AI가 당신의 감정을 분석하고 공감해주는 디지털 다이어리">
15    <meta property="og:image" content="/favicon-192.png">
16
17    <!-- Twitter -->
18    <meta property="twitter:card" content="summary_large_image">
19    <meta property="twitter:title" content="공감 AI 다이어리">
20    <meta property="twitter:description" content="AI가 당신의 감정을 분석하고 공감해주는 디지털 다이어리">
21
22    <!-- Favicon -->
23    <link rel="icon" type="image/png" sizes="32x32" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📖</text></svg>">
24
25    <title>공감 AI 다이어리</title>
26
27    <!-- Preconnect for performance -->
28    <link rel="preconnect" href="https://fonts.googleapis.com">
29    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
30    <link rel="preconnect" href="https://openrouter.ai">
31
32    <!-- Fonts -->
33    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
34
35    <!-- Styles -->
36    <link rel="stylesheet" href="styles.css">
37</head>
38<body>
39    <div class="container">
40        <!-- Header Section -->
41        <header class="header">
42            <div class="header-top">
43                <div class="header-title-group">
44                    <h1 class="app-title">
45                        <span class="title-icon">📖</span>
46                        공감 AI 다이어리
47                    </h1>
48                    <p class="app-subtitle">당신의 마음을 따뜻하게 이해하는 일기장</p>
49                </div>
50                <button id="settingsBtn" class="btn-settings" aria-label="설정" title="API 키 설정">
51                    ⚙️
52                </button>
53            </div>
54        </header>
55
56        <!-- API Key Settings Modal -->
57        <div id="settingsModal" class="modal hidden" role="dialog" aria-labelledby="settings-title" aria-modal="true">
58            <div class="modal-content settings-modal">
59                <div class="modal-header">
60                    <h3 id="settings-title" class="modal-title">⚙️ API 키 설정</h3>
61                    <button id="closeSettingsBtn" class="btn-close" aria-label="닫기">✕</button>
62                </div>
63                <div class="modal-body">
64                    <div class="settings-info">
65                        <p>ℹ️ 이 앱은 서버에서 API를 관리하므로 별도의 API 키 설정이 필요하지 않습니다.</p>
66                        <p class="settings-help-secondary">
67                            💡 로컬 개발이나 자신의 API 키를 사용하려면 아래에 입력하세요.
68                        </p>
69                    </div>
70                    <div class="form-group">
71                        <label for="apiKeyInput" class="form-label">API 키</label>
72                        <input
73                            type="password"
74                            id="apiKeyInput"
75                            class="form-input"
76                            placeholder="sk-or-v1-..."
77                            aria-describedby="api-key-help"
78                        />
79                        <small id="api-key-help" class="form-help">
80                            API 키는 브라우저에만 저장되며 외부로 전송되지 않습니다.
81                        </small>
82                    </div>
83                    <div id="apiKeyStatus" class="api-status hidden"></div>
84                </div>
85                <div class="modal-actions">
86                    <button id="saveApiKeyBtn" class="btn btn-primary">
87                        <span class="btn-icon">💾</span>
88                        저장
89                    </button>
90                    <button id="cancelSettingsBtn" class="btn btn-secondary">
91                        취소
92                    </button>
93                </div>
94            </div>
95            <div class="modal-backdrop"></div>
96        </div>
97
98        <!-- Main Content -->
99        <main class="main-content">
100            <!-- Today's Date -->
101            <div class="date-section">
102                <div class="today-date" id="todayDate"></div>
103            </div>
104
105            <!-- Diary Input Section -->
106            <section class="diary-input-section">
107                <div class="input-container">
108                    <label for="diaryInput" class="input-label">
109                        <span class="label-icon">✍️</span>
110                        오늘 하루는 어떠셨나요?
111                    </label>
112                    <textarea
113                        id="diaryInput"
114                        class="diary-input"
115                        placeholder="마음 속 이야기를 자유롭게 적어보세요..."
116                        rows="3"
117                        aria-describedby="input-help"
118                        aria-label="일기 내용 입력"
119                    ></textarea>
120                    <div id="input-help" class="visually-hidden">
121                        Ctrl+Enter를 누르면 감정 분석을 시작합니다
122                    </div>
123                    <div class="input-actions">
124                        <button id="analyzeBtn" class="btn btn-primary" aria-describedby="analyze-help">
125                            <span class="btn-icon" aria-hidden="true">🔍</span>
126                            감정 분석하기
127                        </button>
128                        <div id="analyze-help" class="visually-hidden">
129                            일기 내용을 AI가 분석하여 감정을 파악하고 공감 메시지를 제공합니다
130                        </div>
131                    </div>
132                </div>
133            </section>
134
135            <!-- Analysis Loading -->
136            <div id="loadingSection" class="loading-section hidden" role="status" aria-live="polite">
137                <div class="loading-spinner" aria-hidden="true"></div>
138                <p class="loading-text">마음을 분석하는 중...</p>
139            </div>
140
141            <!-- Analysis Result Section -->
142            <section id="analysisResult" class="analysis-result hidden" role="region" aria-labelledby="result-title" aria-live="polite">
143                <div class="result-container">
144                    <h3 id="result-title" class="result-title">감정 분석 결과</h3>
145
146                    <div class="emotion-display">
147                        <div class="emotion-icon-container">
148                            <span id="emotionIcon" class="emotion-icon"></span>
149                        </div>
150                        <div class="emotion-info">
151                            <div id="emotionName" class="emotion-name"></div>
152                            <div class="emotion-intensity">
153                                <span class="intensity-label">감정 강도:</span>
154                                <div class="intensity-bar">
155                                    <div id="intensityFill" class="intensity-fill"></div>
156                                </div>
157                                <span id="intensityValue" class="intensity-value"></span>
158                            </div>
159                        </div>
160                    </div>
161
162                    <div class="empathy-message-container">
163                        <h4 class="empathy-title">
164                            <span class="empathy-icon">💙</span>
165                            공감 메시지
166                        </h4>
167                        <div id="empathyMessage" class="empathy-message"></div>
168                    </div>
169
170                    <div class="result-actions">
171                        <button id="saveBtn" class="btn btn-secondary" aria-describedby="save-help">
172                            <span class="btn-icon" aria-hidden="true">💾</span>
173                            일기 저장하기
174                        </button>
175                        <div id="save-help" class="visually-hidden">
176                            분석 결과와 함께 일기를 브라우저에 저장합니다
177                        </div>
178                    </div>
179                </div>
180            </section>
181        </main>
182
183        <!-- Diary List Section -->
184        <section class="diary-list-section">
185            <div class="list-header">
186                <h2 id="list-title" class="list-title">
187                    <span class="title-icon" aria-hidden="true">📚</span>
188                    지난 일기들
189                </h2>
190                <button id="toggleListBtn" class="btn btn-text" aria-expanded="false" aria-controls="diaryList">
191                    <span id="toggleIcon" aria-hidden="true">📖</span>
192                    <span id="toggleText">펼치기</span>
193                </button>
194            </div>
195
196            <div id="diaryList" class="diary-list hidden" role="region" aria-labelledby="list-title">
197                <div id="diaryListContent" class="diary-list-content">
198                    <!-- Diary entries will be inserted here -->
199                </div>
200                <div id="emptyState" class="empty-state">
201                    <span class="empty-icon">📝</span>
202                    <p class="empty-text">아직 저장된 일기가 없어요.<br>첫 번째 일기를 작성해보세요!</p>
203                </div>
204            </div>
205        </section>
206
207        <!-- Footer -->
208        <footer class="footer">
209            <p class="footer-text">당신의 모든 감정이 소중합니다 ✨</p>
210            <div style="margin-top: 20px; padding: 20px; background: rgba(255, 255, 255, 0.95); border-radius: 10px; border: 2px solid rgba(255, 255, 255, 0.3);">
211                <p style="margin: 0 0 12px 0; text-align: center; font-size: 0.9em; color: #333; line-height: 1.6;">
212                    💡 <strong>7장</strong>에서 만든 공감 AI 다이어리와<br>
213                    <strong>8장의 Vercel 배포편</strong>을 응용해 제작하였습니다.
214                </p>
215                <div style="text-align: center; margin-top: 15px;">
216                    <a href="https://github.com/taehojo/vibecoding" target="_blank" style="display: inline-block; padding: 10px 20px; background: #667eea; color: white; text-decoration: none; border-radius: 8px; font-weight: 600; transition: all 0.3s ease; box-shadow: 0 2px 8px rgba(0,0,0,0.2);">
217                        📚 GitHub 저장소로 돌아가기
218                    </a>
219                </div>
220            </div>
221        </footer>
222    </div>
223
224    <!-- Confirmation Modal -->
225    <div id="confirmModal" class="modal hidden" role="dialog" aria-labelledby="modal-title" aria-modal="true">
226        <div class="modal-content">
227            <div class="modal-header">
228                <h3 id="modal-title" class="modal-title">일기 삭제</h3>
229            </div>
230            <div class="modal-body">
231                <p>정말로 이 일기를 삭제하시겠어요?</p>
232                <p class="modal-warning">삭제된 일기는 복구할 수 없습니다.</p>
233            </div>
234            <div class="modal-actions">
235                <button id="confirmDeleteBtn" class="btn btn-danger" aria-describedby="modal-title">
236                    삭제
237                </button>
238                <button id="cancelDeleteBtn" class="btn btn-secondary" aria-describedby="modal-title">
239                    취소
240                </button>
241            </div>
242        </div>
243        <div class="modal-backdrop"></div>
244    </div>
245
246    <!-- Success Toast -->
247    <div id="successToast" class="toast hidden">
248        <span class="toast-icon">✅</span>
249        <span class="toast-message"></span>
250    </div>
251
252    <!-- Scripts -->
253    
253<script src="backend.js"></script>
253
254    
254<script src="app.js"></script>
254
255</body>
256</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.