@zshuangmu/agenthub 0.4.14 → 0.4.15

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 (3) hide show
  1. package/README.md +108 -108
  2. package/package.json +1 -1
  3. package/src/lib/html.js +401 -62
package/README.md CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  # 🤖 AgentHub
4
4
 
5
- **OpenClaw Agent 的打包、发布与分发平台**
5
+ **Packaging, Publishing & Distribution Platform for OpenClaw Agents**
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/@zshuangmu/agenthub.svg)](https://www.npmjs.com/package/@zshuangmu/agenthub)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
9
9
  [![Node: >=18](https://img.shields.io/badge/Node.js->=18-green.svg)](https://nodejs.org/)
10
10
  [![GitHub Stars](https://img.shields.io/github/stars/itshaungmu/AgentHub?style=social)](https://github.com/itshaungmu/AgentHub)
11
11
 
12
- **把你调教好的 OpenClaw Agent 变成可复用、可分发、可升级的标准资产**
12
+ **Turn your well-trained OpenClaw Agent into reusable, distributable, and upgradable standard assets**
13
13
 
14
- 🌐 **在线演示**: [https://agenthub.cyou](https://agenthub.cyou/)
14
+ 🌐 **Live Demo**: [https://agenthub.cyou](https://agenthub.cyou/)
15
15
 
16
16
  [English](README.md) | [中文](README_CN.md)
17
17
 
@@ -19,52 +19,52 @@
19
19
 
20
20
  ---
21
21
 
22
- ## 🎯 AgentHub 是什么?
22
+ ## 🎯 What is AgentHub?
23
23
 
24
- AgentHub 是一个专为 **OpenClaw** 设计的 Agent 打包与分发平台,类似于:
25
- - **Docker Hub** 之于 Docker 容器
26
- - **npm** 之于 Node.js
24
+ AgentHub is a packaging and distribution platform designed specifically for **OpenClaw**, similar to:
25
+ - **Docker Hub** for Docker containers
26
+ - **npm** for Node.js packages
27
27
 
28
- 但专注于 **OpenClaw Agent 的分发与复刻**。
28
+ But focused on **OpenClaw Agent distribution and replication**.
29
29
 
30
- ### 核心能力
30
+ ### Core Capabilities
31
31
 
32
- | 能力 | 描述 |
33
- |------|------|
34
- | 📦 **一键打包** | Agent personality、memoryskills 打包成标准 Bundle |
35
- | 🚀 **发布分发** | 发布到本地或远程 Registry,生成可分享链接 |
36
- | ⚡ **一键安装** | 团队成员通过统一命令安装,复刻完整 Agent 能力 |
37
- | 🔄 **版本管理** | 完整的升级、回滚、校验支持 |
32
+ | Capability | Description |
33
+ |------------|-------------|
34
+ | 📦 **One-Click Packaging** | Package Agent's personality, memory, and skills into a standard Bundle |
35
+ | 🚀 **Publish & Distribute** | Publish to local or remote Registry, generate shareable links |
36
+ | ⚡ **One-Click Install** | Team members install via unified command, replicate complete Agent capabilities |
37
+ | 🔄 **Version Management** | Full support for upgrades, rollbacks, and verification |
38
38
 
39
- ### 适合谁?
39
+ ### Who is it for?
40
40
 
41
- - **✅ OpenClaw 团队用户**: 统一分发、版本管理、团队复用
42
- - **✅ Agent 创作者**: 打包分享你调教好的 Agent
43
- - **✅ AI 重度用户**: 快速获得别人调教好的 Agent 能力
41
+ - **✅ OpenClaw Team Users**: Unified distribution, version management, team reuse
42
+ - **✅ Agent Creators**: Package and share your well-trained Agents
43
+ - **✅ AI Power Users**: Quickly acquire Agent capabilities trained by others
44
44
 
45
- ### 不适合谁?
45
+ ### Who is it NOT for?
46
46
 
47
- - ❌ OpenClaw 用户(当前仅支持 OpenClaw
48
- - ❌ 需要 Prompt 收藏夹(请使用专门的 Prompt 工具)
49
- - ❌ 单个 Skill 分发(请使用 ClawHub
47
+ - ❌ Non-OpenClaw users (currently only supports OpenClaw)
48
+ - ❌ Those needing a Prompt collection (please use dedicated Prompt tools)
49
+ - ❌ Single Skill distribution (please use ClawHub)
50
50
 
51
- ## 🎯 官方样板 Agent
51
+ ## 🎯 Official Sample Agents
52
52
 
53
- 我们提供了 3 个官方样板 Agent,帮助你快速上手:
53
+ We provide 3 official sample Agents to help you get started quickly:
54
54
 
55
- | Agent | 描述 | 适用场景 |
56
- |-------|------|----------|
57
- | **code-review-assistant** | 代码审查助手 | 代码质量审查、安全漏洞识别 |
58
- | **team-knowledge-assistant** | 团队知识问答 | 项目信息检索、新员工入职 |
59
- | **product-doc-writer** | 产品文档撰写 | 功能文档、用户指南、API 文档 |
55
+ | Agent | Description | Use Cases |
56
+ |-------|-------------|-----------|
57
+ | **code-review-assistant** | Code Review Assistant | Code quality review, security vulnerability identification |
58
+ | **team-knowledge-assistant** | Team Knowledge Q&A | Project information retrieval, new employee onboarding |
59
+ | **product-doc-writer** | Product Documentation Writer | Feature docs, user guides, API documentation |
60
60
 
61
- ### 快速试用
61
+ ### Quick Try
62
62
 
63
63
  ```bash
64
- # 打包任意样板 Agent
64
+ # Package any sample Agent
65
65
  agenthub pack --workspace ./samples/code-review-assistant --config ./samples/code-review-assistant/openclaw.json
66
66
 
67
- # 发布并安装
67
+ # Publish and install
68
68
  agenthub publish ./bundles/code-review-assistant-1.0.0.agent --registry ./.registry
69
69
  agenthub install code-review-assistant --registry ./.registry --target-workspace ./workspace
70
70
  ```
@@ -73,140 +73,140 @@ agenthub install code-review-assistant --registry ./.registry --target-workspace
73
73
 
74
74
  ![AgentHub Web Interface](./docs/image.png)
75
75
 
76
- ## 🚀 3 步上手
76
+ ## 🚀 3 Steps to Get Started
77
77
 
78
- ### 第一步:安装
78
+ ### Step 1: Installation
79
79
 
80
80
  ```bash
81
- # 通过 npm 全局安装
81
+ # Install globally via npm
82
82
  npm install -g @zshuangmu/agenthub
83
83
 
84
- # 或克隆源码
84
+ # Or clone from source
85
85
  git clone https://github.com/itshaungmu/AgentHub.git
86
86
  cd AgentHub && npm install && npm link
87
87
  ```
88
88
 
89
- ### 第二步:打包并发布你的 Agent
89
+ ### Step 2: Package and Publish Your Agent
90
90
 
91
91
  ```bash
92
- # 1. 打包你的 OpenClaw workspace
92
+ # 1. Package your OpenClaw workspace
93
93
  agenthub pack --workspace ./my-workspace --config openclaw.json
94
94
 
95
- # 或指定版本号
95
+ # Or specify a version number
96
96
  agenthub pack --workspace ./my-workspace --config openclaw.json --version 2.0.0
97
97
 
98
- # 2. 发布到 Registry
98
+ # 2. Publish to Registry
99
99
  agenthub publish ./bundles/my-agent.agent --registry ./.registry
100
100
  ```
101
101
 
102
- ### 第三步:团队成员安装使用
102
+ ### Step 3: Team Members Install and Use
103
103
 
104
104
  ```bash
105
- # 团队成员一键安装
105
+ # Team members install with one click
106
106
  agenthub install my-agent --registry ./.registry --target-workspace ./workspace
107
107
 
108
- # 或启动 Web 界面浏览
108
+ # Or start the Web interface to browse
109
109
  agenthub serve --registry ./.registry --port 3000
110
110
  ```
111
111
 
112
- 访问 http://localhost:3000 查看你的 Agent
112
+ Visit http://localhost:3000 to see your Agent!
113
113
 
114
- ### 🎯 试用样板 Agent
114
+ ### 🎯 Try Sample Agents
115
115
 
116
- 我们提供了一个官方样板 Agent,帮助你快速体验:
116
+ We provide an official sample Agent for quick experience:
117
117
 
118
118
  ```bash
119
- # 1. 克隆仓库
119
+ # 1. Clone the repository
120
120
  git clone https://github.com/itshaungmu/AgentHub.git
121
121
  cd AgentHub
122
122
 
123
- # 2. 打包样板 Agent
123
+ # 2. Package the sample Agent
124
124
  agenthub pack --workspace ./samples/code-review-assistant --config ./samples/code-review-assistant/openclaw.json
125
125
 
126
- # 3. 发布到本地 Registry
126
+ # 3. Publish to local Registry
127
127
  agenthub publish ./bundles/code-review-assistant-1.0.0.agent --registry ./.registry
128
128
 
129
- # 4. 安装到你的 workspace
129
+ # 4. Install to your workspace
130
130
  agenthub install code-review-assistant --registry ./.registry --target-workspace ./my-workspace
131
131
 
132
- # 5. 校验安装
132
+ # 5. Verify installation
133
133
  agenthub verify code-review-assistant --registry ./.registry --target-workspace ./my-workspace
134
134
  ```
135
135
 
136
136
  ---
137
137
 
138
- ## 📖 命令文档
139
-
140
- ### CLI 命令
141
-
142
- | 命令 | 描述 |
143
- |------|------|
144
- | `pack` | 打包 workspace Agent Bundle(支持 `--version` 指定版本) |
145
- | `publish` | 发布到本地 Registry |
146
- | `publish-remote` | 发布到远程服务器 |
147
- | `search` | 搜索 Registry 中的 Agent |
148
- | `info` | 查看 Agent 详情 |
149
- | `install` | 安装 Agent workspace |
150
- | `list` | 列出已安装的 Agent |
151
- | `uninstall` | 卸载已安装的 Agent |
152
- | `verify` | 校验已安装 Agent 是否完整 |
153
- | `versions` | 查看 Agent 版本历史 |
154
- | `update` | 更新 Agent 到最新版 |
155
- | `rollback` | 回滚 Agent 到指定版本 |
156
- | `stats` | 查看 Agent 统计信息 |
157
- | `doctor` | 诊断 AgentHub 安装和环境问题 |
158
- | `serve` | 启动 Web + API 服务 |
159
- | `api` | 仅启动 API 服务 |
160
- | `web` | 仅启动 Web 前端 |
138
+ ## 📖 Command Documentation
139
+
140
+ ### CLI Commands
141
+
142
+ | Command | Description |
143
+ |---------|-------------|
144
+ | `pack` | Package workspace as Agent Bundle (supports `--version` to specify version) |
145
+ | `publish` | Publish to local Registry |
146
+ | `publish-remote` | Publish to remote server |
147
+ | `search` | Search Agents in Registry |
148
+ | `info` | View Agent details |
149
+ | `install` | Install Agent to workspace |
150
+ | `list` | List installed Agents |
151
+ | `uninstall` | Uninstall an installed Agent |
152
+ | `verify` | Verify installed Agent integrity |
153
+ | `versions` | View Agent version history |
154
+ | `update` | Update Agent to latest version |
155
+ | `rollback` | Rollback Agent to specified version |
156
+ | `stats` | View Agent statistics |
157
+ | `doctor` | Diagnose AgentHub installation and environment issues |
158
+ | `serve` | Start Web + API services |
159
+ | `api` | Start API service only |
160
+ | `web` | Start Web frontend only |
161
161
 
162
162
  ### HTTP API
163
163
 
164
164
  ```bash
165
- # 健康检查
165
+ # Health check
166
166
  curl http://localhost:3001/api/health
167
167
 
168
- # 列出所有 Agent
168
+ # List all Agents
169
169
  curl http://localhost:3001/api/agents
170
170
 
171
- # 搜索 Agent
171
+ # Search Agents
172
172
  curl "http://localhost:3001/api/agents?q=react"
173
173
 
174
- # 获取 Agent 详情
174
+ # Get Agent details
175
175
  curl http://localhost:3001/api/agents/my-agent
176
176
 
177
- # 下载 Agent Bundle
177
+ # Download Agent Bundle
178
178
  curl http://localhost:3001/api/agents/my-agent/download
179
179
 
180
- # 获取统计信息
180
+ # Get statistics
181
181
  curl http://localhost:3001/api/stats
182
182
 
183
- # 获取下载排行
183
+ # Get download ranking
184
184
  curl "http://localhost:3001/api/stats/ranking?limit=10"
185
185
 
186
- # 发布 Agent (POST)
186
+ # Publish Agent (POST)
187
187
  curl -X POST http://localhost:3001/api/publish -H "Content-Type: application/json" -d '{"slug":"my-agent","version":"1.0.0"}'
188
188
 
189
- # 上传发布 Agent (POST)
189
+ # Upload and publish Agent (POST)
190
190
  curl -X POST http://localhost:3001/api/publish-upload -H "Content-Type: application/json" -d '{"bundleData":"..."}'
191
191
  ```
192
192
 
193
- ### AI 自动发现
193
+ ### AI Auto-Discovery
194
194
 
195
- 让你的 AI 助手自动发现可用的 Agent:
195
+ Let your AI assistant automatically discover available Agents:
196
196
 
197
197
  ```bash
198
198
  curl http://localhost:3001/api/skills/agenthub-discover
199
199
  ```
200
200
 
201
- ## 📚 教程文档
201
+ ## 📚 Tutorial Documentation
202
202
 
203
- | 教程 | 描述 |
204
- |------|------|
205
- | [3 步复刻 Agent](./docs/quick-start-3-steps.md) | 10 分钟快速上手指南 |
206
- | [团队分发指南](./docs/team-distribution-guide.md) | 如何把团队 Agent 标准化分发 |
207
- | [常见问题 FAQ](./docs/faq.md) | 常见问题解答 |
203
+ | Tutorial | Description |
204
+ |----------|-------------|
205
+ | [3 Steps to Replicate Agent](./docs/quick-start-3-steps.md) | 10-minute quick start guide |
206
+ | [Team Distribution Guide](./docs/team-distribution-guide.md) | How to standardize team Agent distribution |
207
+ | [FAQ](./docs/faq.md) | Frequently asked questions |
208
208
 
209
- ## 🏗️ 架构
209
+ ## 🏗️ Architecture
210
210
 
211
211
  ```
212
212
  ┌─────────────────┐ pack ┌─────────────────┐ publish ┌─────────────────┐
@@ -223,45 +223,45 @@ curl http://localhost:3001/api/skills/agenthub-discover
223
223
  └─────────────────┘
224
224
  ```
225
225
 
226
- ## 🧪 开发
226
+ ## 🧪 Development
227
227
 
228
228
  ```bash
229
- # 运行测试
229
+ # Run tests
230
230
  npm test
231
231
 
232
- # 启动开发服务器
232
+ # Start development server
233
233
  node src/cli.js serve --registry ./.registry
234
234
  ```
235
235
 
236
- ## 🐳 Docker 部署
236
+ ## 🐳 Docker Deployment
237
237
 
238
238
  ```bash
239
- # 生产环境启动(容器内)
239
+ # Production startup (inside container)
240
240
  NODE_ENV=production node src/cli.js serve --registry ./.registry --port 3000 --host 0.0.0.0
241
241
  ```
242
242
 
243
- ## 🤝 贡献
243
+ ## 🤝 Contributing
244
244
 
245
- 欢迎贡献!请查看 [CONTRIBUTING.md](CONTRIBUTING.md) 了解详情。
245
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
246
246
 
247
- - 🐛 [报告 Bug](https://github.com/itshaungmu/AgentHub/issues/new?template=bug_report.md)
248
- - 💡 [请求功能](https://github.com/itshaungmu/AgentHub/issues/new?template=feature_request.md)
249
- - 🔧 [提交 PR](https://github.com/itshaungmu/AgentHub/pulls)
247
+ - 🐛 [Report a Bug](https://github.com/itshaungmu/AgentHub/issues/new?template=bug_report.md)
248
+ - 💡 [Request a Feature](https://github.com/itshaungmu/AgentHub/issues/new?template=feature_request.md)
249
+ - 🔧 [Submit a PR](https://github.com/itshaungmu/AgentHub/pulls)
250
250
 
251
- ## 📄 许可证
251
+ ## 📄 License
252
252
 
253
253
  [MIT License](LICENSE) © AgentHub Team
254
254
 
255
- ## 🙏 致谢
255
+ ## 🙏 Acknowledgments
256
256
 
257
- - [OpenClaw](https://github.com/openclaw) 生态系统构建
258
- - 灵感来自 npm Docker Hub
257
+ - Built for the [OpenClaw](https://github.com/openclaw) ecosystem
258
+ - Inspired by npm and Docker Hub
259
259
 
260
260
  ---
261
261
 
262
262
  <div align="center">
263
263
 
264
- **[⬆ 返回顶部](#agenthub)**
264
+ **[⬆ Back to Top](#agenthub)**
265
265
 
266
266
  Made with ❤️ by the AgentHub Team
267
267
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zshuangmu/agenthub",
3
- "version": "0.4.14",
3
+ "version": "0.4.15",
4
4
  "description": "AI Agent 打包与分发平台 - 一句话打包上传,一键下载获得能力",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/lib/html.js CHANGED
@@ -183,19 +183,15 @@ const langScript = `
183
183
  el.placeholder = window.i18n[lang][key];
184
184
  }
185
185
  });
186
- // Update active button
187
186
  document.querySelectorAll('.lang-btn').forEach(btn => {
188
187
  btn.classList.toggle('active', btn.dataset.lang === lang);
189
188
  });
190
- // Update html lang attribute
191
189
  document.documentElement.lang = lang === 'zh' ? 'zh-CN' : 'en';
192
190
  }
193
191
 
194
- // Theme toggle function
195
192
  function setTheme(theme) {
196
193
  localStorage.setItem('agenthub-theme', theme);
197
194
  document.documentElement.setAttribute('data-theme', theme);
198
- // Update theme button icon
199
195
  const themeBtn = document.querySelector('.theme-btn');
200
196
  if (themeBtn) {
201
197
  themeBtn.textContent = theme === 'dark' ? '☀️' : '🌙';
@@ -214,15 +210,12 @@ const langScript = `
214
210
 
215
211
  document.addEventListener('DOMContentLoaded', () => {
216
212
  setLang(savedLang);
217
- // Initialize theme (default to light)
218
213
  const savedTheme = localStorage.getItem('agenthub-theme') || 'light';
219
214
  setTheme(savedTheme);
220
215
 
221
- // Copy to clipboard with fallback
216
+ // Copy to clipboard
222
217
  async function copyText(text) {
223
- if (navigator.clipboard?.writeText) {
224
- return navigator.clipboard.writeText(text);
225
- }
218
+ if (navigator.clipboard?.writeText) return navigator.clipboard.writeText(text);
226
219
  const ta = Object.assign(document.createElement('textarea'), { value: text, style: 'position:fixed;opacity:0' });
227
220
  document.body.appendChild(ta);
228
221
  ta.select();
@@ -230,12 +223,10 @@ const langScript = `
230
223
  ta.remove();
231
224
  }
232
225
 
233
- // Initialize copy buttons
234
226
  document.querySelectorAll('.api-code, .detail-install').forEach(el => {
235
227
  el.addEventListener('click', () => {
236
228
  const text = el.querySelector('.code-text')?.textContent.trim() || el.textContent.trim();
237
229
  const btn = el.querySelector('.copy-btn');
238
-
239
230
  copyText(text).then(() => {
240
231
  if (!btn) return;
241
232
  btn.textContent = '✓';
@@ -244,6 +235,89 @@ const langScript = `
244
235
  }).catch(e => console.error('Copy failed:', e));
245
236
  });
246
237
  });
238
+
239
+ // === Client-side search & filter ===
240
+ const searchInput = document.getElementById('agent-search');
241
+ const categoryTabs = document.querySelectorAll('.category-tab');
242
+ const agentCards = document.querySelectorAll('.agent-card');
243
+ const loadMoreBtn = document.getElementById('load-more-btn');
244
+ const noResults = document.querySelector('.no-results');
245
+ let visibleCount = 0;
246
+ const PAGE_SIZE = 12;
247
+ let currentCategory = 'all';
248
+ let searchTerm = '';
249
+
250
+ function getFilteredCards() {
251
+ return Array.from(agentCards).filter(card => {
252
+ const matchCategory = currentCategory === 'all' || card.dataset.category === currentCategory;
253
+ const matchSearch = !searchTerm || card.textContent.toLowerCase().includes(searchTerm.toLowerCase());
254
+ return matchCategory && matchSearch;
255
+ });
256
+ }
257
+
258
+ function updateDisplay() {
259
+ const filtered = getFilteredCards();
260
+ agentCards.forEach(c => c.classList.add('hidden'));
261
+ filtered.forEach(c => c.classList.remove('hidden'));
262
+
263
+ visibleCount = Math.min(PAGE_SIZE, filtered.length);
264
+ filtered.slice(0, visibleCount).forEach(c => c.classList.remove('hidden'));
265
+
266
+ if (loadMoreBtn) {
267
+ loadMoreBtn.style.display = visibleCount < filtered.length ? 'inline-block' : 'none';
268
+ }
269
+ if (noResults) {
270
+ noResults.classList.toggle('show', filtered.length === 0);
271
+ }
272
+ }
273
+
274
+ if (searchInput) {
275
+ searchInput.addEventListener('input', (e) => {
276
+ searchTerm = e.target.value;
277
+ updateDisplay();
278
+ });
279
+ // Prevent form submit for client-side search
280
+ const form = searchInput.closest('form');
281
+ if (form) {
282
+ form.addEventListener('submit', (e) => {
283
+ e.preventDefault();
284
+ searchTerm = searchInput.value;
285
+ updateDisplay();
286
+ });
287
+ }
288
+ }
289
+
290
+ categoryTabs.forEach(tab => {
291
+ tab.addEventListener('click', () => {
292
+ categoryTabs.forEach(t => t.classList.remove('active'));
293
+ tab.classList.add('active');
294
+ currentCategory = tab.dataset.category;
295
+ updateDisplay();
296
+ });
297
+ });
298
+
299
+ if (loadMoreBtn) {
300
+ loadMoreBtn.addEventListener('click', () => {
301
+ const filtered = getFilteredCards();
302
+ visibleCount = Math.min(visibleCount + PAGE_SIZE, filtered.length);
303
+ filtered.slice(0, visibleCount).forEach(c => c.classList.remove('hidden'));
304
+ loadMoreBtn.style.display = visibleCount < filtered.length ? 'inline-block' : 'none';
305
+ });
306
+ }
307
+
308
+ updateDisplay();
309
+
310
+ // === Scroll reveal animation ===
311
+ const revealObserver = new IntersectionObserver((entries) => {
312
+ entries.forEach(entry => {
313
+ if (entry.isIntersecting) {
314
+ entry.target.classList.add('visible');
315
+ revealObserver.unobserve(entry.target);
316
+ }
317
+ });
318
+ }, { threshold: 0.1, rootMargin: '0px 0px -40px 0px' });
319
+
320
+ document.querySelectorAll('.reveal').forEach(el => revealObserver.observe(el));
247
321
  });
248
322
  })();
249
323
  </script>
@@ -378,13 +452,51 @@ function page(title, body, options = {}) {
378
452
 
379
453
  /* Animations */
380
454
  @keyframes fadeInUp {
381
- from { opacity: 0; transform: translateY(16px); }
455
+ from { opacity: 0; transform: translateY(20px); }
382
456
  to { opacity: 1; transform: translateY(0); }
383
457
  }
384
458
  @keyframes fadeIn {
385
459
  from { opacity: 0; }
386
460
  to { opacity: 1; }
387
461
  }
462
+ @keyframes gradientShift {
463
+ 0%, 100% { background-position: 0% 50%; }
464
+ 50% { background-position: 100% 50%; }
465
+ }
466
+ @keyframes float {
467
+ 0%, 100% { transform: translateY(0px); }
468
+ 50% { transform: translateY(-8px); }
469
+ }
470
+ @keyframes pulse {
471
+ 0%, 100% { opacity: 0.6; }
472
+ 50% { opacity: 1; }
473
+ }
474
+ @keyframes countUp {
475
+ from { opacity: 0; transform: translateY(10px); }
476
+ to { opacity: 1; transform: translateY(0); }
477
+ }
478
+ @keyframes shimmer {
479
+ 0% { background-position: -200% 0; }
480
+ 100% { background-position: 200% 0; }
481
+ }
482
+ @keyframes slideInRight {
483
+ from { opacity: 0; transform: translateX(20px); }
484
+ to { opacity: 1; transform: translateX(0); }
485
+ }
486
+
487
+ /* Scroll reveal */
488
+ .reveal {
489
+ opacity: 0;
490
+ transform: translateY(24px);
491
+ transition: all 0.6s cubic-bezier(0.16, 1, 0.3, 1);
492
+ }
493
+ .reveal.visible {
494
+ opacity: 1;
495
+ transform: translateY(0);
496
+ }
497
+ .reveal-delay-1 { transition-delay: 0.1s; }
498
+ .reveal-delay-2 { transition-delay: 0.2s; }
499
+ .reveal-delay-3 { transition-delay: 0.3s; }
388
500
  a { color: inherit; text-decoration: none; }
389
501
  .container {
390
502
  max-width: 1200px;
@@ -540,50 +652,79 @@ function page(title, body, options = {}) {
540
652
  /* Hero - Sunset gradient style */
541
653
  .hero {
542
654
  text-align: center;
543
- padding: 72px 20px 56px;
655
+ padding: 80px 20px 64px;
544
656
  position: relative;
657
+ overflow: hidden;
545
658
  }
546
659
  .hero::before {
547
660
  content: '';
548
661
  position: absolute;
549
- top: -20px;
662
+ top: -40px;
550
663
  left: 50%;
551
664
  transform: translateX(-50%);
552
- width: 800px;
553
- height: 500px;
554
- background: radial-gradient(ellipse at center, rgba(250, 112, 154, 0.08) 0%, rgba(254, 225, 64, 0.05) 40%, transparent 70%);
665
+ width: 900px;
666
+ height: 600px;
667
+ background: radial-gradient(ellipse at center, rgba(250, 112, 154, 0.1) 0%, rgba(254, 225, 64, 0.06) 30%, rgba(255, 183, 77, 0.04) 50%, transparent 70%);
668
+ pointer-events: none;
669
+ z-index: -1;
670
+ animation: pulse 6s ease-in-out infinite;
671
+ }
672
+ .hero::after {
673
+ content: '';
674
+ position: absolute;
675
+ top: 50%;
676
+ left: 50%;
677
+ transform: translate(-50%, -50%);
678
+ width: 600px;
679
+ height: 600px;
680
+ background: conic-gradient(from 0deg, transparent, rgba(250, 112, 154, 0.04), transparent, rgba(254, 152, 0, 0.04), transparent);
681
+ border-radius: 50%;
682
+ animation: spin 20s linear infinite;
555
683
  pointer-events: none;
556
684
  z-index: -1;
557
685
  }
686
+ @keyframes spin { to { transform: translate(-50%, -50%) rotate(360deg); } }
558
687
  .hero h1 {
559
688
  font-family: var(--font-display);
560
- font-size: clamp(40px, 8vw, 64px);
689
+ font-size: clamp(42px, 8vw, 72px);
561
690
  font-weight: 700;
562
- margin-bottom: 16px;
563
- letter-spacing: -0.03em;
564
- background: linear-gradient(135deg, var(--color-1) 0%, var(--color-3) 50%, var(--color-2) 100%);
691
+ margin-bottom: 20px;
692
+ letter-spacing: -0.04em;
693
+ background: linear-gradient(135deg, var(--color-1) 0%, var(--color-3) 40%, var(--color-2) 70%, var(--color-1) 100%);
694
+ background-size: 200% auto;
565
695
  -webkit-background-clip: text;
566
696
  -webkit-text-fill-color: transparent;
567
697
  background-clip: text;
568
- animation: fadeInUp 0.6s ease-out;
698
+ animation: fadeInUp 0.6s ease-out, gradientShift 6s ease infinite;
569
699
  }
570
700
  .hero-subtitle {
571
- font-size: 17px;
701
+ font-size: 18px;
572
702
  color: var(--text-secondary);
573
- max-width: 560px;
574
- margin: 0 auto 44px;
575
- line-height: 1.75;
703
+ max-width: 600px;
704
+ margin: 0 auto 48px;
705
+ line-height: 1.8;
576
706
  animation: fadeInUp 0.6s ease-out 0.1s backwards;
577
707
  }
578
708
  .hero-stats {
579
709
  display: flex;
580
710
  justify-content: center;
581
- gap: 56px;
582
- margin-bottom: 44px;
711
+ gap: 48px;
712
+ margin-bottom: 48px;
583
713
  animation: fadeInUp 0.6s ease-out 0.2s backwards;
584
714
  }
585
715
  .hero-stat {
586
716
  text-align: center;
717
+ padding: 16px 24px;
718
+ background: var(--bg-card);
719
+ border: 1px solid var(--border);
720
+ border-radius: 16px;
721
+ transition: all 0.3s ease;
722
+ min-width: 140px;
723
+ }
724
+ .hero-stat:hover {
725
+ border-color: var(--color-1);
726
+ transform: translateY(-2px);
727
+ box-shadow: 0 8px 24px rgba(250, 112, 154, 0.1);
587
728
  }
588
729
  .hero-stat-value {
589
730
  font-family: var(--font-display);
@@ -601,23 +742,23 @@ function page(title, body, options = {}) {
601
742
  text-transform: uppercase;
602
743
  letter-spacing: 0.1em;
603
744
  font-weight: 600;
604
- margin-top: 4px;
745
+ margin-top: 6px;
605
746
  }
606
747
 
607
748
  /* Features - Warm coral accents */
608
749
  .features {
609
750
  display: grid;
610
751
  grid-template-columns: repeat(3, 1fr);
611
- gap: 16px;
752
+ gap: 18px;
612
753
  margin-bottom: 56px;
613
754
  }
614
755
  .feature-card {
615
756
  background: var(--bg-card);
616
757
  border: 1px solid var(--border);
617
758
  border-radius: 16px;
618
- padding: 28px 24px;
759
+ padding: 32px 24px;
619
760
  text-align: center;
620
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
761
+ transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
621
762
  position: relative;
622
763
  overflow: hidden;
623
764
  }
@@ -632,31 +773,45 @@ function page(title, body, options = {}) {
632
773
  opacity: 0;
633
774
  transition: opacity 0.3s;
634
775
  }
776
+ .feature-card::after {
777
+ content: '';
778
+ position: absolute;
779
+ inset: 0;
780
+ background: linear-gradient(135deg, rgba(250, 112, 154, 0.03), transparent);
781
+ opacity: 0;
782
+ transition: opacity 0.3s;
783
+ }
635
784
  .feature-card:hover {
636
785
  border-color: var(--color-1);
637
- transform: translateY(-4px);
638
- box-shadow: 0 12px 32px rgba(250, 112, 154, 0.12);
786
+ transform: translateY(-6px);
787
+ box-shadow: 0 16px 40px rgba(250, 112, 154, 0.12);
639
788
  }
640
789
  .feature-card:hover::before {
641
790
  opacity: 1;
642
791
  }
792
+ .feature-card:hover::after {
793
+ opacity: 1;
794
+ }
643
795
  .feature-icon {
644
- font-size: 32px;
645
- margin-bottom: 14px;
796
+ font-size: 36px;
797
+ margin-bottom: 16px;
646
798
  display: block;
799
+ animation: float 3s ease-in-out infinite;
647
800
  }
801
+ .feature-card:nth-child(2) .feature-icon { animation-delay: 0.5s; }
802
+ .feature-card:nth-child(3) .feature-icon { animation-delay: 1s; }
648
803
  .feature-title {
649
804
  font-family: var(--font-display);
650
- font-size: 14px;
805
+ font-size: 15px;
651
806
  font-weight: 600;
652
- margin-bottom: 8px;
807
+ margin-bottom: 10px;
653
808
  letter-spacing: -0.01em;
654
809
  color: var(--text-primary);
655
810
  }
656
811
  .feature-desc {
657
812
  font-size: 13px;
658
813
  color: var(--text-secondary);
659
- line-height: 1.6;
814
+ line-height: 1.7;
660
815
  }
661
816
 
662
817
  /* Section - Coral themed */
@@ -694,16 +849,30 @@ function page(title, body, options = {}) {
694
849
  display: grid;
695
850
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
696
851
  gap: 18px;
852
+ transition: all 0.3s ease;
697
853
  }
698
854
  .agent-card {
699
855
  background: var(--bg-card);
700
856
  border: 1px solid var(--border);
701
857
  border-radius: 16px;
702
- padding: 22px;
703
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
858
+ padding: 24px;
859
+ transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
704
860
  cursor: pointer;
705
861
  animation: fadeInUp 0.5s ease-out backwards;
706
862
  position: relative;
863
+ overflow: hidden;
864
+ }
865
+ .agent-card::after {
866
+ content: '';
867
+ position: absolute;
868
+ bottom: 0;
869
+ left: 0;
870
+ right: 0;
871
+ height: 3px;
872
+ background: linear-gradient(90deg, var(--color-1), var(--color-3), var(--color-2));
873
+ transform: scaleX(0);
874
+ transition: transform 0.3s ease;
875
+ transform-origin: left;
707
876
  }
708
877
  .agent-card:nth-child(1) { animation-delay: 0.05s; }
709
878
  .agent-card:nth-child(2) { animation-delay: 0.1s; }
@@ -716,8 +885,11 @@ function page(title, body, options = {}) {
716
885
  .agent-card:hover {
717
886
  background: var(--bg-card-hover);
718
887
  border-color: var(--color-1);
719
- transform: translateY(-4px);
720
- box-shadow: 0 16px 40px rgba(250, 112, 154, 0.15);
888
+ transform: translateY(-6px);
889
+ box-shadow: 0 20px 48px rgba(250, 112, 154, 0.15);
890
+ }
891
+ .agent-card:hover::after {
892
+ transform: scaleX(1);
721
893
  }
722
894
  .agent-card-featured {
723
895
  border-color: var(--color-1);
@@ -1197,26 +1369,45 @@ function page(title, body, options = {}) {
1197
1369
  .how-it-works {
1198
1370
  display: grid;
1199
1371
  grid-template-columns: repeat(3, 1fr);
1200
- gap: 24px;
1372
+ gap: 32px;
1201
1373
  margin-bottom: 56px;
1374
+ position: relative;
1375
+ }
1376
+ .how-it-works::before {
1377
+ content: '';
1378
+ position: absolute;
1379
+ top: 36px;
1380
+ left: 16%;
1381
+ right: 16%;
1382
+ height: 2px;
1383
+ background: linear-gradient(90deg, var(--color-1), var(--color-3), var(--color-2));
1384
+ opacity: 0.2;
1385
+ z-index: 0;
1202
1386
  }
1203
1387
  .step {
1204
1388
  text-align: center;
1389
+ position: relative;
1390
+ z-index: 1;
1205
1391
  }
1206
1392
  .step-number {
1207
- width: 48px;
1208
- height: 48px;
1393
+ width: 52px;
1394
+ height: 52px;
1209
1395
  background: linear-gradient(135deg, var(--color-1) 0%, var(--color-3) 100%);
1210
1396
  color: #ffffff;
1211
- border-radius: 14px;
1397
+ border-radius: 16px;
1212
1398
  display: flex;
1213
1399
  align-items: center;
1214
1400
  justify-content: center;
1215
1401
  font-family: var(--font-display);
1216
- font-size: 18px;
1402
+ font-size: 20px;
1217
1403
  font-weight: 700;
1218
- margin: 0 auto 16px;
1404
+ margin: 0 auto 18px;
1219
1405
  box-shadow: 0 8px 24px rgba(250, 112, 154, 0.25);
1406
+ transition: all 0.3s ease;
1407
+ }
1408
+ .step:hover .step-number {
1409
+ transform: scale(1.1) rotate(5deg);
1410
+ box-shadow: 0 12px 32px rgba(250, 112, 154, 0.35);
1220
1411
  }
1221
1412
  .step h4 {
1222
1413
  font-family: var(--font-display);
@@ -1230,6 +1421,98 @@ function page(title, body, options = {}) {
1230
1421
  line-height: 1.6;
1231
1422
  }
1232
1423
 
1424
+ /* Category filter tabs */
1425
+ .category-filters {
1426
+ display: flex;
1427
+ flex-wrap: wrap;
1428
+ gap: 8px;
1429
+ margin-bottom: 20px;
1430
+ justify-content: center;
1431
+ }
1432
+ .category-tab {
1433
+ padding: 8px 18px;
1434
+ border-radius: 24px;
1435
+ border: 1px solid var(--border);
1436
+ background: var(--bg-card);
1437
+ color: var(--text-secondary);
1438
+ font-size: 13px;
1439
+ font-weight: 500;
1440
+ font-family: var(--font-display);
1441
+ cursor: pointer;
1442
+ transition: all 0.25s ease;
1443
+ }
1444
+ .category-tab:hover {
1445
+ border-color: var(--color-1);
1446
+ color: var(--color-1);
1447
+ background: var(--accent-glow);
1448
+ }
1449
+ .category-tab.active {
1450
+ background: linear-gradient(135deg, var(--color-1), var(--color-3));
1451
+ color: white;
1452
+ border-color: transparent;
1453
+ box-shadow: 0 4px 12px rgba(250, 112, 154, 0.25);
1454
+ }
1455
+ .category-tab .count {
1456
+ display: inline-block;
1457
+ background: rgba(255,255,255,0.2);
1458
+ padding: 1px 7px;
1459
+ border-radius: 10px;
1460
+ font-size: 11px;
1461
+ margin-left: 4px;
1462
+ }
1463
+ .category-tab.active .count {
1464
+ background: rgba(255,255,255,0.3);
1465
+ }
1466
+ .category-tab:not(.active) .count {
1467
+ background: var(--bg-secondary);
1468
+ }
1469
+
1470
+ /* Load more */
1471
+ .load-more-wrap {
1472
+ text-align: center;
1473
+ margin-top: 28px;
1474
+ }
1475
+ .load-more-btn {
1476
+ padding: 12px 36px;
1477
+ border-radius: 12px;
1478
+ border: 2px solid var(--border);
1479
+ background: var(--bg-card);
1480
+ color: var(--text-secondary);
1481
+ font-size: 14px;
1482
+ font-weight: 600;
1483
+ font-family: var(--font-display);
1484
+ cursor: pointer;
1485
+ transition: all 0.3s ease;
1486
+ }
1487
+ .load-more-btn:hover {
1488
+ border-color: var(--color-1);
1489
+ color: var(--color-1);
1490
+ transform: translateY(-2px);
1491
+ box-shadow: 0 8px 24px rgba(250, 112, 154, 0.12);
1492
+ }
1493
+ .load-more-btn:active {
1494
+ transform: translateY(0);
1495
+ }
1496
+ .agent-card.hidden {
1497
+ display: none;
1498
+ }
1499
+
1500
+ /* No results */
1501
+ .no-results {
1502
+ text-align: center;
1503
+ padding: 48px 20px;
1504
+ color: var(--text-muted);
1505
+ display: none;
1506
+ }
1507
+ .no-results.show {
1508
+ display: block;
1509
+ }
1510
+ .no-results-icon {
1511
+ font-size: 48px;
1512
+ margin-bottom: 12px;
1513
+ opacity: 0.5;
1514
+ }
1515
+
1233
1516
  /* Search - Coral themed */
1234
1517
  .search-box {
1235
1518
  display: flex;
@@ -1304,9 +1587,21 @@ function page(title, body, options = {}) {
1304
1587
  /* Footer - Coral themed */
1305
1588
  footer {
1306
1589
  border-top: 1px solid var(--border);
1307
- padding: 36px 0;
1308
- margin-top: 64px;
1590
+ padding: 48px 0;
1591
+ margin-top: 80px;
1309
1592
  background: var(--bg-secondary);
1593
+ position: relative;
1594
+ }
1595
+ footer::before {
1596
+ content: '';
1597
+ position: absolute;
1598
+ top: 0;
1599
+ left: 0;
1600
+ right: 0;
1601
+ height: 3px;
1602
+ background: linear-gradient(90deg, var(--color-1), var(--color-3), var(--color-2), var(--color-1));
1603
+ background-size: 200% auto;
1604
+ animation: gradientShift 4s linear infinite;
1310
1605
  }
1311
1606
  .footer-content {
1312
1607
  display: flex;
@@ -1321,12 +1616,14 @@ function page(title, body, options = {}) {
1321
1616
  gap: 12px;
1322
1617
  }
1323
1618
  .footer-brand-icon {
1324
- width: 32px;
1325
- height: 32px;
1619
+ width: 36px;
1620
+ height: 36px;
1326
1621
  display: flex;
1327
1622
  align-items: center;
1328
1623
  justify-content: center;
1329
- font-size: 22px;
1624
+ font-size: 24px;
1625
+ background: var(--accent-glow);
1626
+ border-radius: 10px;
1330
1627
  }
1331
1628
  .footer-brand-text {
1332
1629
  font-family: var(--font-display);
@@ -1344,6 +1641,10 @@ function page(title, body, options = {}) {
1344
1641
  .footer-powered a {
1345
1642
  color: var(--color-1);
1346
1643
  font-weight: 600;
1644
+ transition: color 0.2s;
1645
+ }
1646
+ .footer-powered a:hover {
1647
+ color: var(--color-3);
1347
1648
  }
1348
1649
  .footer-links {
1349
1650
  display: flex;
@@ -1354,7 +1655,7 @@ function page(title, body, options = {}) {
1354
1655
  font-size: 13px;
1355
1656
  font-family: var(--font-display);
1356
1657
  font-weight: 500;
1357
- transition: color 0.2s;
1658
+ transition: all 0.2s;
1358
1659
  }
1359
1660
  .footer-links a:hover {
1360
1661
  color: var(--color-1);
@@ -1364,10 +1665,12 @@ function page(title, body, options = {}) {
1364
1665
  .hero { padding: 48px 16px 40px; }
1365
1666
  .hero h1 { font-size: clamp(32px, 7vw, 44px); }
1366
1667
  .hero-subtitle { font-size: 15px; padding: 0 12px; }
1367
- .hero-stats { gap: 32px; flex-wrap: wrap; }
1368
- .hero-stat-value { font-size: 30px; }
1668
+ .hero-stats { gap: 16px; flex-wrap: wrap; }
1669
+ .hero-stat { min-width: 100px; padding: 12px 16px; }
1670
+ .hero-stat-value { font-size: 28px; }
1369
1671
  .features { grid-template-columns: 1fr; gap: 14px; }
1370
1672
  .how-it-works { grid-template-columns: 1fr; gap: 24px; }
1673
+ .how-it-works::before { display: none; }
1371
1674
  .detail-grid { grid-template-columns: repeat(2, 1fr); }
1372
1675
  .agent-grid { grid-template-columns: 1fr; }
1373
1676
  .footer-content { flex-direction: column; text-align: center; gap: 20px; }
@@ -1396,12 +1699,16 @@ function page(title, body, options = {}) {
1396
1699
  .stats-table th, .stats-table td { padding: 12px 10px; font-size: 13px; }
1397
1700
  .step-number { width: 42px; height: 42px; font-size: 16px; }
1398
1701
  .step h4 { font-size: 14px; }
1702
+ .category-filters { gap: 6px; }
1703
+ .category-tab { padding: 6px 14px; font-size: 12px; }
1399
1704
  }
1400
1705
 
1401
1706
  @media (max-width: 480px) {
1402
1707
  .theme-btn { width: 32px; height: 32px; font-size: 14px; }
1403
- .hero-stat-value { font-size: 26px; }
1708
+ .hero-stat-value { font-size: 24px; }
1404
1709
  .hero-stat-label { font-size: 10px; }
1710
+ .hero-stats { gap: 10px; }
1711
+ .hero-stat { min-width: 80px; padding: 10px 12px; }
1405
1712
  .nav-links { gap: 12px; }
1406
1713
  .nav-links a { font-size: 12px; }
1407
1714
  .section-title { font-size: 18px; }
@@ -1465,6 +1772,13 @@ ${langScript}`;
1465
1772
  export function renderAgentListPage({ query, agents, totalDownloads, apiBase }) {
1466
1773
  const agentCount = agents.length;
1467
1774
 
1775
+ // Count agents per category
1776
+ const categoryCounts = {};
1777
+ agents.forEach(a => {
1778
+ const cat = a.metadata?.category || 'default';
1779
+ categoryCounts[cat] = (categoryCounts[cat] || 0) + 1;
1780
+ });
1781
+
1468
1782
  const features = `
1469
1783
  <div class="features">
1470
1784
  <div class="feature-card">
@@ -1498,7 +1812,7 @@ export function renderAgentListPage({ query, agents, totalDownloads, apiBase })
1498
1812
  }[category] || 'tag-default';
1499
1813
 
1500
1814
  return `
1501
- <article class="agent-card${featured ? ' agent-card-featured' : ''}" onclick="window.location='/agents/${agent.slug}'">
1815
+ <article class="agent-card hidden" data-category="${category}" onclick="window.location='/agents/${agent.slug}'">
1502
1816
  ${featured ? '<span class="featured-badge">⭐</span>' : ''}
1503
1817
  <div class="agent-header">
1504
1818
  <a href="/agents/${agent.slug}" class="agent-name" onclick="event.stopPropagation()">${agent.name || agent.slug}</a>
@@ -1519,8 +1833,24 @@ export function renderAgentListPage({ query, agents, totalDownloads, apiBase })
1519
1833
  `;
1520
1834
  }).join('');
1521
1835
 
1836
+ // Category filter tabs
1837
+ const categoryFilters = `
1838
+ <div class="category-filters">
1839
+ <button class="category-tab active" data-category="all">All<span class="count">${agentCount}</span></button>
1840
+ ${Object.entries(categoryCounts).sort((a, b) => b[1] - a[1]).map(([cat, count]) => {
1841
+ const tagClass = {
1842
+ 'ops': 'tag-ops',
1843
+ 'engineering': 'tag-engineering',
1844
+ 'content': 'tag-content',
1845
+ 'product': 'tag-product'
1846
+ }[cat] || 'tag-default';
1847
+ return `<button class="category-tab" data-category="${cat}">${cat}<span class="count">${count}</span></button>`;
1848
+ }).join('')}
1849
+ </div>
1850
+ `;
1851
+
1522
1852
  const howItWorks = `
1523
- <div class="section">
1853
+ <div class="section reveal">
1524
1854
  <h2 class="section-title" style="text-align: center; margin-bottom: 32px;" data-i18n="howToUse">How to Use</h2>
1525
1855
  <div class="how-it-works">
1526
1856
  <div class="step">
@@ -1543,7 +1873,7 @@ export function renderAgentListPage({ query, agents, totalDownloads, apiBase })
1543
1873
  `;
1544
1874
 
1545
1875
  const apiBox = `
1546
- <div class="api-box">
1876
+ <div class="api-box reveal">
1547
1877
  <h3 data-i18n="apiBoxTitle">🤖 AI Auto-Discovery API</h3>
1548
1878
  <p data-i18n="apiBoxDesc">Let your AI assistant automatically discover and install Agents</p>
1549
1879
  <div class="api-code" title="Click to copy">
@@ -1584,12 +1914,21 @@ export function renderAgentListPage({ query, agents, totalDownloads, apiBase })
1584
1914
  <a href="/stats" class="section-link" data-i18n="sectionViewAll">View All →</a>
1585
1915
  </div>
1586
1916
  <form class="search-box" method="get" action="/">
1587
- <input type="search" name="q" value="${query ?? ""}" data-i18n-placeholder="searchPlaceholder" placeholder="Search Agents, skills, tags..." />
1917
+ <input id="agent-search" type="search" name="q" value="${query ?? ""}" data-i18n-placeholder="searchPlaceholder" placeholder="Search Agents, skills, tags..." />
1588
1918
  <button type="submit" data-i18n="searchButton">Search</button>
1589
1919
  </form>
1920
+ ${categoryFilters}
1921
+ <div class="no-results">
1922
+ <div class="no-results-icon">🔍</div>
1923
+ <h3>No matching agents found</h3>
1924
+ <p>Try adjusting your search or filter</p>
1925
+ </div>
1590
1926
  <div class="agent-grid">
1591
1927
  ${cards || `<div class="empty-state"><h3 data-i18n="noAgents">No Agents yet</h3><p data-i18n="noAgentsHint">Use <code>agenthub pack</code> to package your first Agent!</p></div>`}
1592
1928
  </div>
1929
+ <div class="load-more-wrap">
1930
+ <button id="load-more-btn" class="load-more-btn">Load More Agents</button>
1931
+ </div>
1593
1932
  </section>
1594
1933
 
1595
1934
  ${howItWorks}