claude-code-templates 1.27.0 → 1.28.1
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.
- package/bin/create-claude-config.js +1 -0
- package/package.json +1 -1
- package/src/index.js +71 -11
- package/src/skill-dashboard-web/index.html +326 -0
- package/src/skill-dashboard-web/script.js +445 -0
- package/src/skill-dashboard-web/styles.css +3469 -0
- package/src/skill-dashboard.js +441 -0
|
@@ -59,6 +59,7 @@ program
|
|
|
59
59
|
.option('--agents', 'launch Claude Code agents dashboard (opens directly to conversations)')
|
|
60
60
|
.option('--chats-mobile', 'launch mobile-first chats interface (AI-optimized for mobile devices)')
|
|
61
61
|
.option('--plugins', 'launch Plugin Dashboard to view marketplaces, installed plugins, and permissions')
|
|
62
|
+
.option('--skills-manager', 'launch Skills Dashboard to view and explore installed Claude Code Skills')
|
|
62
63
|
.option('--tunnel', 'enable Cloudflare Tunnel for remote access (use with --analytics or --chats)')
|
|
63
64
|
.option('--verbose', 'enable verbose logging for debugging and development')
|
|
64
65
|
.option('--health-check, --health, --check, --verify', 'run comprehensive health check to verify Claude Code setup')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-templates",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.1",
|
|
4
4
|
"description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/index.js
CHANGED
|
@@ -16,11 +16,48 @@ const { runAnalytics } = require('./analytics');
|
|
|
16
16
|
const { startChatsMobile } = require('./chats-mobile');
|
|
17
17
|
const { runHealthCheck } = require('./health-check');
|
|
18
18
|
const { runPluginDashboard } = require('./plugin-dashboard');
|
|
19
|
+
const { runSkillDashboard } = require('./skill-dashboard');
|
|
19
20
|
const { trackingService } = require('./tracking-service');
|
|
20
21
|
const { createGlobalAgent, listGlobalAgents, removeGlobalAgent, updateGlobalAgent } = require('./sdk/global-agent-manager');
|
|
21
22
|
const SessionSharing = require('./session-sharing');
|
|
22
23
|
const ConversationAnalyzer = require('./analytics/core/ConversationAnalyzer');
|
|
23
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Get platform-appropriate Python command candidates
|
|
27
|
+
* Returns array of commands to try in order
|
|
28
|
+
* @returns {string[]} Array of Python commands to try
|
|
29
|
+
*/
|
|
30
|
+
function getPlatformPythonCandidates() {
|
|
31
|
+
if (process.platform === 'win32') {
|
|
32
|
+
// Windows: Try py launcher (PEP 397) first, then python, then python3
|
|
33
|
+
return ['py', 'python', 'python3'];
|
|
34
|
+
} else {
|
|
35
|
+
// Unix/Linux/Mac: Try python3 first, then python
|
|
36
|
+
return ['python3', 'python'];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Replace python3 commands with platform-appropriate Python command in configuration
|
|
42
|
+
* Windows typically uses 'python' or 'py', while Unix/Linux uses 'python3'
|
|
43
|
+
* @param {Object} config - Configuration object to process
|
|
44
|
+
* @returns {Object} Processed configuration with platform-appropriate Python commands
|
|
45
|
+
*/
|
|
46
|
+
function replacePythonCommands(config) {
|
|
47
|
+
if (!config || typeof config !== 'object') {
|
|
48
|
+
return config;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// On Windows, replace python3 with python for better compatibility
|
|
52
|
+
if (process.platform === 'win32') {
|
|
53
|
+
const configString = JSON.stringify(config);
|
|
54
|
+
const replacedString = configString.replace(/python3\s/g, 'python ');
|
|
55
|
+
return JSON.parse(replacedString);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return config;
|
|
59
|
+
}
|
|
60
|
+
|
|
24
61
|
async function showMainMenu() {
|
|
25
62
|
console.log('');
|
|
26
63
|
|
|
@@ -213,6 +250,14 @@ async function createClaudeConfig(options = {}) {
|
|
|
213
250
|
return;
|
|
214
251
|
}
|
|
215
252
|
|
|
253
|
+
// Handle skills dashboard
|
|
254
|
+
if (options.skillsManager) {
|
|
255
|
+
trackingService.trackCommandExecution('skills-manager');
|
|
256
|
+
trackingService.trackAnalyticsDashboard({ page: 'skills-manager', source: 'command_line' });
|
|
257
|
+
await runSkillDashboard(options);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
216
261
|
// Handle chats dashboard (now points to mobile chats interface)
|
|
217
262
|
if (options.chats) {
|
|
218
263
|
trackingService.trackCommandExecution('chats', { tunnel: options.tunnel || false });
|
|
@@ -692,7 +737,10 @@ async function installIndividualSetting(settingName, targetDir, options) {
|
|
|
692
737
|
}
|
|
693
738
|
|
|
694
739
|
const settingConfigText = await response.text();
|
|
695
|
-
|
|
740
|
+
let settingConfig = JSON.parse(settingConfigText);
|
|
741
|
+
|
|
742
|
+
// Replace python3 with platform-appropriate command for Windows compatibility
|
|
743
|
+
settingConfig = replacePythonCommands(settingConfig);
|
|
696
744
|
|
|
697
745
|
// Check if there are additional files to download (e.g., Python scripts)
|
|
698
746
|
const additionalFiles = {};
|
|
@@ -1021,7 +1069,10 @@ async function installIndividualHook(hookName, targetDir, options) {
|
|
|
1021
1069
|
}
|
|
1022
1070
|
|
|
1023
1071
|
const hookConfigText = await response.text();
|
|
1024
|
-
|
|
1072
|
+
let hookConfig = JSON.parse(hookConfigText);
|
|
1073
|
+
|
|
1074
|
+
// Replace python3 with platform-appropriate command for Windows compatibility
|
|
1075
|
+
hookConfig = replacePythonCommands(hookConfig);
|
|
1025
1076
|
|
|
1026
1077
|
// Check if there are additional files to download (e.g., Python scripts for hooks)
|
|
1027
1078
|
const additionalFiles = {};
|
|
@@ -3158,21 +3209,30 @@ async function executeE2BSandbox(options, targetDir) {
|
|
|
3158
3209
|
check.on('error', () => resolve(false));
|
|
3159
3210
|
});
|
|
3160
3211
|
};
|
|
3161
|
-
|
|
3162
|
-
//
|
|
3163
|
-
let pythonCmd =
|
|
3212
|
+
|
|
3213
|
+
// Try to find Python 3.11 first (recommended for E2B)
|
|
3214
|
+
let pythonCmd = null;
|
|
3164
3215
|
const python311Available = await checkPythonVersion('python3.11');
|
|
3165
3216
|
if (python311Available) {
|
|
3166
3217
|
pythonCmd = 'python3.11';
|
|
3167
3218
|
console.log(chalk.blue('✓ Using Python 3.11 (recommended for E2B)'));
|
|
3168
3219
|
} else {
|
|
3169
|
-
|
|
3220
|
+
// Fall back to platform-appropriate Python commands
|
|
3221
|
+
console.log(chalk.yellow('⚠ Python 3.11 not found, trying platform defaults...'));
|
|
3222
|
+
const candidates = getPlatformPythonCandidates();
|
|
3223
|
+
|
|
3224
|
+
for (const candidate of candidates) {
|
|
3225
|
+
if (await checkPythonVersion(candidate)) {
|
|
3226
|
+
pythonCmd = candidate;
|
|
3227
|
+
console.log(chalk.blue(`✓ Using ${candidate} for E2B`));
|
|
3228
|
+
break;
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3170
3231
|
}
|
|
3171
|
-
|
|
3172
|
-
// Verify
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
pythonSpinner.fail('Python 3 not found');
|
|
3232
|
+
|
|
3233
|
+
// Verify we found a working Python installation
|
|
3234
|
+
if (!pythonCmd) {
|
|
3235
|
+
pythonSpinner.fail('Python not found');
|
|
3176
3236
|
console.log(chalk.red('❌ Python 3.11+ is required for E2B sandbox'));
|
|
3177
3237
|
console.log(chalk.yellow('💡 Please install Python 3.11+ and try again'));
|
|
3178
3238
|
console.log(chalk.blue(' Visit: https://python.org/downloads'));
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Claude Code Skills Dashboard</title>
|
|
7
|
+
<link rel="stylesheet" href="styles.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div class="app-container">
|
|
11
|
+
<!-- Sidebar Navigation -->
|
|
12
|
+
<aside class="sidebar" id="sidebar">
|
|
13
|
+
<div class="sidebar-header">
|
|
14
|
+
<div class="sidebar-logo">
|
|
15
|
+
<span class="logo-icon">🎯</span>
|
|
16
|
+
<span class="logo-text">Skills Manager</span>
|
|
17
|
+
</div>
|
|
18
|
+
<button class="sidebar-toggle" id="sidebarToggle" aria-label="Toggle sidebar">
|
|
19
|
+
<span class="toggle-icon">☰</span>
|
|
20
|
+
</button>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="sidebar-stats">
|
|
24
|
+
<div class="sidebar-stat">
|
|
25
|
+
<span class="stat-number" id="sidebarTotalSkills">-</span>
|
|
26
|
+
<span class="stat-text">Total Skills</span>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="sidebar-stat">
|
|
29
|
+
<span class="stat-number" id="sidebarPersonalSkills">-</span>
|
|
30
|
+
<span class="stat-text">Personal</span>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="sidebar-section">
|
|
35
|
+
<div class="sidebar-section-header">
|
|
36
|
+
<span class="section-title">Filter by Source</span>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="source-filters">
|
|
39
|
+
<button class="source-filter-btn active" data-filter="all">
|
|
40
|
+
All Sources
|
|
41
|
+
</button>
|
|
42
|
+
<button class="source-filter-btn" data-filter="personal">
|
|
43
|
+
Personal
|
|
44
|
+
</button>
|
|
45
|
+
<button class="source-filter-btn" data-filter="project">
|
|
46
|
+
Project
|
|
47
|
+
</button>
|
|
48
|
+
<button class="source-filter-btn" data-filter="plugin">
|
|
49
|
+
Plugin
|
|
50
|
+
</button>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="sidebar-footer">
|
|
55
|
+
<a href="https://docs.claude.com/en/docs/agents-and-tools/agent-skills" target="_blank" class="sidebar-link">
|
|
56
|
+
<span class="link-icon">📚</span>
|
|
57
|
+
<span class="link-text">Skills Documentation</span>
|
|
58
|
+
</a>
|
|
59
|
+
<a href="https://aitmpl.com/skills" target="_blank" class="sidebar-link">
|
|
60
|
+
<span class="link-icon">🔍</span>
|
|
61
|
+
<span class="link-text">Browse Skills</span>
|
|
62
|
+
</a>
|
|
63
|
+
</div>
|
|
64
|
+
</aside>
|
|
65
|
+
|
|
66
|
+
<!-- Main Content Area -->
|
|
67
|
+
<main class="main-content">
|
|
68
|
+
<!-- Top Bar -->
|
|
69
|
+
<header class="top-bar">
|
|
70
|
+
<div class="top-bar-left">
|
|
71
|
+
<h1 class="page-title">
|
|
72
|
+
<span class="title-icon">🧠</span>
|
|
73
|
+
<span id="currentViewName">All Skills</span>
|
|
74
|
+
</h1>
|
|
75
|
+
<div class="breadcrumb" id="breadcrumb"></div>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="top-bar-right">
|
|
78
|
+
<div class="search-box">
|
|
79
|
+
<span class="search-icon">🔍</span>
|
|
80
|
+
<input
|
|
81
|
+
type="text"
|
|
82
|
+
id="skillSearch"
|
|
83
|
+
placeholder="Search skills..."
|
|
84
|
+
class="search-input"
|
|
85
|
+
>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="view-controls">
|
|
88
|
+
<button class="refresh-btn" id="refreshBtn" title="Refresh data">
|
|
89
|
+
<span class="refresh-icon">🔄</span>
|
|
90
|
+
</button>
|
|
91
|
+
<button class="view-btn active" data-view="grid" title="Grid view">
|
|
92
|
+
<span class="view-icon">▦</span>
|
|
93
|
+
</button>
|
|
94
|
+
<button class="view-btn" data-view="list" title="List view">
|
|
95
|
+
<span class="view-icon">☰</span>
|
|
96
|
+
</button>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</header>
|
|
100
|
+
|
|
101
|
+
<!-- Filters Bar -->
|
|
102
|
+
<div class="filters-bar">
|
|
103
|
+
<div class="filter-group">
|
|
104
|
+
<button class="filter-chip active" data-filter="all">
|
|
105
|
+
All Skills
|
|
106
|
+
<span class="chip-badge" id="countAll">0</span>
|
|
107
|
+
</button>
|
|
108
|
+
<button class="filter-chip" data-filter="personal">
|
|
109
|
+
<span class="status-dot personal"></span>
|
|
110
|
+
Personal
|
|
111
|
+
<span class="chip-badge" id="countPersonal">0</span>
|
|
112
|
+
</button>
|
|
113
|
+
<button class="filter-chip" data-filter="project">
|
|
114
|
+
<span class="status-dot project"></span>
|
|
115
|
+
Project
|
|
116
|
+
<span class="chip-badge" id="countProject">0</span>
|
|
117
|
+
</button>
|
|
118
|
+
<button class="filter-chip" data-filter="plugin">
|
|
119
|
+
<span class="status-dot plugin"></span>
|
|
120
|
+
Plugin
|
|
121
|
+
<span class="chip-badge" id="countPlugin">0</span>
|
|
122
|
+
</button>
|
|
123
|
+
</div>
|
|
124
|
+
<div class="sort-controls">
|
|
125
|
+
<label for="sortSelect" class="sort-label">Sort by:</label>
|
|
126
|
+
<select id="sortSelect" class="sort-select">
|
|
127
|
+
<option value="name">Name</option>
|
|
128
|
+
<option value="files">File Count</option>
|
|
129
|
+
<option value="modified">Last Modified</option>
|
|
130
|
+
</select>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<!-- Skills Grid/List -->
|
|
135
|
+
<div class="skills-container" id="skillsContainer">
|
|
136
|
+
<div class="content-loading">
|
|
137
|
+
<div class="spinner-large"></div>
|
|
138
|
+
<p class="loading-text">Loading skills...</p>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<!-- Empty State -->
|
|
143
|
+
<div class="empty-state-container" id="emptyState" style="display: none;">
|
|
144
|
+
<div class="empty-state">
|
|
145
|
+
<div class="empty-icon">🎯</div>
|
|
146
|
+
<h2 class="empty-title">No skills found</h2>
|
|
147
|
+
<p class="empty-description" id="emptyDescription">
|
|
148
|
+
Try adjusting your filters or search terms
|
|
149
|
+
</p>
|
|
150
|
+
<button class="btn-primary" id="clearFiltersBtn" style="display: none;">
|
|
151
|
+
Clear Filters
|
|
152
|
+
</button>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
</main>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<!-- Skill Detail Modal -->
|
|
159
|
+
<div class="modal-overlay" id="skillModal">
|
|
160
|
+
<div class="modal-container skill-modal">
|
|
161
|
+
<div class="modal-header">
|
|
162
|
+
<div class="modal-title-section">
|
|
163
|
+
<h2 class="modal-title" id="modalSkillName">Skill Name</h2>
|
|
164
|
+
<div class="modal-badges">
|
|
165
|
+
<span class="source-badge" id="modalSourceBadge">Personal</span>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
<button class="modal-close" id="closeModal" aria-label="Close modal">
|
|
169
|
+
✕
|
|
170
|
+
</button>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<div class="modal-body">
|
|
174
|
+
<!-- Skills Loading Levels -->
|
|
175
|
+
<div class="skill-levels-section">
|
|
176
|
+
<h3 class="section-title">
|
|
177
|
+
<span class="section-icon">📊</span>
|
|
178
|
+
Progressive Context Loading
|
|
179
|
+
</h3>
|
|
180
|
+
<p class="section-description">
|
|
181
|
+
Skills load content in three levels, minimizing context usage while maximizing flexibility
|
|
182
|
+
</p>
|
|
183
|
+
|
|
184
|
+
<div class="loading-levels">
|
|
185
|
+
<!-- Level 1: Metadata -->
|
|
186
|
+
<div class="level-card level-1" data-level="1">
|
|
187
|
+
<div class="level-header">
|
|
188
|
+
<div class="level-number">1</div>
|
|
189
|
+
<div class="level-info">
|
|
190
|
+
<div class="level-title">METADATA</div>
|
|
191
|
+
<div class="level-timing">Always loaded (at startup)</div>
|
|
192
|
+
</div>
|
|
193
|
+
<div class="level-cost">~100 tokens</div>
|
|
194
|
+
</div>
|
|
195
|
+
<div class="level-content">
|
|
196
|
+
<div class="level-description">
|
|
197
|
+
Name and description from YAML frontmatter for Skill discovery
|
|
198
|
+
</div>
|
|
199
|
+
<div class="metadata-display">
|
|
200
|
+
<div class="metadata-field">
|
|
201
|
+
<span class="field-label">name:</span>
|
|
202
|
+
<span class="field-value" id="metadataName">-</span>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="metadata-field">
|
|
205
|
+
<span class="field-label">description:</span>
|
|
206
|
+
<span class="field-value" id="metadataDescription">-</span>
|
|
207
|
+
</div>
|
|
208
|
+
<div class="metadata-field" id="metadataToolsField" style="display: none;">
|
|
209
|
+
<span class="field-label">allowed-tools:</span>
|
|
210
|
+
<div class="field-value-chips" id="metadataTools"></div>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<!-- Flow Arrow -->
|
|
217
|
+
<div class="level-arrow">
|
|
218
|
+
<div class="arrow-connector"></div>
|
|
219
|
+
<div class="arrow-label">When Skill triggers on relevant context</div>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
<!-- Level 2: Instructions -->
|
|
223
|
+
<div class="level-card level-2" data-level="2">
|
|
224
|
+
<div class="level-header">
|
|
225
|
+
<div class="level-number">2</div>
|
|
226
|
+
<div class="level-info">
|
|
227
|
+
<div class="level-title">INSTRUCTIONS</div>
|
|
228
|
+
<div class="level-timing">When Skill is triggered</div>
|
|
229
|
+
</div>
|
|
230
|
+
<div class="level-cost"><5k tokens</div>
|
|
231
|
+
</div>
|
|
232
|
+
<div class="level-content">
|
|
233
|
+
<div class="level-description">
|
|
234
|
+
SKILL.md body with procedural knowledge, workflows, and guidance
|
|
235
|
+
</div>
|
|
236
|
+
<div class="instructions-display">
|
|
237
|
+
<div class="file-item">
|
|
238
|
+
<span class="file-icon">📄</span>
|
|
239
|
+
<span class="file-name">SKILL.md</span>
|
|
240
|
+
<span class="file-meta" id="level2FileSize">-</span>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<!-- Flow Arrow -->
|
|
247
|
+
<div class="level-arrow">
|
|
248
|
+
<div class="arrow-connector"></div>
|
|
249
|
+
<div class="arrow-label">As files are referenced or executed</div>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
<!-- Level 3+: Resources -->
|
|
253
|
+
<div class="level-card level-3" data-level="3">
|
|
254
|
+
<div class="level-header">
|
|
255
|
+
<div class="level-number">3+</div>
|
|
256
|
+
<div class="level-info">
|
|
257
|
+
<div class="level-title">RESOURCES & CODE</div>
|
|
258
|
+
<div class="level-timing">Loaded as needed</div>
|
|
259
|
+
</div>
|
|
260
|
+
<div class="level-cost">Effectively unlimited</div>
|
|
261
|
+
</div>
|
|
262
|
+
<div class="level-content">
|
|
263
|
+
<div class="level-description">
|
|
264
|
+
Additional markdown files, executable scripts, and reference materials
|
|
265
|
+
</div>
|
|
266
|
+
<div class="resources-display" id="resourcesDisplay">
|
|
267
|
+
<div class="resource-category" id="instructionsCategory" style="display: none;">
|
|
268
|
+
<div class="category-header">
|
|
269
|
+
<span class="category-icon">📝</span>
|
|
270
|
+
<span class="category-name">Instructions</span>
|
|
271
|
+
<span class="category-count" id="instructionsCount">0</span>
|
|
272
|
+
</div>
|
|
273
|
+
<div class="category-description">Additional markdown files with specialized guidance and workflows</div>
|
|
274
|
+
<div class="category-files" id="instructionsFiles"></div>
|
|
275
|
+
</div>
|
|
276
|
+
<div class="resource-category" id="codeCategory" style="display: none;">
|
|
277
|
+
<div class="category-header">
|
|
278
|
+
<span class="category-icon">💻</span>
|
|
279
|
+
<span class="category-name">Code</span>
|
|
280
|
+
<span class="category-count" id="codeCount">0</span>
|
|
281
|
+
</div>
|
|
282
|
+
<div class="category-description">Executable scripts that Claude runs via bash without loading into context</div>
|
|
283
|
+
<div class="category-files" id="codeFiles"></div>
|
|
284
|
+
</div>
|
|
285
|
+
<div class="resource-category" id="resourcesCategory" style="display: none;">
|
|
286
|
+
<div class="category-header">
|
|
287
|
+
<span class="category-icon">📋</span>
|
|
288
|
+
<span class="category-name">Resources</span>
|
|
289
|
+
<span class="category-count" id="resourcesCount">0</span>
|
|
290
|
+
</div>
|
|
291
|
+
<div class="category-description">Reference materials like schemas, API docs, templates, and examples</div>
|
|
292
|
+
<div class="category-files" id="resourcesFiles"></div>
|
|
293
|
+
</div>
|
|
294
|
+
<div class="empty-resources" id="emptyResources">
|
|
295
|
+
<span class="empty-icon">📭</span>
|
|
296
|
+
<span class="empty-text">No additional resources</span>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
|
|
305
|
+
<div class="modal-footer">
|
|
306
|
+
<div class="modal-meta">
|
|
307
|
+
<span class="meta-item">
|
|
308
|
+
<span class="meta-label">Total Files:</span>
|
|
309
|
+
<span class="meta-value" id="modalFileCount">-</span>
|
|
310
|
+
</span>
|
|
311
|
+
<span class="meta-item">
|
|
312
|
+
<span class="meta-label">Last Modified:</span>
|
|
313
|
+
<span class="meta-value" id="modalLastModified">-</span>
|
|
314
|
+
</span>
|
|
315
|
+
<span class="meta-item">
|
|
316
|
+
<span class="meta-label">Source:</span>
|
|
317
|
+
<span class="meta-value" id="modalSource">-</span>
|
|
318
|
+
</span>
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
|
|
324
|
+
<script src="script.js"></script>
|
|
325
|
+
</body>
|
|
326
|
+
</html>
|