openfree commited on
Commit
6689cf4
ยท
verified ยท
1 Parent(s): 2a1423f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +433 -189
index.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>HuggingFace & Replicate ํŠธ๋ Œ๋”ฉ/์‹ ๊ทœ URL ์ถ”์ถœ๊ธฐ</title>
7
  <style>
8
  * {
9
  box-sizing: border-box;
@@ -12,300 +12,544 @@
12
  }
13
 
14
  body {
15
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
16
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
  min-height: 100vh;
18
- display: flex;
19
- align-items: center;
20
- justify-content: center;
21
  padding: 20px;
22
  }
23
 
24
  .container {
25
- background: rgba(255, 255, 255, 0.95);
26
- border-radius: 20px;
27
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
28
- padding: 40px;
29
- max-width: 900px;
30
- width: 100%;
31
- backdrop-filter: blur(10px);
32
  }
33
 
34
  h1 {
35
  text-align: center;
36
  color: #333;
37
- margin-bottom: 10px;
38
- font-size: 2rem;
39
- background: linear-gradient(135deg, #667eea, #764ba2);
40
- -webkit-background-clip: text;
41
- -webkit-text-fill-color: transparent;
42
- background-clip: text;
43
  }
44
 
45
- .subtitle {
46
- text-align: center;
 
 
 
 
 
 
 
 
 
 
47
  color: #666;
48
- margin-bottom: 40px;
49
- font-size: 1.1rem;
 
 
 
50
  }
51
 
52
- .service-section {
53
- margin-bottom: 30px;
54
- background: #f8f9fa;
55
- padding: 25px;
56
- border-radius: 15px;
57
- border: 1px solid #e9ecef;
58
  }
59
 
60
- .service-title {
61
- font-size: 1.5rem;
62
- color: #333;
63
- margin-bottom: 20px;
 
 
 
 
 
 
 
 
 
 
64
  display: flex;
65
- align-items: center;
66
  gap: 10px;
 
 
67
  }
68
 
69
- .service-icon {
70
- width: 30px;
71
- height: 30px;
72
- display: inline-flex;
73
- align-items: center;
74
- justify-content: center;
 
 
 
75
  }
76
 
77
- .url-grid {
 
 
 
 
 
 
78
  display: grid;
79
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
80
- gap: 15px;
 
81
  }
82
 
83
- .url-card {
84
  background: white;
 
85
  padding: 20px;
86
- border-radius: 10px;
87
- border: 1px solid #e0e0e0;
88
  transition: all 0.3s ease;
89
  cursor: pointer;
90
  position: relative;
91
  overflow: hidden;
92
  }
93
 
94
- .url-card:hover {
95
- transform: translateY(-2px);
96
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
97
- border-color: #667eea;
98
  }
99
 
100
- .url-card::before {
101
  content: '';
102
  position: absolute;
103
  top: 0;
104
  left: 0;
105
  width: 100%;
106
- height: 3px;
107
  background: linear-gradient(90deg, #667eea, #764ba2);
108
- transform: translateX(-100%);
109
- transition: transform 0.3s ease;
110
  }
111
 
112
- .url-card:hover::before {
113
- transform: translateX(0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
115
 
116
- .url-type {
117
  font-weight: 600;
118
- color: #667eea;
119
- margin-bottom: 10px;
120
  font-size: 1.1rem;
 
 
 
121
  }
122
 
123
- .url-link {
124
  color: #666;
125
  font-size: 0.9rem;
126
- word-break: break-all;
127
- display: block;
128
- text-decoration: none;
129
  }
130
 
131
- .url-link:hover {
132
- color: #667eea;
 
 
 
 
133
  }
134
 
135
- .copy-btn {
136
- margin-top: 10px;
137
- padding: 8px 16px;
138
- background: linear-gradient(135deg, #667eea, #764ba2);
139
- color: white;
140
- border: none;
141
- border-radius: 5px;
142
- cursor: pointer;
143
- font-size: 0.85rem;
144
- transition: all 0.3s ease;
145
  }
146
 
147
- .copy-btn:hover {
148
- transform: scale(1.05);
149
- box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
 
150
  }
151
 
152
- .copy-btn.copied {
153
- background: #4caf50;
 
 
 
 
 
 
154
  }
155
 
156
- .date-info {
 
 
 
 
 
 
 
 
 
157
  text-align: center;
158
- color: #999;
159
- font-size: 0.9rem;
160
- margin-top: 30px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
 
163
  .note {
164
  background: #fef3c7;
165
  border: 1px solid #fbbf24;
166
- border-radius: 10px;
167
  padding: 15px;
168
- margin-top: 20px;
169
  color: #92400e;
170
- font-size: 0.9rem;
171
  }
172
 
173
  @media (max-width: 600px) {
174
- .container {
175
- padding: 20px;
176
  }
177
 
178
  h1 {
179
- font-size: 1.5rem;
180
- }
181
-
182
- .service-title {
183
- font-size: 1.2rem;
184
  }
185
  }
186
  </style>
187
  </head>
188
  <body>
189
  <div class="container">
190
- <h1>๐Ÿš€ AI ๋ชจ๋ธ ํ—ˆ๋ธŒ URL ์ถ”์ถœ๊ธฐ</h1>
191
- <p class="subtitle">HuggingFace์™€ Replicate์˜ ํŠธ๋ Œ๋”ฉ ๋ฐ ์‹ ๊ทœ ๋ชจ๋ธ/์ŠคํŽ˜์ด์Šค URL</p>
192
-
193
- <!-- HuggingFace Models -->
194
- <div class="service-section">
195
- <h2 class="service-title">
196
- <span class="service-icon">๐Ÿค—</span>
197
- HuggingFace Models
198
- </h2>
199
- <div class="url-grid">
200
- <div class="url-card" onclick="copyToClipboard(this, 'https://huggingface.co/models?sort=trending')">
201
- <div class="url-type">๐Ÿ“ˆ ํŠธ๋ Œ๋”ฉ ๋ชจ๋ธ</div>
202
- <a href="https://huggingface.co/models?sort=trending" target="_blank" class="url-link">
203
- https://huggingface.co/models?sort=trending
204
- </a>
205
- <button class="copy-btn">URL ๋ณต์‚ฌ</button>
206
- </div>
207
- <div class="url-card" onclick="copyToClipboard(this, 'https://huggingface.co/models?sort=created')">
208
- <div class="url-type">๐Ÿ†• ์‹ ๊ทœ ๋ชจ๋ธ</div>
209
- <a href="https://huggingface.co/models?sort=created" target="_blank" class="url-link">
210
- https://huggingface.co/models?sort=created
211
- </a>
212
- <button class="copy-btn">URL ๋ณต์‚ฌ</button>
 
213
  </div>
214
  </div>
215
  </div>
216
 
217
- <!-- HuggingFace Spaces -->
218
- <div class="service-section">
219
- <h2 class="service-title">
220
- <span class="service-icon">๐ŸŽฏ</span>
221
- HuggingFace Spaces
222
- </h2>
223
- <div class="url-grid">
224
- <div class="url-card" onclick="copyToClipboard(this, 'https://huggingface.co/spaces?sort=trending')">
225
- <div class="url-type">๐Ÿ“ˆ ํŠธ๋ Œ๋”ฉ ์ŠคํŽ˜์ด์Šค</div>
226
- <a href="https://huggingface.co/spaces?sort=trending" target="_blank" class="url-link">
227
- https://huggingface.co/spaces?sort=trending
228
- </a>
229
- <button class="copy-btn">URL ๋ณต์‚ฌ</button>
230
- </div>
231
- <div class="url-card" onclick="copyToClipboard(this, 'https://huggingface.co/spaces?sort=created')">
232
- <div class="url-type">๐Ÿ†• ์‹ ๊ทœ ์ŠคํŽ˜์ด์Šค</div>
233
- <a href="https://huggingface.co/spaces?sort=created" target="_blank" class="url-link">
234
- https://huggingface.co/spaces?sort=created
235
- </a>
236
- <button class="copy-btn">URL ๋ณต์‚ฌ</button>
237
  </div>
238
  </div>
239
  </div>
240
 
241
- <!-- Replicate -->
242
- <div class="service-section">
243
- <h2 class="service-title">
244
- <span class="service-icon">โšก</span>
245
- Replicate
246
- </h2>
247
- <div class="url-grid">
248
- <div class="url-card" onclick="copyToClipboard(this, 'https://replicate.com/explore')">
249
- <div class="url-type">๐Ÿ”ฅ ์ธ๊ธฐ ๋ชจ๋ธ (Explore)</div>
250
- <a href="https://replicate.com/explore" target="_blank" class="url-link">
251
- https://replicate.com/explore
252
- </a>
253
- <button class="copy-btn">URL ๋ณต์‚ฌ</button>
254
- </div>
255
- <div class="url-card" onclick="copyToClipboard(this, 'https://replicate.com/collections')">
256
- <div class="url-type">๐Ÿ“š ์ปฌ๋ ‰์…˜๋ณ„ ๋ชจ๋ธ</div>
257
- <a href="https://replicate.com/collections" target="_blank" class="url-link">
258
- https://replicate.com/collections
259
- </a>
260
- <button class="copy-btn">URL ๋ณต์‚ฌ</button>
261
  </div>
262
  </div>
263
  </div>
264
 
265
  <div class="note">
266
- ๐Ÿ’ก <strong>์ฐธ๊ณ :</strong> Replicate๋Š” ๋ณ„๋„์˜ "์‹ ๊ทœ" ์ •๋ ฌ ์˜ต์…˜์ด ์—†์œผ๋ฉฐ, Explore ํŽ˜์ด์ง€์—์„œ ์ตœ์‹  ๋ฐ ์ธ๊ธฐ ๋ชจ๋ธ์„ ํ•จ๊ป˜ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 
267
  </div>
268
-
269
- <p class="date-info">์ตœ์ข… ์—…๋ฐ์ดํŠธ: 2025๋…„ 6์›” 26์ผ</p>
270
  </div>
271
 
 
 
272
  <script>
273
- function copyToClipboard(card, url) {
274
- // ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง ๋ฐฉ์ง€
275
- event.preventDefault();
276
- event.stopPropagation();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
 
278
- // ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ
279
- navigator.clipboard.writeText(url).then(() => {
280
- const btn = card.querySelector('.copy-btn');
281
- const originalText = btn.textContent;
282
 
283
- // ๋ฒ„ํŠผ ํ…์ŠคํŠธ ๋ณ€๊ฒฝ
284
- btn.textContent = 'โœ“ ๋ณต์‚ฌ๋จ!';
285
- btn.classList.add('copied');
286
 
287
- // 2์ดˆ ํ›„ ์›๋ž˜ ์ƒํƒœ๋กœ ๋ณต์›
288
- setTimeout(() => {
289
- btn.textContent = originalText;
290
- btn.classList.remove('copied');
291
- }, 2000);
292
- }).catch(err => {
293
- console.error('๋ณต์‚ฌ ์‹คํŒจ:', err);
294
- alert('๋ณต์‚ฌ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ๋ณต์‚ฌํ•ด์ฃผ์„ธ์š”.');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  });
296
  }
297
 
298
- // URL ์นด๏ฟฝ๏ฟฝ ํด๋ฆญ ์‹œ ๋งํฌ ์—ด๊ธฐ (๋ณต์‚ฌ ๋ฒ„ํŠผ ์ œ์™ธ)
299
- document.querySelectorAll('.url-card').forEach(card => {
300
- card.addEventListener('click', (e) => {
301
- if (!e.target.classList.contains('copy-btn')) {
302
- const link = card.querySelector('.url-link');
303
- if (link) {
304
- window.open(link.href, '_blank');
305
- }
306
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  });
308
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  </script>
310
  </body>
311
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>HuggingFace & Replicate ์‹ค์‹œ๊ฐ„ ํŠธ๋ Œ๋”ฉ/์‹ ๊ทœ ๋ฆฌ์ŠคํŠธ</title>
7
  <style>
8
  * {
9
  box-sizing: border-box;
 
12
  }
13
 
14
  body {
15
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
16
+ background: #f5f5f5;
17
  min-height: 100vh;
 
 
 
18
  padding: 20px;
19
  }
20
 
21
  .container {
22
+ max-width: 1400px;
23
+ margin: 0 auto;
 
 
 
 
 
24
  }
25
 
26
  h1 {
27
  text-align: center;
28
  color: #333;
29
+ margin-bottom: 30px;
30
+ font-size: 2.5rem;
 
 
 
 
31
  }
32
 
33
+ .category-tabs {
34
+ display: flex;
35
+ gap: 10px;
36
+ margin-bottom: 20px;
37
+ flex-wrap: wrap;
38
+ justify-content: center;
39
+ }
40
+
41
+ .tab-button {
42
+ padding: 12px 24px;
43
+ border: none;
44
+ background: #fff;
45
  color: #666;
46
+ border-radius: 8px;
47
+ cursor: pointer;
48
+ font-size: 1rem;
49
+ transition: all 0.3s ease;
50
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
51
  }
52
 
53
+ .tab-button:hover {
54
+ transform: translateY(-2px);
55
+ box-shadow: 0 4px 10px rgba(0,0,0,0.15);
 
 
 
56
  }
57
 
58
+ .tab-button.active {
59
+ background: linear-gradient(135deg, #667eea, #764ba2);
60
+ color: white;
61
+ }
62
+
63
+ .content-section {
64
+ display: none;
65
+ }
66
+
67
+ .content-section.active {
68
+ display: block;
69
+ }
70
+
71
+ .filter-buttons {
72
  display: flex;
 
73
  gap: 10px;
74
+ margin-bottom: 20px;
75
+ justify-content: center;
76
  }
77
 
78
+ .filter-btn {
79
+ padding: 8px 16px;
80
+ border: 1px solid #ddd;
81
+ background: white;
82
+ color: #666;
83
+ border-radius: 20px;
84
+ cursor: pointer;
85
+ font-size: 0.9rem;
86
+ transition: all 0.3s ease;
87
  }
88
 
89
+ .filter-btn.active {
90
+ background: #667eea;
91
+ color: white;
92
+ border-color: #667eea;
93
+ }
94
+
95
+ .items-grid {
96
  display: grid;
97
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
98
+ gap: 20px;
99
+ margin-top: 20px;
100
  }
101
 
102
+ .item-card {
103
  background: white;
104
+ border-radius: 12px;
105
  padding: 20px;
106
+ box-shadow: 0 2px 10px rgba(0,0,0,0.08);
 
107
  transition: all 0.3s ease;
108
  cursor: pointer;
109
  position: relative;
110
  overflow: hidden;
111
  }
112
 
113
+ .item-card:hover {
114
+ transform: translateY(-5px);
115
+ box-shadow: 0 5px 20px rgba(0,0,0,0.15);
 
116
  }
117
 
118
+ .item-card::before {
119
  content: '';
120
  position: absolute;
121
  top: 0;
122
  left: 0;
123
  width: 100%;
124
+ height: 4px;
125
  background: linear-gradient(90deg, #667eea, #764ba2);
 
 
126
  }
127
 
128
+ .item-header {
129
+ display: flex;
130
+ align-items: start;
131
+ gap: 12px;
132
+ margin-bottom: 12px;
133
+ }
134
+
135
+ .item-icon {
136
+ width: 40px;
137
+ height: 40px;
138
+ background: #f0f0f0;
139
+ border-radius: 8px;
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ font-size: 1.5rem;
144
+ }
145
+
146
+ .item-info {
147
+ flex: 1;
148
  }
149
 
150
+ .item-title {
151
  font-weight: 600;
152
+ color: #333;
153
+ margin-bottom: 4px;
154
  font-size: 1.1rem;
155
+ overflow: hidden;
156
+ text-overflow: ellipsis;
157
+ white-space: nowrap;
158
  }
159
 
160
+ .item-author {
161
  color: #666;
162
  font-size: 0.9rem;
 
 
 
163
  }
164
 
165
+ .item-stats {
166
+ display: flex;
167
+ gap: 15px;
168
+ margin-top: 12px;
169
+ font-size: 0.85rem;
170
+ color: #666;
171
  }
172
 
173
+ .stat {
174
+ display: flex;
175
+ align-items: center;
176
+ gap: 5px;
 
 
 
 
 
 
177
  }
178
 
179
+ .loading {
180
+ text-align: center;
181
+ padding: 40px;
182
+ color: #666;
183
  }
184
 
185
+ .loading-spinner {
186
+ display: inline-block;
187
+ width: 40px;
188
+ height: 40px;
189
+ border: 4px solid #f3f3f3;
190
+ border-top: 4px solid #667eea;
191
+ border-radius: 50%;
192
+ animation: spin 1s linear infinite;
193
  }
194
 
195
+ @keyframes spin {
196
+ 0% { transform: rotate(0deg); }
197
+ 100% { transform: rotate(360deg); }
198
+ }
199
+
200
+ .error {
201
+ background: #fee;
202
+ color: #c33;
203
+ padding: 20px;
204
+ border-radius: 8px;
205
  text-align: center;
206
+ margin: 20px 0;
207
+ }
208
+
209
+ .refresh-btn {
210
+ position: fixed;
211
+ bottom: 30px;
212
+ right: 30px;
213
+ width: 60px;
214
+ height: 60px;
215
+ background: linear-gradient(135deg, #667eea, #764ba2);
216
+ color: white;
217
+ border: none;
218
+ border-radius: 50%;
219
+ cursor: pointer;
220
+ font-size: 1.5rem;
221
+ box-shadow: 0 4px 15px rgba(0,0,0,0.2);
222
+ transition: all 0.3s ease;
223
+ z-index: 100;
224
+ }
225
+
226
+ .refresh-btn:hover {
227
+ transform: scale(1.1);
228
+ box-shadow: 0 6px 20px rgba(0,0,0,0.3);
229
  }
230
 
231
  .note {
232
  background: #fef3c7;
233
  border: 1px solid #fbbf24;
234
+ border-radius: 8px;
235
  padding: 15px;
236
+ margin: 20px 0;
237
  color: #92400e;
238
+ text-align: center;
239
  }
240
 
241
  @media (max-width: 600px) {
242
+ .items-grid {
243
+ grid-template-columns: 1fr;
244
  }
245
 
246
  h1 {
247
+ font-size: 1.8rem;
 
 
 
 
248
  }
249
  }
250
  </style>
251
  </head>
252
  <body>
253
  <div class="container">
254
+ <h1>๐Ÿš€ AI ๋ชจ๋ธ & ์ŠคํŽ˜์ด์Šค ์‹ค์‹œ๊ฐ„ ํŠธ๋ Œ๋”ฉ</h1>
255
+
256
+ <div class="category-tabs">
257
+ <button class="tab-button active" onclick="showCategory('hf-models')">
258
+ ๐Ÿค— HF Models
259
+ </button>
260
+ <button class="tab-button" onclick="showCategory('hf-spaces')">
261
+ ๐ŸŽฏ HF Spaces
262
+ </button>
263
+ <button class="tab-button" onclick="showCategory('replicate')">
264
+ โšก Replicate
265
+ </button>
266
+ </div>
267
+
268
+ <!-- HuggingFace Models Section -->
269
+ <div id="hf-models" class="content-section active">
270
+ <div class="filter-buttons">
271
+ <button class="filter-btn active" onclick="loadHFModels('trending')">๐Ÿ“ˆ ํŠธ๋ Œ๋”ฉ</button>
272
+ <button class="filter-btn" onclick="loadHFModels('new')">๐Ÿ†• ์‹ ๊ทœ</button>
273
+ </div>
274
+ <div id="hf-models-content" class="items-grid">
275
+ <div class="loading">
276
+ <div class="loading-spinner"></div>
277
+ <p>๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘...</p>
278
  </div>
279
  </div>
280
  </div>
281
 
282
+ <!-- HuggingFace Spaces Section -->
283
+ <div id="hf-spaces" class="content-section">
284
+ <div class="filter-buttons">
285
+ <button class="filter-btn active" onclick="loadHFSpaces('trending')">๐Ÿ“ˆ ํŠธ๋ Œ๋”ฉ</button>
286
+ <button class="filter-btn" onclick="loadHFSpaces('new')">๐Ÿ†• ์‹ ๊ทœ</button>
287
+ </div>
288
+ <div id="hf-spaces-content" class="items-grid">
289
+ <div class="loading">
290
+ <div class="loading-spinner"></div>
291
+ <p>์ŠคํŽ˜์ด์Šค ๋กœ๋”ฉ ์ค‘...</p>
 
 
 
 
 
 
 
 
 
 
292
  </div>
293
  </div>
294
  </div>
295
 
296
+ <!-- Replicate Section -->
297
+ <div id="replicate" class="content-section">
298
+ <div class="filter-buttons">
299
+ <button class="filter-btn active" onclick="loadReplicate()">๐Ÿ”ฅ ์ธ๊ธฐ ๋ชจ๋ธ</button>
300
+ </div>
301
+ <div id="replicate-content" class="items-grid">
302
+ <div class="loading">
303
+ <div class="loading-spinner"></div>
304
+ <p>๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘...</p>
 
 
 
 
 
 
 
 
 
 
 
305
  </div>
306
  </div>
307
  </div>
308
 
309
  <div class="note">
310
+ โš ๏ธ CORS ์ •์ฑ…์œผ๋กœ ์ธํ•ด ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋กœ๋“œ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
311
+ ํ”„๋ก์‹œ ์„œ๋ฒ„๋‚˜ ๋ฐฑ์—”๋“œ API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
312
  </div>
 
 
313
  </div>
314
 
315
+ <button class="refresh-btn" onclick="refreshCurrent()">๐Ÿ”„</button>
316
+
317
  <script>
318
+ let currentCategory = 'hf-models';
319
+ let currentFilter = 'trending';
320
+
321
+ // ์นดํ…Œ๊ณ ๋ฆฌ ์ „ํ™˜
322
+ function showCategory(category) {
323
+ currentCategory = category;
324
+
325
+ // ํƒญ ํ™œ์„ฑํ™”
326
+ document.querySelectorAll('.tab-button').forEach(btn => {
327
+ btn.classList.remove('active');
328
+ });
329
+ event.target.classList.add('active');
330
+
331
+ // ์„น์…˜ ํ‘œ์‹œ
332
+ document.querySelectorAll('.content-section').forEach(section => {
333
+ section.classList.remove('active');
334
+ });
335
+ document.getElementById(category).classList.add('active');
336
+
337
+ // ๋ฐ์ดํ„ฐ ๋กœ๋“œ
338
+ if (category === 'hf-models') {
339
+ loadHFModels('trending');
340
+ } else if (category === 'hf-spaces') {
341
+ loadHFSpaces('trending');
342
+ } else if (category === 'replicate') {
343
+ loadReplicate();
344
+ }
345
+ }
346
+
347
+ // HuggingFace Models ๋กœ๋“œ
348
+ async function loadHFModels(filter) {
349
+ currentFilter = filter;
350
+
351
+ // ํ•„ํ„ฐ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”
352
+ document.querySelectorAll('#hf-models .filter-btn').forEach(btn => {
353
+ btn.classList.remove('active');
354
+ });
355
+ event.target.classList.add('active');
356
+
357
+ const container = document.getElementById('hf-models-content');
358
+ container.innerHTML = '<div class="loading"><div class="loading-spinner"></div><p>๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘...</p></div>';
359
 
360
+ try {
361
+ // HuggingFace API ์‚ฌ์šฉ
362
+ const sort = filter === 'trending' ? 'likes' : 'created';
363
+ const response = await fetch(`https://huggingface.co/api/models?sort=${sort}&limit=20`);
364
 
365
+ if (!response.ok) throw new Error('API ์š”์ฒญ ์‹คํŒจ');
 
 
366
 
367
+ const data = await response.json();
368
+ displayHFModels(data, container);
369
+ } catch (error) {
370
+ // CORS ์—๋Ÿฌ ์‹œ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ํ‘œ์‹œ
371
+ displaySampleHFModels(filter, container);
372
+ }
373
+ }
374
+
375
+ // HuggingFace Spaces ๋กœ๋“œ
376
+ async function loadHFSpaces(filter) {
377
+ currentFilter = filter;
378
+
379
+ // ํ•„ํ„ฐ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”
380
+ document.querySelectorAll('#hf-spaces .filter-btn').forEach(btn => {
381
+ btn.classList.remove('active');
382
+ });
383
+ event.target.classList.add('active');
384
+
385
+ const container = document.getElementById('hf-spaces-content');
386
+ container.innerHTML = '<div class="loading"><div class="loading-spinner"></div><p>์ŠคํŽ˜์ด์Šค ๋กœ๋”ฉ ์ค‘...</p></div>';
387
+
388
+ try {
389
+ // HuggingFace API ์‚ฌ์šฉ
390
+ const sort = filter === 'trending' ? 'likes' : 'created';
391
+ const response = await fetch(`https://huggingface.co/api/spaces?sort=${sort}&limit=20`);
392
+
393
+ if (!response.ok) throw new Error('API ์š”์ฒญ ๏ฟฝ๏ฟฝํŒจ');
394
+
395
+ const data = await response.json();
396
+ displayHFSpaces(data, container);
397
+ } catch (error) {
398
+ // CORS ์—๋Ÿฌ ์‹œ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ํ‘œ์‹œ
399
+ displaySampleHFSpaces(filter, container);
400
+ }
401
+ }
402
+
403
+ // Replicate ๋ชจ๋ธ ๋กœ๋“œ
404
+ async function loadReplicate() {
405
+ const container = document.getElementById('replicate-content');
406
+ container.innerHTML = '<div class="loading"><div class="loading-spinner"></div><p>๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘...</p></div>';
407
+
408
+ // Replicate๋Š” ๊ณต๊ฐœ API๊ฐ€ ์ œํ•œ์ ์ด๋ฏ€๋กœ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ํ‘œ์‹œ
409
+ displaySampleReplicateModels(container);
410
+ }
411
+
412
+ // HuggingFace Models ํ‘œ์‹œ
413
+ function displayHFModels(models, container) {
414
+ container.innerHTML = '';
415
+ models.forEach(model => {
416
+ const card = createModelCard({
417
+ title: model.modelId || model.id,
418
+ author: model.author || 'Unknown',
419
+ likes: model.likes || 0,
420
+ downloads: model.downloads || 0,
421
+ url: `https://huggingface.co/${model.modelId || model.id}`,
422
+ icon: '๐Ÿค–'
423
+ });
424
+ container.appendChild(card);
425
+ });
426
+ }
427
+
428
+ // HuggingFace Spaces ํ‘œ์‹œ
429
+ function displayHFSpaces(spaces, container) {
430
+ container.innerHTML = '';
431
+ spaces.forEach(space => {
432
+ const card = createModelCard({
433
+ title: space.id.split('/')[1] || space.id,
434
+ author: space.id.split('/')[0] || 'Unknown',
435
+ likes: space.likes || 0,
436
+ sdk: space.sdk || 'Unknown',
437
+ url: `https://huggingface.co/spaces/${space.id}`,
438
+ icon: '๐ŸŽฏ'
439
+ });
440
+ container.appendChild(card);
441
+ });
442
+ }
443
+
444
+ // ๋ชจ๋ธ ์นด๋“œ ์ƒ์„ฑ
445
+ function createModelCard(data) {
446
+ const card = document.createElement('div');
447
+ card.className = 'item-card';
448
+ card.onclick = () => window.open(data.url, '_blank');
449
+
450
+ card.innerHTML = `
451
+ <div class="item-header">
452
+ <div class="item-icon">${data.icon}</div>
453
+ <div class="item-info">
454
+ <div class="item-title">${data.title}</div>
455
+ <div class="item-author">by ${data.author}</div>
456
+ </div>
457
+ </div>
458
+ <div class="item-stats">
459
+ ${data.likes !== undefined ? `<div class="stat">โค๏ธ ${formatNumber(data.likes)}</div>` : ''}
460
+ ${data.downloads !== undefined ? `<div class="stat">โฌ‡๏ธ ${formatNumber(data.downloads)}</div>` : ''}
461
+ ${data.sdk ? `<div class="stat">๐Ÿ› ๏ธ ${data.sdk}</div>` : ''}
462
+ ${data.runs !== undefined ? `<div class="stat">โ–ถ๏ธ ${formatNumber(data.runs)}</div>` : ''}
463
+ </div>
464
+ `;
465
+
466
+ return card;
467
+ }
468
+
469
+ // ์ˆซ์ž ํฌ๋งท
470
+ function formatNumber(num) {
471
+ if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M';
472
+ if (num >= 1000) return (num / 1000).toFixed(1) + 'K';
473
+ return num.toString();
474
+ }
475
+
476
+ // ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ํ‘œ์‹œ ํ•จ์ˆ˜๋“ค
477
+ function displaySampleHFModels(filter, container) {
478
+ const sampleData = filter === 'trending' ? [
479
+ { title: 'meta-llama/Llama-3.3-70B', author: 'meta-llama', likes: 177000, downloads: 1150000, icon: '๐Ÿค–' },
480
+ { title: 'DeepSeek-R1', author: 'deepseek-ai', likes: 10400, downloads: 567000, icon: '๐Ÿค–' },
481
+ { title: 'Qwen/Qwen3-235B', author: 'Qwen', likes: 5370, downloads: 225000, icon: '๐Ÿค–' },
482
+ { title: 'FLUX.1-dev', author: 'black-forest-labs', likes: 29100, downloads: 397000, icon: '๐Ÿค–' },
483
+ { title: 'microsoft/Phi-4', author: 'microsoft', likes: 8900, downloads: 156000, icon: '๐Ÿค–' }
484
+ ] : [
485
+ { title: 'OmniGen2', author: 'research-lab', likes: 156, downloads: 890, icon: '๐Ÿค–' },
486
+ { title: 'VideoGen-Pro', author: 'ai-startup', likes: 89, downloads: 234, icon: '๐Ÿค–' },
487
+ { title: 'CodeLLM-7B', author: 'dev-team', likes: 234, downloads: 1200, icon: '๐Ÿค–' },
488
+ { title: 'MusicGen-V2', author: 'audio-ai', likes: 67, downloads: 456, icon: '๐Ÿค–' },
489
+ { title: 'ImageEdit-XL', author: 'vision-lab', likes: 145, downloads: 789, icon: '๐Ÿค–' }
490
+ ];
491
+
492
+ container.innerHTML = '';
493
+ sampleData.forEach(model => {
494
+ model.url = `https://huggingface.co/${model.author}/${model.title}`;
495
+ container.appendChild(createModelCard(model));
496
  });
497
  }
498
 
499
+ function displaySampleHFSpaces(filter, container) {
500
+ const sampleData = filter === 'trending' ? [
501
+ { title: 'stable-diffusion-webui', author: 'stabilityai', likes: 75500, sdk: 'Gradio', icon: '๐ŸŽฏ' },
502
+ { title: 'chatgpt-clone', author: 'community', likes: 12300, sdk: 'Streamlit', icon: '๐ŸŽฏ' },
503
+ { title: 'image-to-3d', author: 'research', likes: 8590, sdk: 'Gradio', icon: '๐ŸŽฏ' },
504
+ { title: 'voice-clone', author: 'audio-ml', likes: 5640, sdk: 'Gradio', icon: '๐ŸŽฏ' },
505
+ { title: 'code-generator', author: 'dev-tools', likes: 3210, sdk: 'Streamlit', icon: '๐ŸŽฏ' }
506
+ ] : [
507
+ { title: 'new-llm-demo', author: 'researcher', likes: 23, sdk: 'Gradio', icon: '๐ŸŽฏ' },
508
+ { title: 'video-editor', author: 'creator', likes: 45, sdk: 'Streamlit', icon: '๐ŸŽฏ' },
509
+ { title: 'data-viz', author: 'analyst', likes: 67, sdk: 'Streamlit', icon: '๐ŸŽฏ' },
510
+ { title: 'music-mixer', author: 'musician', likes: 34, sdk: 'Gradio', icon: '๐ŸŽฏ' },
511
+ { title: 'text-analyzer', author: 'nlp-dev', likes: 56, sdk: 'Gradio', icon: '๐ŸŽฏ' }
512
+ ];
513
+
514
+ container.innerHTML = '';
515
+ sampleData.forEach(space => {
516
+ space.url = `https://huggingface.co/spaces/${space.author}/${space.title}`;
517
+ container.appendChild(createModelCard(space));
518
+ });
519
+ }
520
+
521
+ function displaySampleReplicateModels(container) {
522
+ const sampleData = [
523
+ { title: 'FLUX1.1-pro', author: 'black-forest-labs', runs: 2910000, icon: 'โšก' },
524
+ { title: 'stable-diffusion-3', author: 'stability-ai', runs: 1750000, icon: 'โšก' },
525
+ { title: 'whisper', author: 'openai', runs: 890000, icon: 'โšก' },
526
+ { title: 'llama-2-70b', author: 'meta', runs: 670000, icon: 'โšก' },
527
+ { title: 'musicgen', author: 'facebook', runs: 450000, icon: 'โšก' },
528
+ { title: 'animate-diff', author: 'lucataco', runs: 320000, icon: 'โšก' },
529
+ { title: 'real-esrgan', author: 'xinntao', runs: 280000, icon: 'โšก' },
530
+ { title: 'rembg', author: 'cjwbw', runs: 210000, icon: 'โšก' }
531
+ ];
532
+
533
+ container.innerHTML = '';
534
+ sampleData.forEach(model => {
535
+ model.url = `https://replicate.com/${model.author}/${model.title}`;
536
+ container.appendChild(createModelCard(model));
537
  });
538
+ }
539
+
540
+ // ์ƒˆ๋กœ๊ณ ์นจ
541
+ function refreshCurrent() {
542
+ if (currentCategory === 'hf-models') {
543
+ loadHFModels(currentFilter);
544
+ } else if (currentCategory === 'hf-spaces') {
545
+ loadHFSpaces(currentFilter);
546
+ } else {
547
+ loadReplicate();
548
+ }
549
+ }
550
+
551
+ // ์ดˆ๊ธฐ ๋กœ๋“œ
552
+ loadHFModels('trending');
553
  </script>
554
  </body>
555
  </html>