fix: remove highlight.js CSS import causing Docker build failure

swadhinbiswas committed 3 months ago
eeb5038
1 parent 8751a22
commit eeb5038
43 files changed
+12302 -1233
▼add-frontmatter.mjs
+32-0
1
+import fs from 'fs';
2
+import path from 'path';
3
+
4
+function processDirectory(dirPath) {
5
+ const files = fs.readdirSync(dirPath);
6
+ for (const file of files) {
7
+ const fullPath = path.join(dirPath, file);
8
+ if (fs.statSync(fullPath).isDirectory()) {
9
+ processDirectory(fullPath);
10
+ } else if (fullPath.endsWith('.md') || fullPath.endsWith('.mdx')) {
11
+ let content = fs.readFileSync(fullPath, 'utf8');
12
+ if (!content.startsWith('---')) {
13
+ // Find the first heading if it exists
14
+ const headingMatch = content.match(/^#\s+(.+)$/m);
15
+ let title = 'Untitled';
16
+ if (headingMatch) {
17
+ title = headingMatch[1].replace(/"/g, '\\"');
18
+ } else {
19
+ // Use filename as fallback title
20
+ title = path.basename(file, path.extname(file)).replace(/-/g, ' ');
21
+ title = title.charAt(0).toUpperCase() + title.slice(1);
22
+ }
23
+
24
+ const frontmatter = `---\ntitle: "${title}"\n---\n\n`;
25
+ fs.writeFileSync(fullPath, frontmatter + content);
26
+ console.log(`Added frontmatter to ${fullPath}`);
27
+ }
28
+ }
29
+ }
30
+}
31
+
32
+processDirectory('./src/content/docs');
0
33
▼astro.config.mjs
+36-3
4
4
5
5
// https://astro.build/config
6
6
export default defineConfig({
7
+ site: "https://docs.opencodehub.space",
7
8
integrations: [
8
9
starlight({
9
10
title: "OpenCodeHub Docs",
42
43
{ label: "Branch Protection", slug: "guides/branch-protection" },
43
44
{ label: "Webhooks", slug: "guides/webhooks" },
44
45
{ label: "Storage Adapters", slug: "guides/storage-adapters" },
46
+ { label: "CircleCI Integration", slug: "guides/circleci-integration" },
45
47
],
46
48
},
47
49
{
65
67
{ label: "Stacked PRs", slug: "features/stacked-prs" },
66
68
{ label: "AI Review", slug: "features/ai-review" },
67
69
{ label: "Merge Queue", slug: "features/merge-queue" },
70
+ { label: "CI/CD Actions", slug: "features/ci-actions" },
71
+ { label: "CI/CD Pipelines", slug: "features/ci-cd" },
68
72
{ label: "Automation Rules", slug: "features/automations" },
69
73
{ label: "PR Inbox", slug: "features/inbox" },
70
74
{ label: "Developer Metrics", slug: "features/developer-metrics" },
71
75
{ label: "Notifications", slug: "features/notifications" },
72
- { label: "CI/CD Actions", slug: "features/ci-actions" },
76
+ { label: "Slack Integration", slug: "features/slack-integration" },
73
77
{ label: "CLI Workflows", slug: "features/cli" },
74
78
],
75
79
},
86
90
{ label: "cPanel", slug: "administration/deploy-cpanel" },
87
91
{ label: "CyberPanel", slug: "administration/deploy-cyberpanel" },
88
92
{ label: "Cloudflare", slug: "administration/deploy-cloudflare" },
93
+ { label: "Coolify", slug: "administration/deploy-coolify" },
94
+ { label: "NAS (Synology/TrueNAS)", slug: "administration/deploy-nas" },
95
+ { label: "Kubernetes (Helm)", slug: "administration/kubernetes" },
89
96
],
90
97
},
91
98
{
95
102
{ label: "Configuration", slug: "administration/configuration" },
96
103
{ label: "Monitoring", slug: "administration/monitoring" },
97
104
{ label: "Security", slug: "administration/security" },
105
+ { label: "Deployment Matrix", slug: "administration/deployment-matrix" },
106
+ { label: "Secret Rotation", slug: "administration/secret-rotation" },
107
+ { label: "Expose NAS / Home Server", slug: "administration/expose-nas" },
108
+ { label: "CircleCI Cloud Workers", slug: "administration/circleci-cloud" },
109
+ { label: "CircleCI Self-Hosted", slug: "administration/circleci-worker" },
110
+ ],
111
+ },
112
+ {
113
+ label: "Operations",
114
+ items: [
115
+ { label: "Incident Runbook", slug: "administration/incident-runbook" },
116
+ { label: "Postmortem Template", slug: "administration/postmortem-template" },
117
+ { label: "Operations Drills", slug: "administration/operations-drills" },
98
118
],
99
119
},
100
120
{
103
123
},
104
124
{
105
125
label: "Development",
106
- autogenerate: { directory: "development" },
126
+ items: [
127
+ { label: "Architecture", slug: "development/architecture" },
128
+ { label: "Local Dev Setup", slug: "development/local-dev-setup" },
129
+ { label: "Contributing", slug: "development/contributing" },
130
+ { label: "Database Schema", slug: "development/database-schema" },
131
+ { label: "Database Migrations", slug: "development/database-migrations" },
132
+ { label: "Testing", slug: "development/testing" },
133
+ { label: "Testing & CI", slug: "development/testing-pipelines" },
134
+ { label: "Security Hardening", slug: "development/security-hardening" },
135
+ { label: "Observability", slug: "development/observability" },
136
+ { label: "Publishing CLI", slug: "development/publishing-cli" },
137
+ ],
107
138
},
108
139
{
109
140
label: "Reference",
110
- autogenerate: { directory: "reference" },
141
+ items: [
142
+ { label: "Glossary", slug: "reference/glossary" },
143
+ ],
111
144
},
112
145
],
113
146
}),
114
147
▼package-lock.json
+5662-0
1
+{
2
+ "name": "docs-site",
3
+ "version": "0.0.1",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "docs-site",
9
+ "version": "0.0.1",
10
+ "dependencies": {
11
+ "@astrojs/starlight": "^0.37.3",
12
+ "astro": "^5.6.1",
13
+ "sharp": "^0.34.2"
14
+ }
15
+ },
16
+ "node_modules/@astrojs/compiler": {
17
+ "version": "2.13.0",
18
+ "license": "MIT"
19
+ },
20
+ "node_modules/@astrojs/internal-helpers": {
21
+ "version": "0.7.5",
22
+ "license": "MIT"
23
+ },
24
+ "node_modules/@astrojs/markdown-remark": {
25
+ "version": "6.3.10",
26
+ "license": "MIT",
27
+ "dependencies": {
28
+ "@astrojs/internal-helpers": "0.7.5",
29
+ "@astrojs/prism": "3.3.0",
30
+ "github-slugger": "^2.0.0",
31
+ "hast-util-from-html": "^2.0.3",
32
+ "hast-util-to-text": "^4.0.2",
33
+ "import-meta-resolve": "^4.2.0",
34
+ "js-yaml": "^4.1.1",
35
+ "mdast-util-definitions": "^6.0.0",
36
+ "rehype-raw": "^7.0.0",
37
+ "rehype-stringify": "^10.0.1",
38
+ "remark-gfm": "^4.0.1",
39
+ "remark-parse": "^11.0.0",
40
+ "remark-rehype": "^11.1.2",
41
+ "remark-smartypants": "^3.0.2",
42
+ "shiki": "^3.19.0",
43
+ "smol-toml": "^1.5.2",
44
+ "unified": "^11.0.5",
45
+ "unist-util-remove-position": "^5.0.0",
46
+ "unist-util-visit": "^5.0.0",
47
+ "unist-util-visit-parents": "^6.0.2",
48
+ "vfile": "^6.0.3"
49
+ }
50
+ },
51
+ "node_modules/@astrojs/mdx": {
52
+ "version": "4.3.13",
53
+ "license": "MIT",
54
+ "dependencies": {
55
+ "@astrojs/markdown-remark": "6.3.10",
56
+ "@mdx-js/mdx": "^3.1.1",
57
+ "acorn": "^8.15.0",
58
+ "es-module-lexer": "^1.7.0",
59
+ "estree-util-visit": "^2.0.0",
60
+ "hast-util-to-html": "^9.0.5",
61
+ "piccolore": "^0.1.3",
62
+ "rehype-raw": "^7.0.0",
63
+ "remark-gfm": "^4.0.1",
64
+ "remark-smartypants": "^3.0.2",
65
+ "source-map": "^0.7.6",
66
+ "unist-util-visit": "^5.0.0",
67
+ "vfile": "^6.0.3"
68
+ },
69
+ "engines": {
70
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
71
+ },
72
+ "peerDependencies": {
73
+ "astro": "^5.0.0"
74
+ }
75
+ },
76
+ "node_modules/@astrojs/prism": {
77
+ "version": "3.3.0",
78
+ "license": "MIT",
79
+ "dependencies": {
80
+ "prismjs": "^1.30.0"
81
+ },
82
+ "engines": {
83
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
84
+ }
85
+ },
86
+ "node_modules/@astrojs/sitemap": {
87
+ "version": "3.7.0",
88
+ "license": "MIT",
89
+ "dependencies": {
90
+ "sitemap": "^8.0.2",
91
+ "stream-replace-string": "^2.0.0",
92
+ "zod": "^3.25.76"
93
+ }
94
+ },
95
+ "node_modules/@astrojs/starlight": {
96
+ "version": "0.37.3",
97
+ "license": "MIT",
98
+ "dependencies": {
99
+ "@astrojs/markdown-remark": "^6.3.1",
100
+ "@astrojs/mdx": "^4.2.3",
101
+ "@astrojs/sitemap": "^3.3.0",
102
+ "@pagefind/default-ui": "^1.3.0",
103
+ "@types/hast": "^3.0.4",
104
+ "@types/js-yaml": "^4.0.9",
105
+ "@types/mdast": "^4.0.4",
106
+ "astro-expressive-code": "^0.41.1",
107
+ "bcp-47": "^2.1.0",
108
+ "hast-util-from-html": "^2.0.1",
109
+ "hast-util-select": "^6.0.2",
110
+ "hast-util-to-string": "^3.0.0",
111
+ "hastscript": "^9.0.0",
112
+ "i18next": "^23.11.5",
113
+ "js-yaml": "^4.1.0",
114
+ "klona": "^2.0.6",
115
+ "magic-string": "^0.30.17",
116
+ "mdast-util-directive": "^3.0.0",
117
+ "mdast-util-to-markdown": "^2.1.0",
118
+ "mdast-util-to-string": "^4.0.0",
119
+ "pagefind": "^1.3.0",
120
+ "rehype": "^13.0.1",
121
+ "rehype-format": "^5.0.0",
122
+ "remark-directive": "^3.0.0",
123
+ "ultrahtml": "^1.6.0",
124
+ "unified": "^11.0.5",
125
+ "unist-util-visit": "^5.0.0",
126
+ "vfile": "^6.0.2"
127
+ },
128
+ "peerDependencies": {
129
+ "astro": "^5.5.0"
130
+ }
131
+ },
132
+ "node_modules/@astrojs/telemetry": {
133
+ "version": "3.3.0",
134
+ "license": "MIT",
135
+ "dependencies": {
136
+ "ci-info": "^4.2.0",
137
+ "debug": "^4.4.0",
138
+ "dlv": "^1.1.3",
139
+ "dset": "^3.1.4",
140
+ "is-docker": "^3.0.0",
141
+ "is-wsl": "^3.1.0",
142
+ "which-pm-runs": "^1.1.0"
143
+ },
144
+ "engines": {
145
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
146
+ }
147
+ },
148
+ "node_modules/@babel/helper-string-parser": {
149
+ "version": "7.27.1",
150
+ "license": "MIT",
151
+ "engines": {
152
+ "node": ">=6.9.0"
153
+ }
154
+ },
155
+ "node_modules/@babel/helper-validator-identifier": {
156
+ "version": "7.28.5",
157
+ "license": "MIT",
158
+ "engines": {
159
+ "node": ">=6.9.0"
160
+ }
161
+ },
162
+ "node_modules/@babel/parser": {
163
+ "version": "7.28.6",
164
+ "license": "MIT",
165
+ "dependencies": {
166
+ "@babel/types": "^7.28.6"
167
+ },
168
+ "bin": {
169
+ "parser": "bin/babel-parser.js"
170
+ },
171
+ "engines": {
172
+ "node": ">=6.0.0"
173
+ }
174
+ },
175
+ "node_modules/@babel/runtime": {
176
+ "version": "7.28.6",
177
+ "license": "MIT",
178
+ "engines": {
179
+ "node": ">=6.9.0"
180
+ }
181
+ },
182
+ "node_modules/@babel/types": {
183
+ "version": "7.28.6",
184
+ "license": "MIT",
185
+ "dependencies": {
186
+ "@babel/helper-string-parser": "^7.27.1",
187
+ "@babel/helper-validator-identifier": "^7.28.5"
188
+ },
189
+ "engines": {
190
+ "node": ">=6.9.0"
191
+ }
192
+ },
193
+ "node_modules/@capsizecss/unpack": {
194
+ "version": "4.0.0",
195
+ "license": "MIT",
196
+ "dependencies": {
197
+ "fontkitten": "^1.0.0"
198
+ },
199
+ "engines": {
200
+ "node": ">=18"
201
+ }
202
+ },
203
+ "node_modules/@ctrl/tinycolor": {
204
+ "version": "4.2.0",
205
+ "license": "MIT",
206
+ "engines": {
207
+ "node": ">=14"
208
+ }
209
+ },
210
+ "node_modules/@emnapi/runtime": {
211
+ "version": "1.11.2",
212
+ "resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.11.2.tgz",
213
+ "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==",
214
+ "license": "MIT",
215
+ "optional": true,
216
+ "dependencies": {
217
+ "tslib": "^2.4.0"
218
+ }
219
+ },
220
+ "node_modules/@esbuild/aix-ppc64": {
221
+ "version": "0.25.12",
222
+ "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
223
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
224
+ "cpu": [
225
+ "ppc64"
226
+ ],
227
+ "license": "MIT",
228
+ "optional": true,
229
+ "os": [
230
+ "aix"
231
+ ],
232
+ "engines": {
233
+ "node": ">=18"
234
+ }
235
+ },
236
+ "node_modules/@esbuild/android-arm": {
237
+ "version": "0.25.12",
238
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
239
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
240
+ "cpu": [
241
+ "arm"
242
+ ],
243
+ "license": "MIT",
244
+ "optional": true,
245
+ "os": [
246
+ "android"
247
+ ],
248
+ "engines": {
249
+ "node": ">=18"
250
+ }
251
+ },
252
+ "node_modules/@esbuild/android-arm64": {
253
+ "version": "0.25.12",
254
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
255
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
256
+ "cpu": [
257
+ "arm64"
258
+ ],
259
+ "license": "MIT",
260
+ "optional": true,
261
+ "os": [
262
+ "android"
263
+ ],
264
+ "engines": {
265
+ "node": ">=18"
266
+ }
267
+ },
268
+ "node_modules/@esbuild/android-x64": {
269
+ "version": "0.25.12",
270
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
271
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
272
+ "cpu": [
273
+ "x64"
274
+ ],
275
+ "license": "MIT",
276
+ "optional": true,
277
+ "os": [
278
+ "android"
279
+ ],
280
+ "engines": {
281
+ "node": ">=18"
282
+ }
283
+ },
284
+ "node_modules/@esbuild/darwin-arm64": {
285
+ "version": "0.25.12",
286
+ "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
287
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
288
+ "cpu": [
289
+ "arm64"
290
+ ],
291
+ "license": "MIT",
292
+ "optional": true,
293
+ "os": [
294
+ "darwin"
295
+ ],
296
+ "engines": {
297
+ "node": ">=18"
298
+ }
299
+ },
300
+ "node_modules/@esbuild/darwin-x64": {
301
+ "version": "0.25.12",
302
+ "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
303
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
304
+ "cpu": [
305
+ "x64"
306
+ ],
307
+ "license": "MIT",
308
+ "optional": true,
309
+ "os": [
310
+ "darwin"
311
+ ],
312
+ "engines": {
313
+ "node": ">=18"
314
+ }
315
+ },
316
+ "node_modules/@esbuild/freebsd-arm64": {
317
+ "version": "0.25.12",
318
+ "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
319
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
320
+ "cpu": [
321
+ "arm64"
322
+ ],
323
+ "license": "MIT",
324
+ "optional": true,
325
+ "os": [
326
+ "freebsd"
327
+ ],
328
+ "engines": {
329
+ "node": ">=18"
330
+ }
331
+ },
332
+ "node_modules/@esbuild/freebsd-x64": {
333
+ "version": "0.25.12",
334
+ "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
335
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
336
+ "cpu": [
337
+ "x64"
338
+ ],
339
+ "license": "MIT",
340
+ "optional": true,
341
+ "os": [
342
+ "freebsd"
343
+ ],
344
+ "engines": {
345
+ "node": ">=18"
346
+ }
347
+ },
348
+ "node_modules/@esbuild/linux-arm": {
349
+ "version": "0.25.12",
350
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
351
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
352
+ "cpu": [
353
+ "arm"
354
+ ],
355
+ "license": "MIT",
356
+ "optional": true,
357
+ "os": [
358
+ "linux"
359
+ ],
360
+ "engines": {
361
+ "node": ">=18"
362
+ }
363
+ },
364
+ "node_modules/@esbuild/linux-arm64": {
365
+ "version": "0.25.12",
366
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
367
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
368
+ "cpu": [
369
+ "arm64"
370
+ ],
371
+ "license": "MIT",
372
+ "optional": true,
373
+ "os": [
374
+ "linux"
375
+ ],
376
+ "engines": {
377
+ "node": ">=18"
378
+ }
379
+ },
380
+ "node_modules/@esbuild/linux-ia32": {
381
+ "version": "0.25.12",
382
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
383
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
384
+ "cpu": [
385
+ "ia32"
386
+ ],
387
+ "license": "MIT",
388
+ "optional": true,
389
+ "os": [
390
+ "linux"
391
+ ],
392
+ "engines": {
393
+ "node": ">=18"
394
+ }
395
+ },
396
+ "node_modules/@esbuild/linux-loong64": {
397
+ "version": "0.25.12",
398
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
399
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
400
+ "cpu": [
401
+ "loong64"
402
+ ],
403
+ "license": "MIT",
404
+ "optional": true,
405
+ "os": [
406
+ "linux"
407
+ ],
408
+ "engines": {
409
+ "node": ">=18"
410
+ }
411
+ },
412
+ "node_modules/@esbuild/linux-mips64el": {
413
+ "version": "0.25.12",
414
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
415
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
416
+ "cpu": [
417
+ "mips64el"
418
+ ],
419
+ "license": "MIT",
420
+ "optional": true,
421
+ "os": [
422
+ "linux"
423
+ ],
424
+ "engines": {
425
+ "node": ">=18"
426
+ }
427
+ },
428
+ "node_modules/@esbuild/linux-ppc64": {
429
+ "version": "0.25.12",
430
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
431
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
432
+ "cpu": [
433
+ "ppc64"
434
+ ],
435
+ "license": "MIT",
436
+ "optional": true,
437
+ "os": [
438
+ "linux"
439
+ ],
440
+ "engines": {
441
+ "node": ">=18"
442
+ }
443
+ },
444
+ "node_modules/@esbuild/linux-riscv64": {
445
+ "version": "0.25.12",
446
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
447
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
448
+ "cpu": [
449
+ "riscv64"
450
+ ],
451
+ "license": "MIT",
452
+ "optional": true,
453
+ "os": [
454
+ "linux"
455
+ ],
456
+ "engines": {
457
+ "node": ">=18"
458
+ }
459
+ },
460
+ "node_modules/@esbuild/linux-s390x": {
461
+ "version": "0.25.12",
462
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
463
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
464
+ "cpu": [
465
+ "s390x"
466
+ ],
467
+ "license": "MIT",
468
+ "optional": true,
469
+ "os": [
470
+ "linux"
471
+ ],
472
+ "engines": {
473
+ "node": ">=18"
474
+ }
475
+ },
476
+ "node_modules/@esbuild/linux-x64": {
477
+ "version": "0.25.12",
478
+ "cpu": [
479
+ "x64"
480
+ ],
481
+ "license": "MIT",
482
+ "optional": true,
483
+ "os": [
484
+ "linux"
485
+ ],
486
+ "engines": {
487
+ "node": ">=18"
488
+ }
489
+ },
490
+ "node_modules/@esbuild/netbsd-arm64": {
491
+ "version": "0.25.12",
492
+ "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
493
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
494
+ "cpu": [
495
+ "arm64"
496
+ ],
497
+ "license": "MIT",
498
+ "optional": true,
499
+ "os": [
500
+ "netbsd"
501
+ ],
502
+ "engines": {
503
+ "node": ">=18"
504
+ }
505
+ },
506
+ "node_modules/@esbuild/netbsd-x64": {
507
+ "version": "0.25.12",
508
+ "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
509
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
510
+ "cpu": [
511
+ "x64"
512
+ ],
513
+ "license": "MIT",
514
+ "optional": true,
515
+ "os": [
516
+ "netbsd"
517
+ ],
518
+ "engines": {
519
+ "node": ">=18"
520
+ }
521
+ },
522
+ "node_modules/@esbuild/openbsd-arm64": {
523
+ "version": "0.25.12",
524
+ "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
525
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
526
+ "cpu": [
527
+ "arm64"
528
+ ],
529
+ "license": "MIT",
530
+ "optional": true,
531
+ "os": [
532
+ "openbsd"
533
+ ],
534
+ "engines": {
535
+ "node": ">=18"
536
+ }
537
+ },
538
+ "node_modules/@esbuild/openbsd-x64": {
539
+ "version": "0.25.12",
540
+ "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
541
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
542
+ "cpu": [
543
+ "x64"
544
+ ],
545
+ "license": "MIT",
546
+ "optional": true,
547
+ "os": [
548
+ "openbsd"
549
+ ],
550
+ "engines": {
551
+ "node": ">=18"
552
+ }
553
+ },
554
+ "node_modules/@esbuild/openharmony-arm64": {
555
+ "version": "0.25.12",
556
+ "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
557
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
558
+ "cpu": [
559
+ "arm64"
560
+ ],
561
+ "license": "MIT",
562
+ "optional": true,
563
+ "os": [
564
+ "openharmony"
565
+ ],
566
+ "engines": {
567
+ "node": ">=18"
568
+ }
569
+ },
570
+ "node_modules/@esbuild/sunos-x64": {
571
+ "version": "0.25.12",
572
+ "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
573
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
574
+ "cpu": [
575
+ "x64"
576
+ ],
577
+ "license": "MIT",
578
+ "optional": true,
579
+ "os": [
580
+ "sunos"
581
+ ],
582
+ "engines": {
583
+ "node": ">=18"
584
+ }
585
+ },
586
+ "node_modules/@esbuild/win32-arm64": {
587
+ "version": "0.25.12",
588
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
589
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
590
+ "cpu": [
591
+ "arm64"
592
+ ],
593
+ "license": "MIT",
594
+ "optional": true,
595
+ "os": [
596
+ "win32"
597
+ ],
598
+ "engines": {
599
+ "node": ">=18"
600
+ }
601
+ },
602
+ "node_modules/@esbuild/win32-ia32": {
603
+ "version": "0.25.12",
604
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
605
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
606
+ "cpu": [
607
+ "ia32"
608
+ ],
609
+ "license": "MIT",
610
+ "optional": true,
611
+ "os": [
612
+ "win32"
613
+ ],
614
+ "engines": {
615
+ "node": ">=18"
616
+ }
617
+ },
618
+ "node_modules/@esbuild/win32-x64": {
619
+ "version": "0.25.12",
620
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
621
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
622
+ "cpu": [
623
+ "x64"
624
+ ],
625
+ "license": "MIT",
626
+ "optional": true,
627
+ "os": [
628
+ "win32"
629
+ ],
630
+ "engines": {
631
+ "node": ">=18"
632
+ }
633
+ },
634
+ "node_modules/@expressive-code/core": {
635
+ "version": "0.41.6",
636
+ "license": "MIT",
637
+ "dependencies": {
638
+ "@ctrl/tinycolor": "^4.0.4",
639
+ "hast-util-select": "^6.0.2",
640
+ "hast-util-to-html": "^9.0.1",
641
+ "hast-util-to-text": "^4.0.1",
642
+ "hastscript": "^9.0.0",
643
+ "postcss": "^8.4.38",
644
+ "postcss-nested": "^6.0.1",
645
+ "unist-util-visit": "^5.0.0",
646
+ "unist-util-visit-parents": "^6.0.1"
647
+ }
648
+ },
649
+ "node_modules/@expressive-code/plugin-frames": {
650
+ "version": "0.41.6",
651
+ "license": "MIT",
652
+ "dependencies": {
653
+ "@expressive-code/core": "^0.41.6"
654
+ }
655
+ },
656
+ "node_modules/@expressive-code/plugin-shiki": {
657
+ "version": "0.41.6",
658
+ "license": "MIT",
659
+ "dependencies": {
660
+ "@expressive-code/core": "^0.41.6",
661
+ "shiki": "^3.2.2"
662
+ }
663
+ },
664
+ "node_modules/@expressive-code/plugin-text-markers": {
665
+ "version": "0.41.6",
666
+ "license": "MIT",
667
+ "dependencies": {
668
+ "@expressive-code/core": "^0.41.6"
669
+ }
670
+ },
671
+ "node_modules/@img/colour": {
672
+ "version": "1.0.0",
673
+ "license": "MIT",
674
+ "engines": {
675
+ "node": ">=18"
676
+ }
677
+ },
678
+ "node_modules/@img/sharp-darwin-arm64": {
679
+ "version": "0.34.5",
680
+ "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
681
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
682
+ "cpu": [
683
+ "arm64"
684
+ ],
685
+ "license": "Apache-2.0",
686
+ "optional": true,
687
+ "os": [
688
+ "darwin"
689
+ ],
690
+ "engines": {
691
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
692
+ },
693
+ "funding": {
694
+ "url": "https://opencollective.com/libvips"
695
+ },
696
+ "optionalDependencies": {
697
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
698
+ }
699
+ },
700
+ "node_modules/@img/sharp-darwin-x64": {
701
+ "version": "0.34.5",
702
+ "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
703
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
704
+ "cpu": [
705
+ "x64"
706
+ ],
707
+ "license": "Apache-2.0",
708
+ "optional": true,
709
+ "os": [
710
+ "darwin"
711
+ ],
712
+ "engines": {
713
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
714
+ },
715
+ "funding": {
716
+ "url": "https://opencollective.com/libvips"
717
+ },
718
+ "optionalDependencies": {
719
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
720
+ }
721
+ },
722
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
723
+ "version": "1.2.4",
724
+ "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
725
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
726
+ "cpu": [
727
+ "arm64"
728
+ ],
729
+ "license": "LGPL-3.0-or-later",
730
+ "optional": true,
731
+ "os": [
732
+ "darwin"
733
+ ],
734
+ "funding": {
735
+ "url": "https://opencollective.com/libvips"
736
+ }
737
+ },
738
+ "node_modules/@img/sharp-libvips-darwin-x64": {
739
+ "version": "1.2.4",
740
+ "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
741
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
742
+ "cpu": [
743
+ "x64"
744
+ ],
745
+ "license": "LGPL-3.0-or-later",
746
+ "optional": true,
747
+ "os": [
748
+ "darwin"
749
+ ],
750
+ "funding": {
751
+ "url": "https://opencollective.com/libvips"
752
+ }
753
+ },
754
+ "node_modules/@img/sharp-libvips-linux-arm": {
755
+ "version": "1.2.4",
756
+ "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
757
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
758
+ "cpu": [
759
+ "arm"
760
+ ],
761
+ "license": "LGPL-3.0-or-later",
762
+ "optional": true,
763
+ "os": [
764
+ "linux"
765
+ ],
766
+ "funding": {
767
+ "url": "https://opencollective.com/libvips"
768
+ }
769
+ },
770
+ "node_modules/@img/sharp-libvips-linux-arm64": {
771
+ "version": "1.2.4",
772
+ "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
773
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
774
+ "cpu": [
775
+ "arm64"
776
+ ],
777
+ "license": "LGPL-3.0-or-later",
778
+ "optional": true,
779
+ "os": [
780
+ "linux"
781
+ ],
782
+ "funding": {
783
+ "url": "https://opencollective.com/libvips"
784
+ }
785
+ },
786
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
787
+ "version": "1.2.4",
788
+ "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
789
+ "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
790
+ "cpu": [
791
+ "ppc64"
792
+ ],
793
+ "license": "LGPL-3.0-or-later",
794
+ "optional": true,
795
+ "os": [
796
+ "linux"
797
+ ],
798
+ "funding": {
799
+ "url": "https://opencollective.com/libvips"
800
+ }
801
+ },
802
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
803
+ "version": "1.2.4",
804
+ "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
805
+ "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
806
+ "cpu": [
807
+ "riscv64"
808
+ ],
809
+ "license": "LGPL-3.0-or-later",
810
+ "optional": true,
811
+ "os": [
812
+ "linux"
813
+ ],
814
+ "funding": {
815
+ "url": "https://opencollective.com/libvips"
816
+ }
817
+ },
818
+ "node_modules/@img/sharp-libvips-linux-s390x": {
819
+ "version": "1.2.4",
820
+ "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
821
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
822
+ "cpu": [
823
+ "s390x"
824
+ ],
825
+ "license": "LGPL-3.0-or-later",
826
+ "optional": true,
827
+ "os": [
828
+ "linux"
829
+ ],
830
+ "funding": {
831
+ "url": "https://opencollective.com/libvips"
832
+ }
833
+ },
834
+ "node_modules/@img/sharp-libvips-linux-x64": {
835
+ "version": "1.2.4",
836
+ "cpu": [
837
+ "x64"
838
+ ],
839
+ "license": "LGPL-3.0-or-later",
840
+ "optional": true,
841
+ "os": [
842
+ "linux"
843
+ ],
844
+ "funding": {
845
+ "url": "https://opencollective.com/libvips"
846
+ }
847
+ },
848
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
849
+ "version": "1.2.4",
850
+ "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
851
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
852
+ "cpu": [
853
+ "arm64"
854
+ ],
855
+ "license": "LGPL-3.0-or-later",
856
+ "optional": true,
857
+ "os": [
858
+ "linux"
859
+ ],
860
+ "funding": {
861
+ "url": "https://opencollective.com/libvips"
862
+ }
863
+ },
864
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
865
+ "version": "1.2.4",
866
+ "cpu": [
867
+ "x64"
868
+ ],
869
+ "license": "LGPL-3.0-or-later",
870
+ "optional": true,
871
+ "os": [
872
+ "linux"
873
+ ],
874
+ "funding": {
875
+ "url": "https://opencollective.com/libvips"
876
+ }
877
+ },
878
+ "node_modules/@img/sharp-linux-arm": {
879
+ "version": "0.34.5",
880
+ "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
881
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
882
+ "cpu": [
883
+ "arm"
884
+ ],
885
+ "license": "Apache-2.0",
886
+ "optional": true,
887
+ "os": [
888
+ "linux"
889
+ ],
890
+ "engines": {
891
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
892
+ },
893
+ "funding": {
894
+ "url": "https://opencollective.com/libvips"
895
+ },
896
+ "optionalDependencies": {
897
+ "@img/sharp-libvips-linux-arm": "1.2.4"
898
+ }
899
+ },
900
+ "node_modules/@img/sharp-linux-arm64": {
901
+ "version": "0.34.5",
902
+ "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
903
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
904
+ "cpu": [
905
+ "arm64"
906
+ ],
907
+ "license": "Apache-2.0",
908
+ "optional": true,
909
+ "os": [
910
+ "linux"
911
+ ],
912
+ "engines": {
913
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
914
+ },
915
+ "funding": {
916
+ "url": "https://opencollective.com/libvips"
917
+ },
918
+ "optionalDependencies": {
919
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
920
+ }
921
+ },
922
+ "node_modules/@img/sharp-linux-ppc64": {
923
+ "version": "0.34.5",
924
+ "resolved": "https://registry.npmmirror.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
925
+ "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
926
+ "cpu": [
927
+ "ppc64"
928
+ ],
929
+ "license": "Apache-2.0",
930
+ "optional": true,
931
+ "os": [
932
+ "linux"
933
+ ],
934
+ "engines": {
935
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
936
+ },
937
+ "funding": {
938
+ "url": "https://opencollective.com/libvips"
939
+ },
940
+ "optionalDependencies": {
941
+ "@img/sharp-libvips-linux-ppc64": "1.2.4"
942
+ }
943
+ },
944
+ "node_modules/@img/sharp-linux-riscv64": {
945
+ "version": "0.34.5",
946
+ "resolved": "https://registry.npmmirror.com/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
947
+ "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
948
+ "cpu": [
949
+ "riscv64"
950
+ ],
951
+ "license": "Apache-2.0",
952
+ "optional": true,
953
+ "os": [
954
+ "linux"
955
+ ],
956
+ "engines": {
957
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
958
+ },
959
+ "funding": {
960
+ "url": "https://opencollective.com/libvips"
961
+ },
962
+ "optionalDependencies": {
963
+ "@img/sharp-libvips-linux-riscv64": "1.2.4"
964
+ }
965
+ },
966
+ "node_modules/@img/sharp-linux-s390x": {
967
+ "version": "0.34.5",
968
+ "resolved": "https://registry.npmmirror.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
969
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
970
+ "cpu": [
971
+ "s390x"
972
+ ],
973
+ "license": "Apache-2.0",
974
+ "optional": true,
975
+ "os": [
976
+ "linux"
977
+ ],
978
+ "engines": {
979
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
980
+ },
981
+ "funding": {
982
+ "url": "https://opencollective.com/libvips"
983
+ },
984
+ "optionalDependencies": {
985
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
986
+ }
987
+ },
988
+ "node_modules/@img/sharp-linux-x64": {
989
+ "version": "0.34.5",
990
+ "cpu": [
991
+ "x64"
992
+ ],
993
+ "license": "Apache-2.0",
994
+ "optional": true,
995
+ "os": [
996
+ "linux"
997
+ ],
998
+ "engines": {
999
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
1000
+ },
1001
+ "funding": {
1002
+ "url": "https://opencollective.com/libvips"
1003
+ },
1004
+ "optionalDependencies": {
1005
+ "@img/sharp-libvips-linux-x64": "1.2.4"
1006
+ }
1007
+ },
1008
+ "node_modules/@img/sharp-linuxmusl-arm64": {
1009
+ "version": "0.34.5",
1010
+ "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
1011
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
1012
+ "cpu": [
1013
+ "arm64"
1014
+ ],
1015
+ "license": "Apache-2.0",
1016
+ "optional": true,
1017
+ "os": [
1018
+ "linux"
1019
+ ],
1020
+ "engines": {
1021
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
1022
+ },
1023
+ "funding": {
1024
+ "url": "https://opencollective.com/libvips"
1025
+ },
1026
+ "optionalDependencies": {
1027
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
1028
+ }
1029
+ },
1030
+ "node_modules/@img/sharp-linuxmusl-x64": {
1031
+ "version": "0.34.5",
1032
+ "cpu": [
1033
+ "x64"
1034
+ ],
1035
+ "license": "Apache-2.0",
1036
+ "optional": true,
1037
+ "os": [
1038
+ "linux"
1039
+ ],
1040
+ "engines": {
1041
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
1042
+ },
1043
+ "funding": {
1044
+ "url": "https://opencollective.com/libvips"
1045
+ },
1046
+ "optionalDependencies": {
1047
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
1048
+ }
1049
+ },
1050
+ "node_modules/@img/sharp-wasm32": {
1051
+ "version": "0.34.5",
1052
+ "resolved": "https://registry.npmmirror.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
1053
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
1054
+ "cpu": [
1055
+ "wasm32"
1056
+ ],
1057
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
1058
+ "optional": true,
1059
+ "dependencies": {
1060
+ "@emnapi/runtime": "^1.7.0"
1061
+ },
1062
+ "engines": {
1063
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
1064
+ },
1065
+ "funding": {
1066
+ "url": "https://opencollective.com/libvips"
1067
+ }
1068
+ },
1069
+ "node_modules/@img/sharp-win32-arm64": {
1070
+ "version": "0.34.5",
1071
+ "resolved": "https://registry.npmmirror.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
1072
+ "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
1073
+ "cpu": [
1074
+ "arm64"
1075
+ ],
1076
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
1077
+ "optional": true,
1078
+ "os": [
1079
+ "win32"
1080
+ ],
1081
+ "engines": {
1082
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
1083
+ },
1084
+ "funding": {
1085
+ "url": "https://opencollective.com/libvips"
1086
+ }
1087
+ },
1088
+ "node_modules/@img/sharp-win32-ia32": {
1089
+ "version": "0.34.5",
1090
+ "resolved": "https://registry.npmmirror.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
1091
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
1092
+ "cpu": [
1093
+ "ia32"
1094
+ ],
1095
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
1096
+ "optional": true,
1097
+ "os": [
1098
+ "win32"
1099
+ ],
1100
+ "engines": {
1101
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
1102
+ },
1103
+ "funding": {
1104
+ "url": "https://opencollective.com/libvips"
1105
+ }
1106
+ },
1107
+ "node_modules/@img/sharp-win32-x64": {
1108
+ "version": "0.34.5",
1109
+ "resolved": "https://registry.npmmirror.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
1110
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
1111
+ "cpu": [
1112
+ "x64"
1113
+ ],
1114
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
1115
+ "optional": true,
1116
+ "os": [
1117
+ "win32"
1118
+ ],
1119
+ "engines": {
1120
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
1121
+ },
1122
+ "funding": {
1123
+ "url": "https://opencollective.com/libvips"
1124
+ }
1125
+ },
1126
+ "node_modules/@jridgewell/sourcemap-codec": {
1127
+ "version": "1.5.5",
1128
+ "license": "MIT"
1129
+ },
1130
+ "node_modules/@mdx-js/mdx": {
1131
+ "version": "3.1.1",
1132
+ "license": "MIT",
1133
+ "dependencies": {
1134
+ "@types/estree": "^1.0.0",
1135
+ "@types/estree-jsx": "^1.0.0",
1136
+ "@types/hast": "^3.0.0",
1137
+ "@types/mdx": "^2.0.0",
1138
+ "acorn": "^8.0.0",
1139
+ "collapse-white-space": "^2.0.0",
1140
+ "devlop": "^1.0.0",
1141
+ "estree-util-is-identifier-name": "^3.0.0",
1142
+ "estree-util-scope": "^1.0.0",
1143
+ "estree-walker": "^3.0.0",
1144
+ "hast-util-to-jsx-runtime": "^2.0.0",
1145
+ "markdown-extensions": "^2.0.0",
1146
+ "recma-build-jsx": "^1.0.0",
1147
+ "recma-jsx": "^1.0.0",
1148
+ "recma-stringify": "^1.0.0",
1149
+ "rehype-recma": "^1.0.0",
1150
+ "remark-mdx": "^3.0.0",
1151
+ "remark-parse": "^11.0.0",
1152
+ "remark-rehype": "^11.0.0",
1153
+ "source-map": "^0.7.0",
1154
+ "unified": "^11.0.0",
1155
+ "unist-util-position-from-estree": "^2.0.0",
1156
+ "unist-util-stringify-position": "^4.0.0",
1157
+ "unist-util-visit": "^5.0.0",
1158
+ "vfile": "^6.0.0"
1159
+ },
1160
+ "funding": {
1161
+ "type": "opencollective",
1162
+ "url": "https://opencollective.com/unified"
1163
+ }
1164
+ },
1165
+ "node_modules/@oslojs/encoding": {
1166
+ "version": "1.1.0",
1167
+ "license": "MIT"
1168
+ },
1169
+ "node_modules/@pagefind/darwin-arm64": {
1170
+ "version": "1.4.0",
1171
+ "resolved": "https://registry.npmmirror.com/@pagefind/darwin-arm64/-/darwin-arm64-1.4.0.tgz",
1172
+ "integrity": "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==",
1173
+ "cpu": [
1174
+ "arm64"
1175
+ ],
1176
+ "license": "MIT",
1177
+ "optional": true,
1178
+ "os": [
1179
+ "darwin"
1180
+ ]
1181
+ },
1182
+ "node_modules/@pagefind/darwin-x64": {
1183
+ "version": "1.4.0",
1184
+ "resolved": "https://registry.npmmirror.com/@pagefind/darwin-x64/-/darwin-x64-1.4.0.tgz",
1185
+ "integrity": "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==",
1186
+ "cpu": [
1187
+ "x64"
1188
+ ],
1189
+ "license": "MIT",
1190
+ "optional": true,
1191
+ "os": [
1192
+ "darwin"
1193
+ ]
1194
+ },
1195
+ "node_modules/@pagefind/default-ui": {
1196
+ "version": "1.4.0",
1197
+ "license": "MIT"
1198
+ },
1199
+ "node_modules/@pagefind/freebsd-x64": {
1200
+ "version": "1.4.0",
1201
+ "resolved": "https://registry.npmmirror.com/@pagefind/freebsd-x64/-/freebsd-x64-1.4.0.tgz",
1202
+ "integrity": "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==",
1203
+ "cpu": [
1204
+ "x64"
1205
+ ],
1206
+ "license": "MIT",
1207
+ "optional": true,
1208
+ "os": [
1209
+ "freebsd"
1210
+ ]
1211
+ },
1212
+ "node_modules/@pagefind/linux-arm64": {
1213
+ "version": "1.4.0",
1214
+ "resolved": "https://registry.npmmirror.com/@pagefind/linux-arm64/-/linux-arm64-1.4.0.tgz",
1215
+ "integrity": "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==",
1216
+ "cpu": [
1217
+ "arm64"
1218
+ ],
1219
+ "license": "MIT",
1220
+ "optional": true,
1221
+ "os": [
1222
+ "linux"
1223
+ ]
1224
+ },
1225
+ "node_modules/@pagefind/linux-x64": {
1226
+ "version": "1.4.0",
1227
+ "cpu": [
1228
+ "x64"
1229
+ ],
1230
+ "license": "MIT",
1231
+ "optional": true,
1232
+ "os": [
1233
+ "linux"
1234
+ ]
1235
+ },
1236
+ "node_modules/@pagefind/windows-x64": {
1237
+ "version": "1.4.0",
1238
+ "resolved": "https://registry.npmmirror.com/@pagefind/windows-x64/-/windows-x64-1.4.0.tgz",
1239
+ "integrity": "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==",
1240
+ "cpu": [
1241
+ "x64"
1242
+ ],
1243
+ "license": "MIT",
1244
+ "optional": true,
1245
+ "os": [
1246
+ "win32"
1247
+ ]
1248
+ },
1249
+ "node_modules/@rollup/pluginutils": {
1250
+ "version": "5.3.0",
1251
+ "license": "MIT",
1252
+ "dependencies": {
1253
+ "@types/estree": "^1.0.0",
1254
+ "estree-walker": "^2.0.2",
1255
+ "picomatch": "^4.0.2"
1256
+ },
1257
+ "engines": {
1258
+ "node": ">=14.0.0"
1259
+ },
1260
+ "peerDependencies": {
1261
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
1262
+ },
1263
+ "peerDependenciesMeta": {
1264
+ "rollup": {
1265
+ "optional": true
1266
+ }
1267
+ }
1268
+ },
1269
+ "node_modules/@rollup/pluginutils/node_modules/estree-walker": {
1270
+ "version": "2.0.2",
1271
+ "license": "MIT"
1272
+ },
1273
+ "node_modules/@rollup/rollup-android-arm-eabi": {
1274
+ "version": "4.55.3",
1275
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.3.tgz",
1276
+ "integrity": "sha512-qyX8+93kK/7R5BEXPC2PjUt0+fS/VO2BVHjEHyIEWiYn88rcRBHmdLgoJjktBltgAf+NY7RfCGB1SoyKS/p9kg==",
1277
+ "cpu": [
1278
+ "arm"
1279
+ ],
1280
+ "license": "MIT",
1281
+ "optional": true,
1282
+ "os": [
1283
+ "android"
1284
+ ]
1285
+ },
1286
+ "node_modules/@rollup/rollup-android-arm64": {
1287
+ "version": "4.55.3",
1288
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.3.tgz",
1289
+ "integrity": "sha512-6sHrL42bjt5dHQzJ12Q4vMKfN+kUnZ0atHHnv4V0Wd9JMTk7FDzSY35+7qbz3ypQYMBPANbpGK7JpnWNnhGt8g==",
1290
+ "cpu": [
1291
+ "arm64"
1292
+ ],
1293
+ "license": "MIT",
1294
+ "optional": true,
1295
+ "os": [
1296
+ "android"
1297
+ ]
1298
+ },
1299
+ "node_modules/@rollup/rollup-darwin-arm64": {
1300
+ "version": "4.55.3",
1301
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.3.tgz",
1302
+ "integrity": "sha512-1ht2SpGIjEl2igJ9AbNpPIKzb1B5goXOcmtD0RFxnwNuMxqkR6AUaaErZz+4o+FKmzxcSNBOLrzsICZVNYa1Rw==",
1303
+ "cpu": [
1304
+ "arm64"
1305
+ ],
1306
+ "license": "MIT",
1307
+ "optional": true,
1308
+ "os": [
1309
+ "darwin"
1310
+ ]
1311
+ },
1312
+ "node_modules/@rollup/rollup-darwin-x64": {
1313
+ "version": "4.55.3",
1314
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.3.tgz",
1315
+ "integrity": "sha512-FYZ4iVunXxtT+CZqQoPVwPhH7549e/Gy7PIRRtq4t5f/vt54pX6eG9ebttRH6QSH7r/zxAFA4EZGlQ0h0FvXiA==",
1316
+ "cpu": [
1317
+ "x64"
1318
+ ],
1319
+ "license": "MIT",
1320
+ "optional": true,
1321
+ "os": [
1322
+ "darwin"
1323
+ ]
1324
+ },
1325
+ "node_modules/@rollup/rollup-freebsd-arm64": {
1326
+ "version": "4.55.3",
1327
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.3.tgz",
1328
+ "integrity": "sha512-M/mwDCJ4wLsIgyxv2Lj7Len+UMHd4zAXu4GQ2UaCdksStglWhP61U3uowkaYBQBhVoNpwx5Hputo8eSqM7K82Q==",
1329
+ "cpu": [
1330
+ "arm64"
1331
+ ],
1332
+ "license": "MIT",
1333
+ "optional": true,
1334
+ "os": [
1335
+ "freebsd"
1336
+ ]
1337
+ },
1338
+ "node_modules/@rollup/rollup-freebsd-x64": {
1339
+ "version": "4.55.3",
1340
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.3.tgz",
1341
+ "integrity": "sha512-5jZT2c7jBCrMegKYTYTpni8mg8y3uY8gzeq2ndFOANwNuC/xJbVAoGKR9LhMDA0H3nIhvaqUoBEuJoICBudFrA==",
1342
+ "cpu": [
1343
+ "x64"
1344
+ ],
1345
+ "license": "MIT",
1346
+ "optional": true,
1347
+ "os": [
1348
+ "freebsd"
1349
+ ]
1350
+ },
1351
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
1352
+ "version": "4.55.3",
1353
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.3.tgz",
1354
+ "integrity": "sha512-YeGUhkN1oA+iSPzzhEjVPS29YbViOr8s4lSsFaZKLHswgqP911xx25fPOyE9+khmN6W4VeM0aevbDp4kkEoHiA==",
1355
+ "cpu": [
1356
+ "arm"
1357
+ ],
1358
+ "license": "MIT",
1359
+ "optional": true,
1360
+ "os": [
1361
+ "linux"
1362
+ ]
1363
+ },
1364
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
1365
+ "version": "4.55.3",
1366
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.3.tgz",
1367
+ "integrity": "sha512-eo0iOIOvcAlWB3Z3eh8pVM8hZ0oVkK3AjEM9nSrkSug2l15qHzF3TOwT0747omI6+CJJvl7drwZepT+re6Fy/w==",
1368
+ "cpu": [
1369
+ "arm"
1370
+ ],
1371
+ "license": "MIT",
1372
+ "optional": true,
1373
+ "os": [
1374
+ "linux"
1375
+ ]
1376
+ },
1377
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
1378
+ "version": "4.55.3",
1379
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.3.tgz",
1380
+ "integrity": "sha512-DJay3ep76bKUDImmn//W5SvpjRN5LmK/ntWyeJs/dcnwiiHESd3N4uteK9FDLf0S0W8E6Y0sVRXpOCoQclQqNg==",
1381
+ "cpu": [
1382
+ "arm64"
1383
+ ],
1384
+ "license": "MIT",
1385
+ "optional": true,
1386
+ "os": [
1387
+ "linux"
1388
+ ]
1389
+ },
1390
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
1391
+ "version": "4.55.3",
1392
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.3.tgz",
1393
+ "integrity": "sha512-BKKWQkY2WgJ5MC/ayvIJTHjy0JUGb5efaHCUiG/39sSUvAYRBaO3+/EK0AZT1RF3pSj86O24GLLik9mAYu0IJg==",
1394
+ "cpu": [
1395
+ "arm64"
1396
+ ],
1397
+ "license": "MIT",
1398
+ "optional": true,
1399
+ "os": [
1400
+ "linux"
1401
+ ]
1402
+ },
1403
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
1404
+ "version": "4.55.3",
1405
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.3.tgz",
1406
+ "integrity": "sha512-Q9nVlWtKAG7ISW80OiZGxTr6rYtyDSkauHUtvkQI6TNOJjFvpj4gcH+KaJihqYInnAzEEUetPQubRwHef4exVg==",
1407
+ "cpu": [
1408
+ "loong64"
1409
+ ],
1410
+ "license": "MIT",
1411
+ "optional": true,
1412
+ "os": [
1413
+ "linux"
1414
+ ]
1415
+ },
1416
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
1417
+ "version": "4.55.3",
1418
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.3.tgz",
1419
+ "integrity": "sha512-2H5LmhzrpC4fFRNwknzmmTvvyJPHwESoJgyReXeFoYYuIDfBhP29TEXOkCJE/KxHi27mj7wDUClNq78ue3QEBQ==",
1420
+ "cpu": [
1421
+ "loong64"
1422
+ ],
1423
+ "license": "MIT",
1424
+ "optional": true,
1425
+ "os": [
1426
+ "linux"
1427
+ ]
1428
+ },
1429
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
1430
+ "version": "4.55.3",
1431
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.3.tgz",
1432
+ "integrity": "sha512-9S542V0ie9LCTznPYlvaeySwBeIEa7rDBgLHKZ5S9DBgcqdJYburabm8TqiqG6mrdTzfV5uttQRHcbKff9lWtA==",
1433
+ "cpu": [
1434
+ "ppc64"
1435
+ ],
1436
+ "license": "MIT",
1437
+ "optional": true,
1438
+ "os": [
1439
+ "linux"
1440
+ ]
1441
+ },
1442
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
1443
+ "version": "4.55.3",
1444
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.3.tgz",
1445
+ "integrity": "sha512-ukxw+YH3XXpcezLgbJeasgxyTbdpnNAkrIlFGDl7t+pgCxZ89/6n1a+MxlY7CegU+nDgrgdqDelPRNQ/47zs0g==",
1446
+ "cpu": [
1447
+ "ppc64"
1448
+ ],
1449
+ "license": "MIT",
1450
+ "optional": true,
1451
+ "os": [
1452
+ "linux"
1453
+ ]
1454
+ },
1455
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
1456
+ "version": "4.55.3",
1457
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.3.tgz",
1458
+ "integrity": "sha512-Iauw9UsTTvlF++FhghFJjqYxyXdggXsOqGpFBylaRopVpcbfyIIsNvkf9oGwfgIcf57z3m8+/oSYTo6HutBFNw==",
1459
+ "cpu": [
1460
+ "riscv64"
1461
+ ],
1462
+ "license": "MIT",
1463
+ "optional": true,
1464
+ "os": [
1465
+ "linux"
1466
+ ]
1467
+ },
1468
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
1469
+ "version": "4.55.3",
1470
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.3.tgz",
1471
+ "integrity": "sha512-3OqKAHSEQXKdq9mQ4eajqUgNIK27VZPW3I26EP8miIzuKzCJ3aW3oEn2pzF+4/Hj/Moc0YDsOtBgT5bZ56/vcA==",
1472
+ "cpu": [
1473
+ "riscv64"
1474
+ ],
1475
+ "license": "MIT",
1476
+ "optional": true,
1477
+ "os": [
1478
+ "linux"
1479
+ ]
1480
+ },
1481
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
1482
+ "version": "4.55.3",
1483
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.3.tgz",
1484
+ "integrity": "sha512-0CM8dSVzVIaqMcXIFej8zZrSFLnGrAE8qlNbbHfTw1EEPnFTg1U1ekI0JdzjPyzSfUsHWtodilQQG/RA55berA==",
1485
+ "cpu": [
1486
+ "s390x"
1487
+ ],
1488
+ "license": "MIT",
1489
+ "optional": true,
1490
+ "os": [
1491
+ "linux"
1492
+ ]
1493
+ },
1494
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
1495
+ "version": "4.55.3",
1496
+ "cpu": [
1497
+ "x64"
1498
+ ],
1499
+ "license": "MIT",
1500
+ "optional": true,
1501
+ "os": [
1502
+ "linux"
1503
+ ]
1504
+ },
1505
+ "node_modules/@rollup/rollup-linux-x64-musl": {
1506
+ "version": "4.55.3",
1507
+ "cpu": [
1508
+ "x64"
1509
+ ],
1510
+ "license": "MIT",
1511
+ "optional": true,
1512
+ "os": [
1513
+ "linux"
1514
+ ]
1515
+ },
1516
+ "node_modules/@rollup/rollup-openbsd-x64": {
1517
+ "version": "4.55.3",
1518
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.3.tgz",
1519
+ "integrity": "sha512-u5KsqxOxjEeIbn7bUK1MPM34jrnPwjeqgyin4/N6e/KzXKfpE9Mi0nCxcQjaM9lLmPcHmn/xx1yOjgTMtu1jWQ==",
1520
+ "cpu": [
1521
+ "x64"
1522
+ ],
1523
+ "license": "MIT",
1524
+ "optional": true,
1525
+ "os": [
1526
+ "openbsd"
1527
+ ]
1528
+ },
1529
+ "node_modules/@rollup/rollup-openharmony-arm64": {
1530
+ "version": "4.55.3",
1531
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.3.tgz",
1532
+ "integrity": "sha512-vo54aXwjpTtsAnb3ca7Yxs9t2INZg7QdXN/7yaoG7nPGbOBXYXQY41Km+S1Ov26vzOAzLcAjmMdjyEqS1JkVhw==",
1533
+ "cpu": [
1534
+ "arm64"
1535
+ ],
1536
+ "license": "MIT",
1537
+ "optional": true,
1538
+ "os": [
1539
+ "openharmony"
1540
+ ]
1541
+ },
1542
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
1543
+ "version": "4.55.3",
1544
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.3.tgz",
1545
+ "integrity": "sha512-HI+PIVZ+m+9AgpnY3pt6rinUdRYrGHvmVdsNQ4odNqQ/eRF78DVpMR7mOq7nW06QxpczibwBmeQzB68wJ+4W4A==",
1546
+ "cpu": [
1547
+ "arm64"
1548
+ ],
1549
+ "license": "MIT",
1550
+ "optional": true,
1551
+ "os": [
1552
+ "win32"
1553
+ ]
1554
+ },
1555
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
1556
+ "version": "4.55.3",
1557
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.3.tgz",
1558
+ "integrity": "sha512-vRByotbdMo3Wdi+8oC2nVxtc3RkkFKrGaok+a62AT8lz/YBuQjaVYAS5Zcs3tPzW43Vsf9J0wehJbUY5xRSekA==",
1559
+ "cpu": [
1560
+ "ia32"
1561
+ ],
1562
+ "license": "MIT",
1563
+ "optional": true,
1564
+ "os": [
1565
+ "win32"
1566
+ ]
1567
+ },
1568
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
1569
+ "version": "4.55.3",
1570
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.3.tgz",
1571
+ "integrity": "sha512-POZHq7UeuzMJljC5NjKi8vKMFN6/5EOqcX1yGntNLp7rUTpBAXQ1hW8kWPFxYLv07QMcNM75xqVLGPWQq6TKFA==",
1572
+ "cpu": [
1573
+ "x64"
1574
+ ],
1575
+ "license": "MIT",
1576
+ "optional": true,
1577
+ "os": [
1578
+ "win32"
1579
+ ]
1580
+ },
1581
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
1582
+ "version": "4.55.3",
1583
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.3.tgz",
1584
+ "integrity": "sha512-aPFONczE4fUFKNXszdvnd2GqKEYQdV5oEsIbKPujJmWlCI9zEsv1Otig8RKK+X9bed9gFUN6LAeN4ZcNuu4zjg==",
1585
+ "cpu": [
1586
+ "x64"
1587
+ ],
1588
+ "license": "MIT",
1589
+ "optional": true,
1590
+ "os": [
1591
+ "win32"
1592
+ ]
1593
+ },
1594
+ "node_modules/@shikijs/core": {
1595
+ "version": "3.21.0",
1596
+ "license": "MIT",
1597
+ "dependencies": {
1598
+ "@shikijs/types": "3.21.0",
1599
+ "@shikijs/vscode-textmate": "^10.0.2",
1600
+ "@types/hast": "^3.0.4",
1601
+ "hast-util-to-html": "^9.0.5"
1602
+ }
1603
+ },
1604
+ "node_modules/@shikijs/engine-javascript": {
1605
+ "version": "3.21.0",
1606
+ "license": "MIT",
1607
+ "dependencies": {
1608
+ "@shikijs/types": "3.21.0",
1609
+ "@shikijs/vscode-textmate": "^10.0.2",
1610
+ "oniguruma-to-es": "^4.3.4"
1611
+ }
1612
+ },
1613
+ "node_modules/@shikijs/engine-oniguruma": {
1614
+ "version": "3.21.0",
1615
+ "license": "MIT",
1616
+ "dependencies": {
1617
+ "@shikijs/types": "3.21.0",
1618
+ "@shikijs/vscode-textmate": "^10.0.2"
1619
+ }
1620
+ },
1621
+ "node_modules/@shikijs/langs": {
1622
+ "version": "3.21.0",
1623
+ "license": "MIT",
1624
+ "dependencies": {
1625
+ "@shikijs/types": "3.21.0"
1626
+ }
1627
+ },
1628
+ "node_modules/@shikijs/themes": {
1629
+ "version": "3.21.0",
1630
+ "license": "MIT",
1631
+ "dependencies": {
1632
+ "@shikijs/types": "3.21.0"
1633
+ }
1634
+ },
1635
+ "node_modules/@shikijs/types": {
1636
+ "version": "3.21.0",
1637
+ "license": "MIT",
1638
+ "dependencies": {
1639
+ "@shikijs/vscode-textmate": "^10.0.2",
1640
+ "@types/hast": "^3.0.4"
1641
+ }
1642
+ },
1643
+ "node_modules/@shikijs/vscode-textmate": {
1644
+ "version": "10.0.2",
1645
+ "license": "MIT"
1646
+ },
1647
+ "node_modules/@types/debug": {
1648
+ "version": "4.1.12",
1649
+ "license": "MIT",
1650
+ "dependencies": {
1651
+ "@types/ms": "*"
1652
+ }
1653
+ },
1654
+ "node_modules/@types/estree": {
1655
+ "version": "1.0.8",
1656
+ "license": "MIT"
1657
+ },
1658
+ "node_modules/@types/estree-jsx": {
1659
+ "version": "1.0.5",
1660
+ "license": "MIT",
1661
+ "dependencies": {
1662
+ "@types/estree": "*"
1663
+ }
1664
+ },
1665
+ "node_modules/@types/hast": {
1666
+ "version": "3.0.4",
1667
+ "license": "MIT",
1668
+ "dependencies": {
1669
+ "@types/unist": "*"
1670
+ }
1671
+ },
1672
+ "node_modules/@types/js-yaml": {
1673
+ "version": "4.0.9",
1674
+ "license": "MIT"
1675
+ },
1676
+ "node_modules/@types/mdast": {
1677
+ "version": "4.0.4",
1678
+ "license": "MIT",
1679
+ "dependencies": {
1680
+ "@types/unist": "*"
1681
+ }
1682
+ },
1683
+ "node_modules/@types/mdx": {
1684
+ "version": "2.0.13",
1685
+ "license": "MIT"
1686
+ },
1687
+ "node_modules/@types/ms": {
1688
+ "version": "2.1.0",
1689
+ "license": "MIT"
1690
+ },
1691
+ "node_modules/@types/nlcst": {
1692
+ "version": "2.0.3",
1693
+ "license": "MIT",
1694
+ "dependencies": {
1695
+ "@types/unist": "*"
1696
+ }
1697
+ },
1698
+ "node_modules/@types/node": {
1699
+ "version": "26.1.1",
1700
+ "resolved": "https://registry.npmmirror.com/@types/node/-/node-26.1.1.tgz",
1701
+ "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==",
1702
+ "license": "MIT",
1703
+ "dependencies": {
1704
+ "undici-types": "~8.3.0"
1705
+ }
1706
+ },
1707
+ "node_modules/@types/sax": {
1708
+ "version": "1.2.7",
1709
+ "license": "MIT",
1710
+ "dependencies": {
1711
+ "@types/node": "*"
1712
+ }
1713
+ },
1714
+ "node_modules/@types/unist": {
1715
+ "version": "3.0.3",
1716
+ "license": "MIT"
1717
+ },
1718
+ "node_modules/@ungap/structured-clone": {
1719
+ "version": "1.3.0",
1720
+ "license": "ISC"
1721
+ },
1722
+ "node_modules/acorn": {
1723
+ "version": "8.15.0",
1724
+ "license": "MIT",
1725
+ "bin": {
1726
+ "acorn": "bin/acorn"
1727
+ },
1728
+ "engines": {
1729
+ "node": ">=0.4.0"
1730
+ }
1731
+ },
1732
+ "node_modules/acorn-jsx": {
1733
+ "version": "5.3.2",
1734
+ "license": "MIT",
1735
+ "peerDependencies": {
1736
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
1737
+ }
1738
+ },
1739
+ "node_modules/ansi-align": {
1740
+ "version": "3.0.1",
1741
+ "license": "ISC",
1742
+ "dependencies": {
1743
+ "string-width": "^4.1.0"
1744
+ }
1745
+ },
1746
+ "node_modules/ansi-align/node_modules/string-width": {
1747
+ "version": "4.2.3",
1748
+ "license": "MIT",
1749
+ "dependencies": {
1750
+ "emoji-regex": "^8.0.0",
1751
+ "is-fullwidth-code-point": "^3.0.0",
1752
+ "strip-ansi": "^6.0.1"
1753
+ },
1754
+ "engines": {
1755
+ "node": ">=8"
1756
+ }
1757
+ },
1758
+ "node_modules/ansi-align/node_modules/string-width/node_modules/emoji-regex": {
1759
+ "version": "8.0.0",
1760
+ "license": "MIT"
1761
+ },
1762
+ "node_modules/ansi-align/node_modules/string-width/node_modules/strip-ansi": {
1763
+ "version": "6.0.1",
1764
+ "license": "MIT",
1765
+ "dependencies": {
1766
+ "ansi-regex": "^5.0.1"
1767
+ },
1768
+ "engines": {
1769
+ "node": ">=8"
1770
+ }
1771
+ },
1772
+ "node_modules/ansi-align/node_modules/string-width/node_modules/strip-ansi/node_modules/ansi-regex": {
1773
+ "version": "5.0.1",
1774
+ "license": "MIT",
1775
+ "engines": {
1776
+ "node": ">=8"
1777
+ }
1778
+ },
1779
+ "node_modules/ansi-regex": {
1780
+ "version": "6.2.2",
1781
+ "license": "MIT",
1782
+ "engines": {
1783
+ "node": ">=12"
1784
+ },
1785
+ "funding": {
1786
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
1787
+ }
1788
+ },
1789
+ "node_modules/ansi-styles": {
1790
+ "version": "6.2.3",
1791
+ "license": "MIT",
1792
+ "engines": {
1793
+ "node": ">=12"
1794
+ },
1795
+ "funding": {
1796
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1797
+ }
1798
+ },
1799
+ "node_modules/anymatch": {
1800
+ "version": "3.1.3",
1801
+ "license": "ISC",
1802
+ "dependencies": {
1803
+ "normalize-path": "^3.0.0",
1804
+ "picomatch": "^2.0.4"
1805
+ },
1806
+ "engines": {
1807
+ "node": ">= 8"
1808
+ }
1809
+ },
1810
+ "node_modules/anymatch/node_modules/picomatch": {
1811
+ "version": "2.3.1",
1812
+ "license": "MIT",
1813
+ "engines": {
1814
+ "node": ">=8.6"
1815
+ },
1816
+ "funding": {
1817
+ "url": "https://github.com/sponsors/jonschlinkert"
1818
+ }
1819
+ },
1820
+ "node_modules/arg": {
1821
+ "version": "5.0.2",
1822
+ "license": "MIT"
1823
+ },
1824
+ "node_modules/argparse": {
1825
+ "version": "2.0.1",
1826
+ "license": "Python-2.0"
1827
+ },
1828
+ "node_modules/aria-query": {
1829
+ "version": "5.3.2",
1830
+ "license": "Apache-2.0",
1831
+ "engines": {
1832
+ "node": ">= 0.4"
1833
+ }
1834
+ },
1835
+ "node_modules/array-iterate": {
1836
+ "version": "2.0.1",
1837
+ "license": "MIT",
1838
+ "funding": {
1839
+ "type": "github",
1840
+ "url": "https://github.com/sponsors/wooorm"
1841
+ }
1842
+ },
1843
+ "node_modules/astring": {
1844
+ "version": "1.9.0",
1845
+ "license": "MIT",
1846
+ "bin": {
1847
+ "astring": "bin/astring"
1848
+ }
1849
+ },
1850
+ "node_modules/astro": {
1851
+ "version": "5.16.12",
1852
+ "license": "MIT",
1853
+ "dependencies": {
1854
+ "@astrojs/compiler": "^2.13.0",
1855
+ "@astrojs/internal-helpers": "0.7.5",
1856
+ "@astrojs/markdown-remark": "6.3.10",
1857
+ "@astrojs/telemetry": "3.3.0",
1858
+ "@capsizecss/unpack": "^4.0.0",
1859
+ "@oslojs/encoding": "^1.1.0",
1860
+ "@rollup/pluginutils": "^5.3.0",
1861
+ "acorn": "^8.15.0",
1862
+ "aria-query": "^5.3.2",
1863
+ "axobject-query": "^4.1.0",
1864
+ "boxen": "8.0.1",
1865
+ "ci-info": "^4.3.1",
1866
+ "clsx": "^2.1.1",
1867
+ "common-ancestor-path": "^1.0.1",
1868
+ "cookie": "^1.1.1",
1869
+ "cssesc": "^3.0.0",
1870
+ "debug": "^4.4.3",
1871
+ "deterministic-object-hash": "^2.0.2",
1872
+ "devalue": "^5.6.2",
1873
+ "diff": "^8.0.3",
1874
+ "dlv": "^1.1.3",
1875
+ "dset": "^3.1.4",
1876
+ "es-module-lexer": "^1.7.0",
1877
+ "esbuild": "^0.25.0",
1878
+ "estree-walker": "^3.0.3",
1879
+ "flattie": "^1.1.1",
1880
+ "fontace": "~0.4.0",
1881
+ "github-slugger": "^2.0.0",
1882
+ "html-escaper": "3.0.3",
1883
+ "http-cache-semantics": "^4.2.0",
1884
+ "import-meta-resolve": "^4.2.0",
1885
+ "js-yaml": "^4.1.1",
1886
+ "magic-string": "^0.30.21",
1887
+ "magicast": "^0.5.1",
1888
+ "mrmime": "^2.0.1",
1889
+ "neotraverse": "^0.6.18",
1890
+ "p-limit": "^6.2.0",
1891
+ "p-queue": "^8.1.1",
1892
+ "package-manager-detector": "^1.6.0",
1893
+ "piccolore": "^0.1.3",
1894
+ "picomatch": "^4.0.3",
1895
+ "prompts": "^2.4.2",
1896
+ "rehype": "^13.0.2",
1897
+ "semver": "^7.7.3",
1898
+ "shiki": "^3.21.0",
1899
+ "smol-toml": "^1.6.0",
1900
+ "svgo": "^4.0.0",
1901
+ "tinyexec": "^1.0.2",
1902
+ "tinyglobby": "^0.2.15",
1903
+ "tsconfck": "^3.1.6",
1904
+ "ultrahtml": "^1.6.0",
1905
+ "unifont": "~0.7.3",
1906
+ "unist-util-visit": "^5.0.0",
1907
+ "unstorage": "^1.17.4",
1908
+ "vfile": "^6.0.3",
1909
+ "vite": "^6.4.1",
1910
+ "vitefu": "^1.1.1",
1911
+ "xxhash-wasm": "^1.1.0",
1912
+ "yargs-parser": "^21.1.1",
1913
+ "yocto-spinner": "^0.2.3",
1914
+ "zod": "^3.25.76",
1915
+ "zod-to-json-schema": "^3.25.1",
1916
+ "zod-to-ts": "^1.2.0"
1917
+ },
1918
+ "bin": {
1919
+ "astro": "astro.js"
1920
+ },
1921
+ "engines": {
1922
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0",
1923
+ "npm": ">=9.6.5",
1924
+ "pnpm": ">=7.1.0"
1925
+ },
1926
+ "funding": {
1927
+ "type": "opencollective",
1928
+ "url": "https://opencollective.com/astrodotbuild"
1929
+ },
1930
+ "optionalDependencies": {
1931
+ "sharp": "^0.34.0"
1932
+ }
1933
+ },
1934
+ "node_modules/astro-expressive-code": {
1935
+ "version": "0.41.6",
1936
+ "license": "MIT",
1937
+ "dependencies": {
1938
+ "rehype-expressive-code": "^0.41.6"
1939
+ },
1940
+ "peerDependencies": {
1941
+ "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta"
1942
+ }
1943
+ },
1944
+ "node_modules/axobject-query": {
1945
+ "version": "4.1.0",
1946
+ "license": "Apache-2.0",
1947
+ "engines": {
1948
+ "node": ">= 0.4"
1949
+ }
1950
+ },
1951
+ "node_modules/bail": {
1952
+ "version": "2.0.2",
1953
+ "license": "MIT",
1954
+ "funding": {
1955
+ "type": "github",
1956
+ "url": "https://github.com/sponsors/wooorm"
1957
+ }
1958
+ },
1959
+ "node_modules/base-64": {
1960
+ "version": "1.0.0",
1961
+ "license": "MIT"
1962
+ },
1963
+ "node_modules/bcp-47": {
1964
+ "version": "2.1.0",
1965
+ "license": "MIT",
1966
+ "dependencies": {
1967
+ "is-alphabetical": "^2.0.0",
1968
+ "is-alphanumerical": "^2.0.0",
1969
+ "is-decimal": "^2.0.0"
1970
+ },
1971
+ "funding": {
1972
+ "type": "github",
1973
+ "url": "https://github.com/sponsors/wooorm"
1974
+ }
1975
+ },
1976
+ "node_modules/bcp-47-match": {
1977
+ "version": "2.0.3",
1978
+ "license": "MIT",
1979
+ "funding": {
1980
+ "type": "github",
1981
+ "url": "https://github.com/sponsors/wooorm"
1982
+ }
1983
+ },
1984
+ "node_modules/boolbase": {
1985
+ "version": "1.0.0",
1986
+ "license": "ISC"
1987
+ },
1988
+ "node_modules/boxen": {
1989
+ "version": "8.0.1",
1990
+ "license": "MIT",
1991
+ "dependencies": {
1992
+ "ansi-align": "^3.0.1",
1993
+ "camelcase": "^8.0.0",
1994
+ "chalk": "^5.3.0",
1995
+ "cli-boxes": "^3.0.0",
1996
+ "string-width": "^7.2.0",
1997
+ "type-fest": "^4.21.0",
1998
+ "widest-line": "^5.0.0",
1999
+ "wrap-ansi": "^9.0.0"
2000
+ },
2001
+ "engines": {
2002
+ "node": ">=18"
2003
+ },
2004
+ "funding": {
2005
+ "url": "https://github.com/sponsors/sindresorhus"
2006
+ }
2007
+ },
2008
+ "node_modules/camelcase": {
2009
+ "version": "8.0.0",
2010
+ "license": "MIT",
2011
+ "engines": {
2012
+ "node": ">=16"
2013
+ },
2014
+ "funding": {
2015
+ "url": "https://github.com/sponsors/sindresorhus"
2016
+ }
2017
+ },
2018
+ "node_modules/ccount": {
2019
+ "version": "2.0.1",
2020
+ "license": "MIT",
2021
+ "funding": {
2022
+ "type": "github",
2023
+ "url": "https://github.com/sponsors/wooorm"
2024
+ }
2025
+ },
2026
+ "node_modules/chalk": {
2027
+ "version": "5.6.2",
2028
+ "license": "MIT",
2029
+ "engines": {
2030
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
2031
+ },
2032
+ "funding": {
2033
+ "url": "https://github.com/chalk/chalk?sponsor=1"
2034
+ }
2035
+ },
2036
+ "node_modules/character-entities": {
2037
+ "version": "2.0.2",
2038
+ "license": "MIT",
2039
+ "funding": {
2040
+ "type": "github",
2041
+ "url": "https://github.com/sponsors/wooorm"
2042
+ }
2043
+ },
2044
+ "node_modules/character-entities-html4": {
2045
+ "version": "2.1.0",
2046
+ "license": "MIT",
2047
+ "funding": {
2048
+ "type": "github",
2049
+ "url": "https://github.com/sponsors/wooorm"
2050
+ }
2051
+ },
2052
+ "node_modules/character-entities-legacy": {
2053
+ "version": "3.0.0",
2054
+ "license": "MIT",
2055
+ "funding": {
2056
+ "type": "github",
2057
+ "url": "https://github.com/sponsors/wooorm"
2058
+ }
2059
+ },
2060
+ "node_modules/character-reference-invalid": {
2061
+ "version": "2.0.1",
2062
+ "license": "MIT",
2063
+ "funding": {
2064
+ "type": "github",
2065
+ "url": "https://github.com/sponsors/wooorm"
2066
+ }
2067
+ },
2068
+ "node_modules/chokidar": {
2069
+ "version": "5.0.0",
2070
+ "license": "MIT",
2071
+ "dependencies": {
2072
+ "readdirp": "^5.0.0"
2073
+ },
2074
+ "engines": {
2075
+ "node": ">= 20.19.0"
2076
+ },
2077
+ "funding": {
2078
+ "url": "https://paulmillr.com/funding/"
2079
+ }
2080
+ },
2081
+ "node_modules/ci-info": {
2082
+ "version": "4.3.1",
2083
+ "funding": [
2084
+ {
2085
+ "type": "github",
2086
+ "url": "https://github.com/sponsors/sibiraj-s"
2087
+ }
2088
+ ],
2089
+ "license": "MIT",
2090
+ "engines": {
2091
+ "node": ">=8"
2092
+ }
2093
+ },
2094
+ "node_modules/cli-boxes": {
2095
+ "version": "3.0.0",
2096
+ "license": "MIT",
2097
+ "engines": {
2098
+ "node": ">=10"
2099
+ },
2100
+ "funding": {
2101
+ "url": "https://github.com/sponsors/sindresorhus"
2102
+ }
2103
+ },
2104
+ "node_modules/clsx": {
2105
+ "version": "2.1.1",
2106
+ "license": "MIT",
2107
+ "engines": {
2108
+ "node": ">=6"
2109
+ }
2110
+ },
2111
+ "node_modules/collapse-white-space": {
2112
+ "version": "2.1.0",
2113
+ "license": "MIT",
2114
+ "funding": {
2115
+ "type": "github",
2116
+ "url": "https://github.com/sponsors/wooorm"
2117
+ }
2118
+ },
2119
+ "node_modules/comma-separated-tokens": {
2120
+ "version": "2.0.3",
2121
+ "license": "MIT",
2122
+ "funding": {
2123
+ "type": "github",
2124
+ "url": "https://github.com/sponsors/wooorm"
2125
+ }
2126
+ },
2127
+ "node_modules/commander": {
2128
+ "version": "11.1.0",
2129
+ "license": "MIT",
2130
+ "engines": {
2131
+ "node": ">=16"
2132
+ }
2133
+ },
2134
+ "node_modules/common-ancestor-path": {
2135
+ "version": "1.0.1",
2136
+ "license": "ISC"
2137
+ },
2138
+ "node_modules/cookie": {
2139
+ "version": "1.1.1",
2140
+ "license": "MIT",
2141
+ "engines": {
2142
+ "node": ">=18"
2143
+ },
2144
+ "funding": {
2145
+ "type": "opencollective",
2146
+ "url": "https://opencollective.com/express"
2147
+ }
2148
+ },
2149
+ "node_modules/cookie-es": {
2150
+ "version": "1.2.2",
2151
+ "license": "MIT"
2152
+ },
2153
+ "node_modules/crossws": {
2154
+ "version": "0.3.5",
2155
+ "license": "MIT",
2156
+ "dependencies": {
2157
+ "uncrypto": "^0.1.3"
2158
+ }
2159
+ },
2160
+ "node_modules/css-select": {
2161
+ "version": "5.2.2",
2162
+ "license": "BSD-2-Clause",
2163
+ "dependencies": {
2164
+ "boolbase": "^1.0.0",
2165
+ "css-what": "^6.1.0",
2166
+ "domhandler": "^5.0.2",
2167
+ "domutils": "^3.0.1",
2168
+ "nth-check": "^2.0.1"
2169
+ },
2170
+ "funding": {
2171
+ "url": "https://github.com/sponsors/fb55"
2172
+ }
2173
+ },
2174
+ "node_modules/css-selector-parser": {
2175
+ "version": "3.3.0",
2176
+ "funding": [
2177
+ {
2178
+ "type": "github",
2179
+ "url": "https://github.com/sponsors/mdevils"
2180
+ },
2181
+ {
2182
+ "type": "patreon",
2183
+ "url": "https://patreon.com/mdevils"
2184
+ }
2185
+ ],
2186
+ "license": "MIT"
2187
+ },
2188
+ "node_modules/css-tree": {
2189
+ "version": "3.1.0",
2190
+ "license": "MIT",
2191
+ "dependencies": {
2192
+ "mdn-data": "2.12.2",
2193
+ "source-map-js": "^1.0.1"
2194
+ },
2195
+ "engines": {
2196
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
2197
+ }
2198
+ },
2199
+ "node_modules/css-what": {
2200
+ "version": "6.2.2",
2201
+ "license": "BSD-2-Clause",
2202
+ "engines": {
2203
+ "node": ">= 6"
2204
+ },
2205
+ "funding": {
2206
+ "url": "https://github.com/sponsors/fb55"
2207
+ }
2208
+ },
2209
+ "node_modules/cssesc": {
2210
+ "version": "3.0.0",
2211
+ "license": "MIT",
2212
+ "bin": {
2213
+ "cssesc": "bin/cssesc"
2214
+ },
2215
+ "engines": {
2216
+ "node": ">=4"
2217
+ }
2218
+ },
2219
+ "node_modules/csso": {
2220
+ "version": "5.0.5",
2221
+ "license": "MIT",
2222
+ "dependencies": {
2223
+ "css-tree": "~2.2.0"
2224
+ },
2225
+ "engines": {
2226
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
2227
+ "npm": ">=7.0.0"
2228
+ }
2229
+ },
2230
+ "node_modules/csso/node_modules/css-tree": {
2231
+ "version": "2.2.1",
2232
+ "license": "MIT",
2233
+ "dependencies": {
2234
+ "mdn-data": "2.0.28",
2235
+ "source-map-js": "^1.0.1"
2236
+ },
2237
+ "engines": {
2238
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
2239
+ "npm": ">=7.0.0"
2240
+ }
2241
+ },
2242
+ "node_modules/csso/node_modules/css-tree/node_modules/mdn-data": {
2243
+ "version": "2.0.28",
2244
+ "license": "CC0-1.0"
2245
+ },
2246
+ "node_modules/debug": {
2247
+ "version": "4.4.3",
2248
+ "license": "MIT",
2249
+ "dependencies": {
2250
+ "ms": "^2.1.3"
2251
+ },
2252
+ "engines": {
2253
+ "node": ">=6.0"
2254
+ },
2255
+ "peerDependenciesMeta": {
2256
+ "supports-color": {
2257
+ "optional": true
2258
+ }
2259
+ }
2260
+ },
2261
+ "node_modules/decode-named-character-reference": {
2262
+ "version": "1.3.0",
2263
+ "license": "MIT",
2264
+ "dependencies": {
2265
+ "character-entities": "^2.0.0"
2266
+ },
2267
+ "funding": {
2268
+ "type": "github",
2269
+ "url": "https://github.com/sponsors/wooorm"
2270
+ }
2271
+ },
2272
+ "node_modules/defu": {
2273
+ "version": "6.1.4",
2274
+ "license": "MIT"
2275
+ },
2276
+ "node_modules/dequal": {
2277
+ "version": "2.0.3",
2278
+ "license": "MIT",
2279
+ "engines": {
2280
+ "node": ">=6"
2281
+ }
2282
+ },
2283
+ "node_modules/destr": {
2284
+ "version": "2.0.5",
2285
+ "license": "MIT"
2286
+ },
2287
+ "node_modules/detect-libc": {
2288
+ "version": "2.1.2",
2289
+ "license": "Apache-2.0",
2290
+ "engines": {
2291
+ "node": ">=8"
2292
+ }
2293
+ },
2294
+ "node_modules/deterministic-object-hash": {
2295
+ "version": "2.0.2",
2296
+ "license": "MIT",
2297
+ "dependencies": {
2298
+ "base-64": "^1.0.0"
2299
+ },
2300
+ "engines": {
2301
+ "node": ">=18"
2302
+ }
2303
+ },
2304
+ "node_modules/devalue": {
2305
+ "version": "5.6.2",
2306
+ "license": "MIT"
2307
+ },
2308
+ "node_modules/devlop": {
2309
+ "version": "1.1.0",
2310
+ "license": "MIT",
2311
+ "dependencies": {
2312
+ "dequal": "^2.0.0"
2313
+ },
2314
+ "funding": {
2315
+ "type": "github",
2316
+ "url": "https://github.com/sponsors/wooorm"
2317
+ }
2318
+ },
2319
+ "node_modules/diff": {
2320
+ "version": "8.0.3",
2321
+ "license": "BSD-3-Clause",
2322
+ "engines": {
2323
+ "node": ">=0.3.1"
2324
+ }
2325
+ },
2326
+ "node_modules/direction": {
2327
+ "version": "2.0.1",
2328
+ "license": "MIT",
2329
+ "bin": {
2330
+ "direction": "cli.js"
2331
+ },
2332
+ "funding": {
2333
+ "type": "github",
2334
+ "url": "https://github.com/sponsors/wooorm"
2335
+ }
2336
+ },
2337
+ "node_modules/dlv": {
2338
+ "version": "1.1.3",
2339
+ "license": "MIT"
2340
+ },
2341
+ "node_modules/dom-serializer": {
2342
+ "version": "2.0.0",
2343
+ "license": "MIT",
2344
+ "dependencies": {
2345
+ "domelementtype": "^2.3.0",
2346
+ "domhandler": "^5.0.2",
2347
+ "entities": "^4.2.0"
2348
+ },
2349
+ "funding": {
2350
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
2351
+ }
2352
+ },
2353
+ "node_modules/dom-serializer/node_modules/entities": {
2354
+ "version": "4.5.0",
2355
+ "license": "BSD-2-Clause",
2356
+ "engines": {
2357
+ "node": ">=0.12"
2358
+ },
2359
+ "funding": {
2360
+ "url": "https://github.com/fb55/entities?sponsor=1"
2361
+ }
2362
+ },
2363
+ "node_modules/domelementtype": {
2364
+ "version": "2.3.0",
2365
+ "funding": [
2366
+ {
2367
+ "type": "github",
2368
+ "url": "https://github.com/sponsors/fb55"
2369
+ }
2370
+ ],
2371
+ "license": "BSD-2-Clause"
2372
+ },
2373
+ "node_modules/domhandler": {
2374
+ "version": "5.0.3",
2375
+ "license": "BSD-2-Clause",
2376
+ "dependencies": {
2377
+ "domelementtype": "^2.3.0"
2378
+ },
2379
+ "engines": {
2380
+ "node": ">= 4"
2381
+ },
2382
+ "funding": {
2383
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
2384
+ }
2385
+ },
2386
+ "node_modules/domutils": {
2387
+ "version": "3.2.2",
2388
+ "license": "BSD-2-Clause",
2389
+ "dependencies": {
2390
+ "dom-serializer": "^2.0.0",
2391
+ "domelementtype": "^2.3.0",
2392
+ "domhandler": "^5.0.3"
2393
+ },
2394
+ "funding": {
2395
+ "url": "https://github.com/fb55/domutils?sponsor=1"
2396
+ }
2397
+ },
2398
+ "node_modules/dset": {
2399
+ "version": "3.1.4",
2400
+ "license": "MIT",
2401
+ "engines": {
2402
+ "node": ">=4"
2403
+ }
2404
+ },
2405
+ "node_modules/emoji-regex": {
2406
+ "version": "10.6.0",
2407
+ "license": "MIT"
2408
+ },
2409
+ "node_modules/entities": {
2410
+ "version": "6.0.1",
2411
+ "license": "BSD-2-Clause",
2412
+ "engines": {
2413
+ "node": ">=0.12"
2414
+ },
2415
+ "funding": {
2416
+ "url": "https://github.com/fb55/entities?sponsor=1"
2417
+ }
2418
+ },
2419
+ "node_modules/es-module-lexer": {
2420
+ "version": "1.7.0",
2421
+ "license": "MIT"
2422
+ },
2423
+ "node_modules/esast-util-from-estree": {
2424
+ "version": "2.0.0",
2425
+ "license": "MIT",
2426
+ "dependencies": {
2427
+ "@types/estree-jsx": "^1.0.0",
2428
+ "devlop": "^1.0.0",
2429
+ "estree-util-visit": "^2.0.0",
2430
+ "unist-util-position-from-estree": "^2.0.0"
2431
+ },
2432
+ "funding": {
2433
+ "type": "opencollective",
2434
+ "url": "https://opencollective.com/unified"
2435
+ }
2436
+ },
2437
+ "node_modules/esast-util-from-js": {
2438
+ "version": "2.0.1",
2439
+ "license": "MIT",
2440
+ "dependencies": {
2441
+ "@types/estree-jsx": "^1.0.0",
2442
+ "acorn": "^8.0.0",
2443
+ "esast-util-from-estree": "^2.0.0",
2444
+ "vfile-message": "^4.0.0"
2445
+ },
2446
+ "funding": {
2447
+ "type": "opencollective",
2448
+ "url": "https://opencollective.com/unified"
2449
+ }
2450
+ },
2451
+ "node_modules/esbuild": {
2452
+ "version": "0.25.12",
2453
+ "hasInstallScript": true,
2454
+ "license": "MIT",
2455
+ "bin": {
2456
+ "esbuild": "bin/esbuild"
2457
+ },
2458
+ "engines": {
2459
+ "node": ">=18"
2460
+ },
2461
+ "optionalDependencies": {
2462
+ "@esbuild/aix-ppc64": "0.25.12",
2463
+ "@esbuild/android-arm": "0.25.12",
2464
+ "@esbuild/android-arm64": "0.25.12",
2465
+ "@esbuild/android-x64": "0.25.12",
2466
+ "@esbuild/darwin-arm64": "0.25.12",
2467
+ "@esbuild/darwin-x64": "0.25.12",
2468
+ "@esbuild/freebsd-arm64": "0.25.12",
2469
+ "@esbuild/freebsd-x64": "0.25.12",
2470
+ "@esbuild/linux-arm": "0.25.12",
2471
+ "@esbuild/linux-arm64": "0.25.12",
2472
+ "@esbuild/linux-ia32": "0.25.12",
2473
+ "@esbuild/linux-loong64": "0.25.12",
2474
+ "@esbuild/linux-mips64el": "0.25.12",
2475
+ "@esbuild/linux-ppc64": "0.25.12",
2476
+ "@esbuild/linux-riscv64": "0.25.12",
2477
+ "@esbuild/linux-s390x": "0.25.12",
2478
+ "@esbuild/linux-x64": "0.25.12",
2479
+ "@esbuild/netbsd-arm64": "0.25.12",
2480
+ "@esbuild/netbsd-x64": "0.25.12",
2481
+ "@esbuild/openbsd-arm64": "0.25.12",
2482
+ "@esbuild/openbsd-x64": "0.25.12",
2483
+ "@esbuild/openharmony-arm64": "0.25.12",
2484
+ "@esbuild/sunos-x64": "0.25.12",
2485
+ "@esbuild/win32-arm64": "0.25.12",
2486
+ "@esbuild/win32-ia32": "0.25.12",
2487
+ "@esbuild/win32-x64": "0.25.12"
2488
+ }
2489
+ },
2490
+ "node_modules/escape-string-regexp": {
2491
+ "version": "5.0.0",
2492
+ "license": "MIT",
2493
+ "engines": {
2494
+ "node": ">=12"
2495
+ },
2496
+ "funding": {
2497
+ "url": "https://github.com/sponsors/sindresorhus"
2498
+ }
2499
+ },
2500
+ "node_modules/estree-util-attach-comments": {
2501
+ "version": "3.0.0",
2502
+ "license": "MIT",
2503
+ "dependencies": {
2504
+ "@types/estree": "^1.0.0"
2505
+ },
2506
+ "funding": {
2507
+ "type": "opencollective",
2508
+ "url": "https://opencollective.com/unified"
2509
+ }
2510
+ },
2511
+ "node_modules/estree-util-build-jsx": {
2512
+ "version": "3.0.1",
2513
+ "license": "MIT",
2514
+ "dependencies": {
2515
+ "@types/estree-jsx": "^1.0.0",
2516
+ "devlop": "^1.0.0",
2517
+ "estree-util-is-identifier-name": "^3.0.0",
2518
+ "estree-walker": "^3.0.0"
2519
+ },
2520
+ "funding": {
2521
+ "type": "opencollective",
2522
+ "url": "https://opencollective.com/unified"
2523
+ }
2524
+ },
2525
+ "node_modules/estree-util-is-identifier-name": {
2526
+ "version": "3.0.0",
2527
+ "license": "MIT",
2528
+ "funding": {
2529
+ "type": "opencollective",
2530
+ "url": "https://opencollective.com/unified"
2531
+ }
2532
+ },
2533
+ "node_modules/estree-util-scope": {
2534
+ "version": "1.0.0",
2535
+ "license": "MIT",
2536
+ "dependencies": {
2537
+ "@types/estree": "^1.0.0",
2538
+ "devlop": "^1.0.0"
2539
+ },
2540
+ "funding": {
2541
+ "type": "opencollective",
2542
+ "url": "https://opencollective.com/unified"
2543
+ }
2544
+ },
2545
+ "node_modules/estree-util-to-js": {
2546
+ "version": "2.0.0",
2547
+ "license": "MIT",
2548
+ "dependencies": {
2549
+ "@types/estree-jsx": "^1.0.0",
2550
+ "astring": "^1.8.0",
2551
+ "source-map": "^0.7.0"
2552
+ },
2553
+ "funding": {
2554
+ "type": "opencollective",
2555
+ "url": "https://opencollective.com/unified"
2556
+ }
2557
+ },
2558
+ "node_modules/estree-util-visit": {
2559
+ "version": "2.0.0",
2560
+ "license": "MIT",
2561
+ "dependencies": {
2562
+ "@types/estree-jsx": "^1.0.0",
2563
+ "@types/unist": "^3.0.0"
2564
+ },
2565
+ "funding": {
2566
+ "type": "opencollective",
2567
+ "url": "https://opencollective.com/unified"
2568
+ }
2569
+ },
2570
+ "node_modules/estree-walker": {
2571
+ "version": "3.0.3",
2572
+ "license": "MIT",
2573
+ "dependencies": {
2574
+ "@types/estree": "^1.0.0"
2575
+ }
2576
+ },
2577
+ "node_modules/eventemitter3": {
2578
+ "version": "5.0.4",
2579
+ "license": "MIT"
2580
+ },
2581
+ "node_modules/expressive-code": {
2582
+ "version": "0.41.6",
2583
+ "license": "MIT",
2584
+ "dependencies": {
2585
+ "@expressive-code/core": "^0.41.6",
2586
+ "@expressive-code/plugin-frames": "^0.41.6",
2587
+ "@expressive-code/plugin-shiki": "^0.41.6",
2588
+ "@expressive-code/plugin-text-markers": "^0.41.6"
2589
+ }
2590
+ },
2591
+ "node_modules/extend": {
2592
+ "version": "3.0.2",
2593
+ "license": "MIT"
2594
+ },
2595
+ "node_modules/fdir": {
2596
+ "version": "6.5.0",
2597
+ "license": "MIT",
2598
+ "engines": {
2599
+ "node": ">=12.0.0"
2600
+ },
2601
+ "peerDependencies": {
2602
+ "picomatch": "^3 || ^4"
2603
+ },
2604
+ "peerDependenciesMeta": {
2605
+ "picomatch": {
2606
+ "optional": true
2607
+ }
2608
+ }
2609
+ },
2610
+ "node_modules/flattie": {
2611
+ "version": "1.1.1",
2612
+ "license": "MIT",
2613
+ "engines": {
2614
+ "node": ">=8"
2615
+ }
2616
+ },
2617
+ "node_modules/fontace": {
2618
+ "version": "0.4.0",
2619
+ "license": "MIT",
2620
+ "dependencies": {
2621
+ "fontkitten": "^1.0.0"
2622
+ }
2623
+ },
2624
+ "node_modules/fontkitten": {
2625
+ "version": "1.0.2",
2626
+ "license": "MIT",
2627
+ "dependencies": {
2628
+ "tiny-inflate": "^1.0.3"
2629
+ },
2630
+ "engines": {
2631
+ "node": ">=20"
2632
+ }
2633
+ },
2634
+ "node_modules/fsevents": {
2635
+ "version": "2.3.3",
2636
+ "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
2637
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
2638
+ "hasInstallScript": true,
2639
+ "license": "MIT",
2640
+ "optional": true,
2641
+ "os": [
2642
+ "darwin"
2643
+ ],
2644
+ "engines": {
2645
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
2646
+ }
2647
+ },
2648
+ "node_modules/get-east-asian-width": {
2649
+ "version": "1.4.0",
2650
+ "license": "MIT",
2651
+ "engines": {
2652
+ "node": ">=18"
2653
+ },
2654
+ "funding": {
2655
+ "url": "https://github.com/sponsors/sindresorhus"
2656
+ }
2657
+ },
2658
+ "node_modules/github-slugger": {
2659
+ "version": "2.0.0",
2660
+ "license": "ISC"
2661
+ },
2662
+ "node_modules/h3": {
2663
+ "version": "1.15.5",
2664
+ "license": "MIT",
2665
+ "dependencies": {
2666
+ "cookie-es": "^1.2.2",
2667
+ "crossws": "^0.3.5",
2668
+ "defu": "^6.1.4",
2669
+ "destr": "^2.0.5",
2670
+ "iron-webcrypto": "^1.2.1",
2671
+ "node-mock-http": "^1.0.4",
2672
+ "radix3": "^1.1.2",
2673
+ "ufo": "^1.6.3",
2674
+ "uncrypto": "^0.1.3"
2675
+ }
2676
+ },
2677
+ "node_modules/hast-util-embedded": {
2678
+ "version": "3.0.0",
2679
+ "license": "MIT",
2680
+ "dependencies": {
2681
+ "@types/hast": "^3.0.0",
2682
+ "hast-util-is-element": "^3.0.0"
2683
+ },
2684
+ "funding": {
2685
+ "type": "opencollective",
2686
+ "url": "https://opencollective.com/unified"
2687
+ }
2688
+ },
2689
+ "node_modules/hast-util-format": {
2690
+ "version": "1.1.0",
2691
+ "license": "MIT",
2692
+ "dependencies": {
2693
+ "@types/hast": "^3.0.0",
2694
+ "hast-util-embedded": "^3.0.0",
2695
+ "hast-util-minify-whitespace": "^1.0.0",
2696
+ "hast-util-phrasing": "^3.0.0",
2697
+ "hast-util-whitespace": "^3.0.0",
2698
+ "html-whitespace-sensitive-tag-names": "^3.0.0",
2699
+ "unist-util-visit-parents": "^6.0.0"
2700
+ },
2701
+ "funding": {
2702
+ "type": "opencollective",
2703
+ "url": "https://opencollective.com/unified"
2704
+ }
2705
+ },
2706
+ "node_modules/hast-util-from-html": {
2707
+ "version": "2.0.3",
2708
+ "license": "MIT",
2709
+ "dependencies": {
2710
+ "@types/hast": "^3.0.0",
2711
+ "devlop": "^1.1.0",
2712
+ "hast-util-from-parse5": "^8.0.0",
2713
+ "parse5": "^7.0.0",
2714
+ "vfile": "^6.0.0",
2715
+ "vfile-message": "^4.0.0"
2716
+ },
2717
+ "funding": {
2718
+ "type": "opencollective",
2719
+ "url": "https://opencollective.com/unified"
2720
+ }
2721
+ },
2722
+ "node_modules/hast-util-from-parse5": {
2723
+ "version": "8.0.3",
2724
+ "license": "MIT",
2725
+ "dependencies": {
2726
+ "@types/hast": "^3.0.0",
2727
+ "@types/unist": "^3.0.0",
2728
+ "devlop": "^1.0.0",
2729
+ "hastscript": "^9.0.0",
2730
+ "property-information": "^7.0.0",
2731
+ "vfile": "^6.0.0",
2732
+ "vfile-location": "^5.0.0",
2733
+ "web-namespaces": "^2.0.0"
2734
+ },
2735
+ "funding": {
2736
+ "type": "opencollective",
2737
+ "url": "https://opencollective.com/unified"
2738
+ }
2739
+ },
2740
+ "node_modules/hast-util-has-property": {
2741
+ "version": "3.0.0",
2742
+ "license": "MIT",
2743
+ "dependencies": {
2744
+ "@types/hast": "^3.0.0"
2745
+ },
2746
+ "funding": {
2747
+ "type": "opencollective",
2748
+ "url": "https://opencollective.com/unified"
2749
+ }
2750
+ },
2751
+ "node_modules/hast-util-is-body-ok-link": {
2752
+ "version": "3.0.1",
2753
+ "license": "MIT",
2754
+ "dependencies": {
2755
+ "@types/hast": "^3.0.0"
2756
+ },
2757
+ "funding": {
2758
+ "type": "opencollective",
2759
+ "url": "https://opencollective.com/unified"
2760
+ }
2761
+ },
2762
+ "node_modules/hast-util-is-element": {
2763
+ "version": "3.0.0",
2764
+ "license": "MIT",
2765
+ "dependencies": {
2766
+ "@types/hast": "^3.0.0"
2767
+ },
2768
+ "funding": {
2769
+ "type": "opencollective",
2770
+ "url": "https://opencollective.com/unified"
2771
+ }
2772
+ },
2773
+ "node_modules/hast-util-minify-whitespace": {
2774
+ "version": "1.0.1",
2775
+ "license": "MIT",
2776
+ "dependencies": {
2777
+ "@types/hast": "^3.0.0",
2778
+ "hast-util-embedded": "^3.0.0",
2779
+ "hast-util-is-element": "^3.0.0",
2780
+ "hast-util-whitespace": "^3.0.0",
2781
+ "unist-util-is": "^6.0.0"
2782
+ },
2783
+ "funding": {
2784
+ "type": "opencollective",
2785
+ "url": "https://opencollective.com/unified"
2786
+ }
2787
+ },
2788
+ "node_modules/hast-util-parse-selector": {
2789
+ "version": "4.0.0",
2790
+ "license": "MIT",
2791
+ "dependencies": {
2792
+ "@types/hast": "^3.0.0"
2793
+ },
2794
+ "funding": {
2795
+ "type": "opencollective",
2796
+ "url": "https://opencollective.com/unified"
2797
+ }
2798
+ },
2799
+ "node_modules/hast-util-phrasing": {
2800
+ "version": "3.0.1",
2801
+ "license": "MIT",
2802
+ "dependencies": {
2803
+ "@types/hast": "^3.0.0",
2804
+ "hast-util-embedded": "^3.0.0",
2805
+ "hast-util-has-property": "^3.0.0",
2806
+ "hast-util-is-body-ok-link": "^3.0.0",
2807
+ "hast-util-is-element": "^3.0.0"
2808
+ },
2809
+ "funding": {
2810
+ "type": "opencollective",
2811
+ "url": "https://opencollective.com/unified"
2812
+ }
2813
+ },
2814
+ "node_modules/hast-util-raw": {
2815
+ "version": "9.1.0",
2816
+ "license": "MIT",
2817
+ "dependencies": {
2818
+ "@types/hast": "^3.0.0",
2819
+ "@types/unist": "^3.0.0",
2820
+ "@ungap/structured-clone": "^1.0.0",
2821
+ "hast-util-from-parse5": "^8.0.0",
2822
+ "hast-util-to-parse5": "^8.0.0",
2823
+ "html-void-elements": "^3.0.0",
2824
+ "mdast-util-to-hast": "^13.0.0",
2825
+ "parse5": "^7.0.0",
2826
+ "unist-util-position": "^5.0.0",
2827
+ "unist-util-visit": "^5.0.0",
2828
+ "vfile": "^6.0.0",
2829
+ "web-namespaces": "^2.0.0",
2830
+ "zwitch": "^2.0.0"
2831
+ },
2832
+ "funding": {
2833
+ "type": "opencollective",
2834
+ "url": "https://opencollective.com/unified"
2835
+ }
2836
+ },
2837
+ "node_modules/hast-util-select": {
2838
+ "version": "6.0.4",
2839
+ "license": "MIT",
2840
+ "dependencies": {
2841
+ "@types/hast": "^3.0.0",
2842
+ "@types/unist": "^3.0.0",
2843
+ "bcp-47-match": "^2.0.0",
2844
+ "comma-separated-tokens": "^2.0.0",
2845
+ "css-selector-parser": "^3.0.0",
2846
+ "devlop": "^1.0.0",
2847
+ "direction": "^2.0.0",
2848
+ "hast-util-has-property": "^3.0.0",
2849
+ "hast-util-to-string": "^3.0.0",
2850
+ "hast-util-whitespace": "^3.0.0",
2851
+ "nth-check": "^2.0.0",
2852
+ "property-information": "^7.0.0",
2853
+ "space-separated-tokens": "^2.0.0",
2854
+ "unist-util-visit": "^5.0.0",
2855
+ "zwitch": "^2.0.0"
2856
+ },
2857
+ "funding": {
2858
+ "type": "opencollective",
2859
+ "url": "https://opencollective.com/unified"
2860
+ }
2861
+ },
2862
+ "node_modules/hast-util-to-estree": {
2863
+ "version": "3.1.3",
2864
+ "license": "MIT",
2865
+ "dependencies": {
2866
+ "@types/estree": "^1.0.0",
2867
+ "@types/estree-jsx": "^1.0.0",
2868
+ "@types/hast": "^3.0.0",
2869
+ "comma-separated-tokens": "^2.0.0",
2870
+ "devlop": "^1.0.0",
2871
+ "estree-util-attach-comments": "^3.0.0",
2872
+ "estree-util-is-identifier-name": "^3.0.0",
2873
+ "hast-util-whitespace": "^3.0.0",
2874
+ "mdast-util-mdx-expression": "^2.0.0",
2875
+ "mdast-util-mdx-jsx": "^3.0.0",
2876
+ "mdast-util-mdxjs-esm": "^2.0.0",
2877
+ "property-information": "^7.0.0",
2878
+ "space-separated-tokens": "^2.0.0",
2879
+ "style-to-js": "^1.0.0",
2880
+ "unist-util-position": "^5.0.0",
2881
+ "zwitch": "^2.0.0"
2882
+ },
2883
+ "funding": {
2884
+ "type": "opencollective",
2885
+ "url": "https://opencollective.com/unified"
2886
+ }
2887
+ },
2888
+ "node_modules/hast-util-to-html": {
2889
+ "version": "9.0.5",
2890
+ "license": "MIT",
2891
+ "dependencies": {
2892
+ "@types/hast": "^3.0.0",
2893
+ "@types/unist": "^3.0.0",
2894
+ "ccount": "^2.0.0",
2895
+ "comma-separated-tokens": "^2.0.0",
2896
+ "hast-util-whitespace": "^3.0.0",
2897
+ "html-void-elements": "^3.0.0",
2898
+ "mdast-util-to-hast": "^13.0.0",
2899
+ "property-information": "^7.0.0",
2900
+ "space-separated-tokens": "^2.0.0",
2901
+ "stringify-entities": "^4.0.0",
2902
+ "zwitch": "^2.0.4"
2903
+ },
2904
+ "funding": {
2905
+ "type": "opencollective",
2906
+ "url": "https://opencollective.com/unified"
2907
+ }
2908
+ },
2909
+ "node_modules/hast-util-to-jsx-runtime": {
2910
+ "version": "2.3.6",
2911
+ "license": "MIT",
2912
+ "dependencies": {
2913
+ "@types/estree": "^1.0.0",
2914
+ "@types/hast": "^3.0.0",
2915
+ "@types/unist": "^3.0.0",
2916
+ "comma-separated-tokens": "^2.0.0",
2917
+ "devlop": "^1.0.0",
2918
+ "estree-util-is-identifier-name": "^3.0.0",
2919
+ "hast-util-whitespace": "^3.0.0",
2920
+ "mdast-util-mdx-expression": "^2.0.0",
2921
+ "mdast-util-mdx-jsx": "^3.0.0",
2922
+ "mdast-util-mdxjs-esm": "^2.0.0",
2923
+ "property-information": "^7.0.0",
2924
+ "space-separated-tokens": "^2.0.0",
2925
+ "style-to-js": "^1.0.0",
2926
+ "unist-util-position": "^5.0.0",
2927
+ "vfile-message": "^4.0.0"
2928
+ },
2929
+ "funding": {
2930
+ "type": "opencollective",
2931
+ "url": "https://opencollective.com/unified"
2932
+ }
2933
+ },
2934
+ "node_modules/hast-util-to-parse5": {
2935
+ "version": "8.0.1",
2936
+ "license": "MIT",
2937
+ "dependencies": {
2938
+ "@types/hast": "^3.0.0",
2939
+ "comma-separated-tokens": "^2.0.0",
2940
+ "devlop": "^1.0.0",
2941
+ "property-information": "^7.0.0",
2942
+ "space-separated-tokens": "^2.0.0",
2943
+ "web-namespaces": "^2.0.0",
2944
+ "zwitch": "^2.0.0"
2945
+ },
2946
+ "funding": {
2947
+ "type": "opencollective",
2948
+ "url": "https://opencollective.com/unified"
2949
+ }
2950
+ },
2951
+ "node_modules/hast-util-to-string": {
2952
+ "version": "3.0.1",
2953
+ "license": "MIT",
2954
+ "dependencies": {
2955
+ "@types/hast": "^3.0.0"
2956
+ },
2957
+ "funding": {
2958
+ "type": "opencollective",
2959
+ "url": "https://opencollective.com/unified"
2960
+ }
2961
+ },
2962
+ "node_modules/hast-util-to-text": {
2963
+ "version": "4.0.2",
2964
+ "license": "MIT",
2965
+ "dependencies": {
2966
+ "@types/hast": "^3.0.0",
2967
+ "@types/unist": "^3.0.0",
2968
+ "hast-util-is-element": "^3.0.0",
2969
+ "unist-util-find-after": "^5.0.0"
2970
+ },
2971
+ "funding": {
2972
+ "type": "opencollective",
2973
+ "url": "https://opencollective.com/unified"
2974
+ }
2975
+ },
2976
+ "node_modules/hast-util-whitespace": {
2977
+ "version": "3.0.0",
2978
+ "license": "MIT",
2979
+ "dependencies": {
2980
+ "@types/hast": "^3.0.0"
2981
+ },
2982
+ "funding": {
2983
+ "type": "opencollective",
2984
+ "url": "https://opencollective.com/unified"
2985
+ }
2986
+ },
2987
+ "node_modules/hastscript": {
2988
+ "version": "9.0.1",
2989
+ "license": "MIT",
2990
+ "dependencies": {
2991
+ "@types/hast": "^3.0.0",
2992
+ "comma-separated-tokens": "^2.0.0",
2993
+ "hast-util-parse-selector": "^4.0.0",
2994
+ "property-information": "^7.0.0",
2995
+ "space-separated-tokens": "^2.0.0"
2996
+ },
2997
+ "funding": {
2998
+ "type": "opencollective",
2999
+ "url": "https://opencollective.com/unified"
3000
+ }
3001
+ },
3002
+ "node_modules/html-escaper": {
3003
+ "version": "3.0.3",
3004
+ "license": "MIT"
3005
+ },
3006
+ "node_modules/html-void-elements": {
3007
+ "version": "3.0.0",
3008
+ "license": "MIT",
3009
+ "funding": {
3010
+ "type": "github",
3011
+ "url": "https://github.com/sponsors/wooorm"
3012
+ }
3013
+ },
3014
+ "node_modules/html-whitespace-sensitive-tag-names": {
3015
+ "version": "3.0.1",
3016
+ "license": "MIT",
3017
+ "funding": {
3018
+ "type": "opencollective",
3019
+ "url": "https://opencollective.com/unified"
3020
+ }
3021
+ },
3022
+ "node_modules/http-cache-semantics": {
3023
+ "version": "4.2.0",
3024
+ "license": "BSD-2-Clause"
3025
+ },
3026
+ "node_modules/i18next": {
3027
+ "version": "23.16.8",
3028
+ "funding": [
3029
+ {
3030
+ "type": "individual",
3031
+ "url": "https://locize.com"
3032
+ },
3033
+ {
3034
+ "type": "individual",
3035
+ "url": "https://locize.com/i18next.html"
3036
+ },
3037
+ {
3038
+ "type": "individual",
3039
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
3040
+ }
3041
+ ],
3042
+ "license": "MIT",
3043
+ "dependencies": {
3044
+ "@babel/runtime": "^7.23.2"
3045
+ }
3046
+ },
3047
+ "node_modules/import-meta-resolve": {
3048
+ "version": "4.2.0",
3049
+ "license": "MIT",
3050
+ "funding": {
3051
+ "type": "github",
3052
+ "url": "https://github.com/sponsors/wooorm"
3053
+ }
3054
+ },
3055
+ "node_modules/inline-style-parser": {
3056
+ "version": "0.2.7",
3057
+ "license": "MIT"
3058
+ },
3059
+ "node_modules/iron-webcrypto": {
3060
+ "version": "1.2.1",
3061
+ "license": "MIT",
3062
+ "funding": {
3063
+ "url": "https://github.com/sponsors/brc-dd"
3064
+ }
3065
+ },
3066
+ "node_modules/is-alphabetical": {
3067
+ "version": "2.0.1",
3068
+ "license": "MIT",
3069
+ "funding": {
3070
+ "type": "github",
3071
+ "url": "https://github.com/sponsors/wooorm"
3072
+ }
3073
+ },
3074
+ "node_modules/is-alphanumerical": {
3075
+ "version": "2.0.1",
3076
+ "license": "MIT",
3077
+ "dependencies": {
3078
+ "is-alphabetical": "^2.0.0",
3079
+ "is-decimal": "^2.0.0"
3080
+ },
3081
+ "funding": {
3082
+ "type": "github",
3083
+ "url": "https://github.com/sponsors/wooorm"
3084
+ }
3085
+ },
3086
+ "node_modules/is-decimal": {
3087
+ "version": "2.0.1",
3088
+ "license": "MIT",
3089
+ "funding": {
3090
+ "type": "github",
3091
+ "url": "https://github.com/sponsors/wooorm"
3092
+ }
3093
+ },
3094
+ "node_modules/is-docker": {
3095
+ "version": "3.0.0",
3096
+ "license": "MIT",
3097
+ "bin": {
3098
+ "is-docker": "cli.js"
3099
+ },
3100
+ "engines": {
3101
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
3102
+ },
3103
+ "funding": {
3104
+ "url": "https://github.com/sponsors/sindresorhus"
3105
+ }
3106
+ },
3107
+ "node_modules/is-fullwidth-code-point": {
3108
+ "version": "3.0.0",
3109
+ "license": "MIT",
3110
+ "engines": {
3111
+ "node": ">=8"
3112
+ }
3113
+ },
3114
+ "node_modules/is-hexadecimal": {
3115
+ "version": "2.0.1",
3116
+ "license": "MIT",
3117
+ "funding": {
3118
+ "type": "github",
3119
+ "url": "https://github.com/sponsors/wooorm"
3120
+ }
3121
+ },
3122
+ "node_modules/is-inside-container": {
3123
+ "version": "1.0.0",
3124
+ "license": "MIT",
3125
+ "dependencies": {
3126
+ "is-docker": "^3.0.0"
3127
+ },
3128
+ "bin": {
3129
+ "is-inside-container": "cli.js"
3130
+ },
3131
+ "engines": {
3132
+ "node": ">=14.16"
3133
+ },
3134
+ "funding": {
3135
+ "url": "https://github.com/sponsors/sindresorhus"
3136
+ }
3137
+ },
3138
+ "node_modules/is-plain-obj": {
3139
+ "version": "4.1.0",
3140
+ "license": "MIT",
3141
+ "engines": {
3142
+ "node": ">=12"
3143
+ },
3144
+ "funding": {
3145
+ "url": "https://github.com/sponsors/sindresorhus"
3146
+ }
3147
+ },
3148
+ "node_modules/is-wsl": {
3149
+ "version": "3.1.0",
3150
+ "license": "MIT",
3151
+ "dependencies": {
3152
+ "is-inside-container": "^1.0.0"
3153
+ },
3154
+ "engines": {
3155
+ "node": ">=16"
3156
+ },
3157
+ "funding": {
3158
+ "url": "https://github.com/sponsors/sindresorhus"
3159
+ }
3160
+ },
3161
+ "node_modules/js-yaml": {
3162
+ "version": "4.1.1",
3163
+ "license": "MIT",
3164
+ "dependencies": {
3165
+ "argparse": "^2.0.1"
3166
+ },
3167
+ "bin": {
3168
+ "js-yaml": "bin/js-yaml.js"
3169
+ }
3170
+ },
3171
+ "node_modules/kleur": {
3172
+ "version": "3.0.3",
3173
+ "license": "MIT",
3174
+ "engines": {
3175
+ "node": ">=6"
3176
+ }
3177
+ },
3178
+ "node_modules/klona": {
3179
+ "version": "2.0.6",
3180
+ "license": "MIT",
3181
+ "engines": {
3182
+ "node": ">= 8"
3183
+ }
3184
+ },
3185
+ "node_modules/longest-streak": {
3186
+ "version": "3.1.0",
3187
+ "license": "MIT",
3188
+ "funding": {
3189
+ "type": "github",
3190
+ "url": "https://github.com/sponsors/wooorm"
3191
+ }
3192
+ },
3193
+ "node_modules/lru-cache": {
3194
+ "version": "11.2.4",
3195
+ "license": "BlueOak-1.0.0",
3196
+ "engines": {
3197
+ "node": "20 || >=22"
3198
+ }
3199
+ },
3200
+ "node_modules/magic-string": {
3201
+ "version": "0.30.21",
3202
+ "license": "MIT",
3203
+ "dependencies": {
3204
+ "@jridgewell/sourcemap-codec": "^1.5.5"
3205
+ }
3206
+ },
3207
+ "node_modules/magicast": {
3208
+ "version": "0.5.1",
3209
+ "license": "MIT",
3210
+ "dependencies": {
3211
+ "@babel/parser": "^7.28.5",
3212
+ "@babel/types": "^7.28.5",
3213
+ "source-map-js": "^1.2.1"
3214
+ }
3215
+ },
3216
+ "node_modules/markdown-extensions": {
3217
+ "version": "2.0.0",
3218
+ "license": "MIT",
3219
+ "engines": {
3220
+ "node": ">=16"
3221
+ },
3222
+ "funding": {
3223
+ "url": "https://github.com/sponsors/sindresorhus"
3224
+ }
3225
+ },
3226
+ "node_modules/markdown-table": {
3227
+ "version": "3.0.4",
3228
+ "license": "MIT",
3229
+ "funding": {
3230
+ "type": "github",
3231
+ "url": "https://github.com/sponsors/wooorm"
3232
+ }
3233
+ },
3234
+ "node_modules/mdast-util-definitions": {
3235
+ "version": "6.0.0",
3236
+ "license": "MIT",
3237
+ "dependencies": {
3238
+ "@types/mdast": "^4.0.0",
3239
+ "@types/unist": "^3.0.0",
3240
+ "unist-util-visit": "^5.0.0"
3241
+ },
3242
+ "funding": {
3243
+ "type": "opencollective",
3244
+ "url": "https://opencollective.com/unified"
3245
+ }
3246
+ },
3247
+ "node_modules/mdast-util-directive": {
3248
+ "version": "3.1.0",
3249
+ "license": "MIT",
3250
+ "dependencies": {
3251
+ "@types/mdast": "^4.0.0",
3252
+ "@types/unist": "^3.0.0",
3253
+ "ccount": "^2.0.0",
3254
+ "devlop": "^1.0.0",
3255
+ "mdast-util-from-markdown": "^2.0.0",
3256
+ "mdast-util-to-markdown": "^2.0.0",
3257
+ "parse-entities": "^4.0.0",
3258
+ "stringify-entities": "^4.0.0",
3259
+ "unist-util-visit-parents": "^6.0.0"
3260
+ },
3261
+ "funding": {
3262
+ "type": "opencollective",
3263
+ "url": "https://opencollective.com/unified"
3264
+ }
3265
+ },
3266
+ "node_modules/mdast-util-find-and-replace": {
3267
+ "version": "3.0.2",
3268
+ "license": "MIT",
3269
+ "dependencies": {
3270
+ "@types/mdast": "^4.0.0",
3271
+ "escape-string-regexp": "^5.0.0",
3272
+ "unist-util-is": "^6.0.0",
3273
+ "unist-util-visit-parents": "^6.0.0"
3274
+ },
3275
+ "funding": {
3276
+ "type": "opencollective",
3277
+ "url": "https://opencollective.com/unified"
3278
+ }
3279
+ },
3280
+ "node_modules/mdast-util-from-markdown": {
3281
+ "version": "2.0.2",
3282
+ "license": "MIT",
3283
+ "dependencies": {
3284
+ "@types/mdast": "^4.0.0",
3285
+ "@types/unist": "^3.0.0",
3286
+ "decode-named-character-reference": "^1.0.0",
3287
+ "devlop": "^1.0.0",
3288
+ "mdast-util-to-string": "^4.0.0",
3289
+ "micromark": "^4.0.0",
3290
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
3291
+ "micromark-util-decode-string": "^2.0.0",
3292
+ "micromark-util-normalize-identifier": "^2.0.0",
3293
+ "micromark-util-symbol": "^2.0.0",
3294
+ "micromark-util-types": "^2.0.0",
3295
+ "unist-util-stringify-position": "^4.0.0"
3296
+ },
3297
+ "funding": {
3298
+ "type": "opencollective",
3299
+ "url": "https://opencollective.com/unified"
3300
+ }
3301
+ },
3302
+ "node_modules/mdast-util-gfm": {
3303
+ "version": "3.1.0",
3304
+ "license": "MIT",
3305
+ "dependencies": {
3306
+ "mdast-util-from-markdown": "^2.0.0",
3307
+ "mdast-util-gfm-autolink-literal": "^2.0.0",
3308
+ "mdast-util-gfm-footnote": "^2.0.0",
3309
+ "mdast-util-gfm-strikethrough": "^2.0.0",
3310
+ "mdast-util-gfm-table": "^2.0.0",
3311
+ "mdast-util-gfm-task-list-item": "^2.0.0",
3312
+ "mdast-util-to-markdown": "^2.0.0"
3313
+ },
3314
+ "funding": {
3315
+ "type": "opencollective",
3316
+ "url": "https://opencollective.com/unified"
3317
+ }
3318
+ },
3319
+ "node_modules/mdast-util-gfm-autolink-literal": {
3320
+ "version": "2.0.1",
3321
+ "license": "MIT",
3322
+ "dependencies": {
3323
+ "@types/mdast": "^4.0.0",
3324
+ "ccount": "^2.0.0",
3325
+ "devlop": "^1.0.0",
3326
+ "mdast-util-find-and-replace": "^3.0.0",
3327
+ "micromark-util-character": "^2.0.0"
3328
+ },
3329
+ "funding": {
3330
+ "type": "opencollective",
3331
+ "url": "https://opencollective.com/unified"
3332
+ }
3333
+ },
3334
+ "node_modules/mdast-util-gfm-footnote": {
3335
+ "version": "2.1.0",
3336
+ "license": "MIT",
3337
+ "dependencies": {
3338
+ "@types/mdast": "^4.0.0",
3339
+ "devlop": "^1.1.0",
3340
+ "mdast-util-from-markdown": "^2.0.0",
3341
+ "mdast-util-to-markdown": "^2.0.0",
3342
+ "micromark-util-normalize-identifier": "^2.0.0"
3343
+ },
3344
+ "funding": {
3345
+ "type": "opencollective",
3346
+ "url": "https://opencollective.com/unified"
3347
+ }
3348
+ },
3349
+ "node_modules/mdast-util-gfm-strikethrough": {
3350
+ "version": "2.0.0",
3351
+ "license": "MIT",
3352
+ "dependencies": {
3353
+ "@types/mdast": "^4.0.0",
3354
+ "mdast-util-from-markdown": "^2.0.0",
3355
+ "mdast-util-to-markdown": "^2.0.0"
3356
+ },
3357
+ "funding": {
3358
+ "type": "opencollective",
3359
+ "url": "https://opencollective.com/unified"
3360
+ }
3361
+ },
3362
+ "node_modules/mdast-util-gfm-table": {
3363
+ "version": "2.0.0",
3364
+ "license": "MIT",
3365
+ "dependencies": {
3366
+ "@types/mdast": "^4.0.0",
3367
+ "devlop": "^1.0.0",
3368
+ "markdown-table": "^3.0.0",
3369
+ "mdast-util-from-markdown": "^2.0.0",
3370
+ "mdast-util-to-markdown": "^2.0.0"
3371
+ },
3372
+ "funding": {
3373
+ "type": "opencollective",
3374
+ "url": "https://opencollective.com/unified"
3375
+ }
3376
+ },
3377
+ "node_modules/mdast-util-gfm-task-list-item": {
3378
+ "version": "2.0.0",
3379
+ "license": "MIT",
3380
+ "dependencies": {
3381
+ "@types/mdast": "^4.0.0",
3382
+ "devlop": "^1.0.0",
3383
+ "mdast-util-from-markdown": "^2.0.0",
3384
+ "mdast-util-to-markdown": "^2.0.0"
3385
+ },
3386
+ "funding": {
3387
+ "type": "opencollective",
3388
+ "url": "https://opencollective.com/unified"
3389
+ }
3390
+ },
3391
+ "node_modules/mdast-util-mdx": {
3392
+ "version": "3.0.0",
3393
+ "license": "MIT",
3394
+ "dependencies": {
3395
+ "mdast-util-from-markdown": "^2.0.0",
3396
+ "mdast-util-mdx-expression": "^2.0.0",
3397
+ "mdast-util-mdx-jsx": "^3.0.0",
3398
+ "mdast-util-mdxjs-esm": "^2.0.0",
3399
+ "mdast-util-to-markdown": "^2.0.0"
3400
+ },
3401
+ "funding": {
3402
+ "type": "opencollective",
3403
+ "url": "https://opencollective.com/unified"
3404
+ }
3405
+ },
3406
+ "node_modules/mdast-util-mdx-expression": {
3407
+ "version": "2.0.1",
3408
+ "license": "MIT",
3409
+ "dependencies": {
3410
+ "@types/estree-jsx": "^1.0.0",
3411
+ "@types/hast": "^3.0.0",
3412
+ "@types/mdast": "^4.0.0",
3413
+ "devlop": "^1.0.0",
3414
+ "mdast-util-from-markdown": "^2.0.0",
3415
+ "mdast-util-to-markdown": "^2.0.0"
3416
+ },
3417
+ "funding": {
3418
+ "type": "opencollective",
3419
+ "url": "https://opencollective.com/unified"
3420
+ }
3421
+ },
3422
+ "node_modules/mdast-util-mdx-jsx": {
3423
+ "version": "3.2.0",
3424
+ "license": "MIT",
3425
+ "dependencies": {
3426
+ "@types/estree-jsx": "^1.0.0",
3427
+ "@types/hast": "^3.0.0",
3428
+ "@types/mdast": "^4.0.0",
3429
+ "@types/unist": "^3.0.0",
3430
+ "ccount": "^2.0.0",
3431
+ "devlop": "^1.1.0",
3432
+ "mdast-util-from-markdown": "^2.0.0",
3433
+ "mdast-util-to-markdown": "^2.0.0",
3434
+ "parse-entities": "^4.0.0",
3435
+ "stringify-entities": "^4.0.0",
3436
+ "unist-util-stringify-position": "^4.0.0",
3437
+ "vfile-message": "^4.0.0"
3438
+ },
3439
+ "funding": {
3440
+ "type": "opencollective",
3441
+ "url": "https://opencollective.com/unified"
3442
+ }
3443
+ },
3444
+ "node_modules/mdast-util-mdxjs-esm": {
3445
+ "version": "2.0.1",
3446
+ "license": "MIT",
3447
+ "dependencies": {
3448
+ "@types/estree-jsx": "^1.0.0",
3449
+ "@types/hast": "^3.0.0",
3450
+ "@types/mdast": "^4.0.0",
3451
+ "devlop": "^1.0.0",
3452
+ "mdast-util-from-markdown": "^2.0.0",
3453
+ "mdast-util-to-markdown": "^2.0.0"
3454
+ },
3455
+ "funding": {
3456
+ "type": "opencollective",
3457
+ "url": "https://opencollective.com/unified"
3458
+ }
3459
+ },
3460
+ "node_modules/mdast-util-phrasing": {
3461
+ "version": "4.1.0",
3462
+ "license": "MIT",
3463
+ "dependencies": {
3464
+ "@types/mdast": "^4.0.0",
3465
+ "unist-util-is": "^6.0.0"
3466
+ },
3467
+ "funding": {
3468
+ "type": "opencollective",
3469
+ "url": "https://opencollective.com/unified"
3470
+ }
3471
+ },
3472
+ "node_modules/mdast-util-to-hast": {
3473
+ "version": "13.2.1",
3474
+ "license": "MIT",
3475
+ "dependencies": {
3476
+ "@types/hast": "^3.0.0",
3477
+ "@types/mdast": "^4.0.0",
3478
+ "@ungap/structured-clone": "^1.0.0",
3479
+ "devlop": "^1.0.0",
3480
+ "micromark-util-sanitize-uri": "^2.0.0",
3481
+ "trim-lines": "^3.0.0",
3482
+ "unist-util-position": "^5.0.0",
3483
+ "unist-util-visit": "^5.0.0",
3484
+ "vfile": "^6.0.0"
3485
+ },
3486
+ "funding": {
3487
+ "type": "opencollective",
3488
+ "url": "https://opencollective.com/unified"
3489
+ }
3490
+ },
3491
+ "node_modules/mdast-util-to-markdown": {
3492
+ "version": "2.1.2",
3493
+ "license": "MIT",
3494
+ "dependencies": {
3495
+ "@types/mdast": "^4.0.0",
3496
+ "@types/unist": "^3.0.0",
3497
+ "longest-streak": "^3.0.0",
3498
+ "mdast-util-phrasing": "^4.0.0",
3499
+ "mdast-util-to-string": "^4.0.0",
3500
+ "micromark-util-classify-character": "^2.0.0",
3501
+ "micromark-util-decode-string": "^2.0.0",
3502
+ "unist-util-visit": "^5.0.0",
3503
+ "zwitch": "^2.0.0"
3504
+ },
3505
+ "funding": {
3506
+ "type": "opencollective",
3507
+ "url": "https://opencollective.com/unified"
3508
+ }
3509
+ },
3510
+ "node_modules/mdast-util-to-string": {
3511
+ "version": "4.0.0",
3512
+ "license": "MIT",
3513
+ "dependencies": {
3514
+ "@types/mdast": "^4.0.0"
3515
+ },
3516
+ "funding": {
3517
+ "type": "opencollective",
3518
+ "url": "https://opencollective.com/unified"
3519
+ }
3520
+ },
3521
+ "node_modules/mdn-data": {
3522
+ "version": "2.12.2",
3523
+ "license": "CC0-1.0"
3524
+ },
3525
+ "node_modules/micromark": {
3526
+ "version": "4.0.2",
3527
+ "funding": [
3528
+ {
3529
+ "type": "GitHub Sponsors",
3530
+ "url": "https://github.com/sponsors/unifiedjs"
3531
+ },
3532
+ {
3533
+ "type": "OpenCollective",
3534
+ "url": "https://opencollective.com/unified"
3535
+ }
3536
+ ],
3537
+ "license": "MIT",
3538
+ "dependencies": {
3539
+ "@types/debug": "^4.0.0",
3540
+ "debug": "^4.0.0",
3541
+ "decode-named-character-reference": "^1.0.0",
3542
+ "devlop": "^1.0.0",
3543
+ "micromark-core-commonmark": "^2.0.0",
3544
+ "micromark-factory-space": "^2.0.0",
3545
+ "micromark-util-character": "^2.0.0",
3546
+ "micromark-util-chunked": "^2.0.0",
3547
+ "micromark-util-combine-extensions": "^2.0.0",
3548
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
3549
+ "micromark-util-encode": "^2.0.0",
3550
+ "micromark-util-normalize-identifier": "^2.0.0",
3551
+ "micromark-util-resolve-all": "^2.0.0",
3552
+ "micromark-util-sanitize-uri": "^2.0.0",
3553
+ "micromark-util-subtokenize": "^2.0.0",
3554
+ "micromark-util-symbol": "^2.0.0",
3555
+ "micromark-util-types": "^2.0.0"
3556
+ }
3557
+ },
3558
+ "node_modules/micromark-core-commonmark": {
3559
+ "version": "2.0.3",
3560
+ "funding": [
3561
+ {
3562
+ "type": "GitHub Sponsors",
3563
+ "url": "https://github.com/sponsors/unifiedjs"
3564
+ },
3565
+ {
3566
+ "type": "OpenCollective",
3567
+ "url": "https://opencollective.com/unified"
3568
+ }
3569
+ ],
3570
+ "license": "MIT",
3571
+ "dependencies": {
3572
+ "decode-named-character-reference": "^1.0.0",
3573
+ "devlop": "^1.0.0",
3574
+ "micromark-factory-destination": "^2.0.0",
3575
+ "micromark-factory-label": "^2.0.0",
3576
+ "micromark-factory-space": "^2.0.0",
3577
+ "micromark-factory-title": "^2.0.0",
3578
+ "micromark-factory-whitespace": "^2.0.0",
3579
+ "micromark-util-character": "^2.0.0",
3580
+ "micromark-util-chunked": "^2.0.0",
3581
+ "micromark-util-classify-character": "^2.0.0",
3582
+ "micromark-util-html-tag-name": "^2.0.0",
3583
+ "micromark-util-normalize-identifier": "^2.0.0",
3584
+ "micromark-util-resolve-all": "^2.0.0",
3585
+ "micromark-util-subtokenize": "^2.0.0",
3586
+ "micromark-util-symbol": "^2.0.0",
3587
+ "micromark-util-types": "^2.0.0"
3588
+ }
3589
+ },
3590
+ "node_modules/micromark-extension-directive": {
3591
+ "version": "3.0.2",
3592
+ "license": "MIT",
3593
+ "dependencies": {
3594
+ "devlop": "^1.0.0",
3595
+ "micromark-factory-space": "^2.0.0",
3596
+ "micromark-factory-whitespace": "^2.0.0",
3597
+ "micromark-util-character": "^2.0.0",
3598
+ "micromark-util-symbol": "^2.0.0",
3599
+ "micromark-util-types": "^2.0.0",
3600
+ "parse-entities": "^4.0.0"
3601
+ },
3602
+ "funding": {
3603
+ "type": "opencollective",
3604
+ "url": "https://opencollective.com/unified"
3605
+ }
3606
+ },
3607
+ "node_modules/micromark-extension-gfm": {
3608
+ "version": "3.0.0",
3609
+ "license": "MIT",
3610
+ "dependencies": {
3611
+ "micromark-extension-gfm-autolink-literal": "^2.0.0",
3612
+ "micromark-extension-gfm-footnote": "^2.0.0",
3613
+ "micromark-extension-gfm-strikethrough": "^2.0.0",
3614
+ "micromark-extension-gfm-table": "^2.0.0",
3615
+ "micromark-extension-gfm-tagfilter": "^2.0.0",
3616
+ "micromark-extension-gfm-task-list-item": "^2.0.0",
3617
+ "micromark-util-combine-extensions": "^2.0.0",
3618
+ "micromark-util-types": "^2.0.0"
3619
+ },
3620
+ "funding": {
3621
+ "type": "opencollective",
3622
+ "url": "https://opencollective.com/unified"
3623
+ }
3624
+ },
3625
+ "node_modules/micromark-extension-gfm-autolink-literal": {
3626
+ "version": "2.1.0",
3627
+ "license": "MIT",
3628
+ "dependencies": {
3629
+ "micromark-util-character": "^2.0.0",
3630
+ "micromark-util-sanitize-uri": "^2.0.0",
3631
+ "micromark-util-symbol": "^2.0.0",
3632
+ "micromark-util-types": "^2.0.0"
3633
+ },
3634
+ "funding": {
3635
+ "type": "opencollective",
3636
+ "url": "https://opencollective.com/unified"
3637
+ }
3638
+ },
3639
+ "node_modules/micromark-extension-gfm-footnote": {
3640
+ "version": "2.1.0",
3641
+ "license": "MIT",
3642
+ "dependencies": {
3643
+ "devlop": "^1.0.0",
3644
+ "micromark-core-commonmark": "^2.0.0",
3645
+ "micromark-factory-space": "^2.0.0",
3646
+ "micromark-util-character": "^2.0.0",
3647
+ "micromark-util-normalize-identifier": "^2.0.0",
3648
+ "micromark-util-sanitize-uri": "^2.0.0",
3649
+ "micromark-util-symbol": "^2.0.0",
3650
+ "micromark-util-types": "^2.0.0"
3651
+ },
3652
+ "funding": {
3653
+ "type": "opencollective",
3654
+ "url": "https://opencollective.com/unified"
3655
+ }
3656
+ },
3657
+ "node_modules/micromark-extension-gfm-strikethrough": {
3658
+ "version": "2.1.0",
3659
+ "license": "MIT",
3660
+ "dependencies": {
3661
+ "devlop": "^1.0.0",
3662
+ "micromark-util-chunked": "^2.0.0",
3663
+ "micromark-util-classify-character": "^2.0.0",
3664
+ "micromark-util-resolve-all": "^2.0.0",
3665
+ "micromark-util-symbol": "^2.0.0",
3666
+ "micromark-util-types": "^2.0.0"
3667
+ },
3668
+ "funding": {
3669
+ "type": "opencollective",
3670
+ "url": "https://opencollective.com/unified"
3671
+ }
3672
+ },
3673
+ "node_modules/micromark-extension-gfm-table": {
3674
+ "version": "2.1.1",
3675
+ "license": "MIT",
3676
+ "dependencies": {
3677
+ "devlop": "^1.0.0",
3678
+ "micromark-factory-space": "^2.0.0",
3679
+ "micromark-util-character": "^2.0.0",
3680
+ "micromark-util-symbol": "^2.0.0",
3681
+ "micromark-util-types": "^2.0.0"
3682
+ },
3683
+ "funding": {
3684
+ "type": "opencollective",
3685
+ "url": "https://opencollective.com/unified"
3686
+ }
3687
+ },
3688
+ "node_modules/micromark-extension-gfm-tagfilter": {
3689
+ "version": "2.0.0",
3690
+ "license": "MIT",
3691
+ "dependencies": {
3692
+ "micromark-util-types": "^2.0.0"
3693
+ },
3694
+ "funding": {
3695
+ "type": "opencollective",
3696
+ "url": "https://opencollective.com/unified"
3697
+ }
3698
+ },
3699
+ "node_modules/micromark-extension-gfm-task-list-item": {
3700
+ "version": "2.1.0",
3701
+ "license": "MIT",
3702
+ "dependencies": {
3703
+ "devlop": "^1.0.0",
3704
+ "micromark-factory-space": "^2.0.0",
3705
+ "micromark-util-character": "^2.0.0",
3706
+ "micromark-util-symbol": "^2.0.0",
3707
+ "micromark-util-types": "^2.0.0"
3708
+ },
3709
+ "funding": {
3710
+ "type": "opencollective",
3711
+ "url": "https://opencollective.com/unified"
3712
+ }
3713
+ },
3714
+ "node_modules/micromark-extension-mdx-expression": {
3715
+ "version": "3.0.1",
3716
+ "funding": [
3717
+ {
3718
+ "type": "GitHub Sponsors",
3719
+ "url": "https://github.com/sponsors/unifiedjs"
3720
+ },
3721
+ {
3722
+ "type": "OpenCollective",
3723
+ "url": "https://opencollective.com/unified"
3724
+ }
3725
+ ],
3726
+ "license": "MIT",
3727
+ "dependencies": {
3728
+ "@types/estree": "^1.0.0",
3729
+ "devlop": "^1.0.0",
3730
+ "micromark-factory-mdx-expression": "^2.0.0",
3731
+ "micromark-factory-space": "^2.0.0",
3732
+ "micromark-util-character": "^2.0.0",
3733
+ "micromark-util-events-to-acorn": "^2.0.0",
3734
+ "micromark-util-symbol": "^2.0.0",
3735
+ "micromark-util-types": "^2.0.0"
3736
+ }
3737
+ },
3738
+ "node_modules/micromark-extension-mdx-jsx": {
3739
+ "version": "3.0.2",
3740
+ "license": "MIT",
3741
+ "dependencies": {
3742
+ "@types/estree": "^1.0.0",
3743
+ "devlop": "^1.0.0",
3744
+ "estree-util-is-identifier-name": "^3.0.0",
3745
+ "micromark-factory-mdx-expression": "^2.0.0",
3746
+ "micromark-factory-space": "^2.0.0",
3747
+ "micromark-util-character": "^2.0.0",
3748
+ "micromark-util-events-to-acorn": "^2.0.0",
3749
+ "micromark-util-symbol": "^2.0.0",
3750
+ "micromark-util-types": "^2.0.0",
3751
+ "vfile-message": "^4.0.0"
3752
+ },
3753
+ "funding": {
3754
+ "type": "opencollective",
3755
+ "url": "https://opencollective.com/unified"
3756
+ }
3757
+ },
3758
+ "node_modules/micromark-extension-mdx-md": {
3759
+ "version": "2.0.0",
3760
+ "license": "MIT",
3761
+ "dependencies": {
3762
+ "micromark-util-types": "^2.0.0"
3763
+ },
3764
+ "funding": {
3765
+ "type": "opencollective",
3766
+ "url": "https://opencollective.com/unified"
3767
+ }
3768
+ },
3769
+ "node_modules/micromark-extension-mdxjs": {
3770
+ "version": "3.0.0",
3771
+ "license": "MIT",
3772
+ "dependencies": {
3773
+ "acorn": "^8.0.0",
3774
+ "acorn-jsx": "^5.0.0",
3775
+ "micromark-extension-mdx-expression": "^3.0.0",
3776
+ "micromark-extension-mdx-jsx": "^3.0.0",
3777
+ "micromark-extension-mdx-md": "^2.0.0",
3778
+ "micromark-extension-mdxjs-esm": "^3.0.0",
3779
+ "micromark-util-combine-extensions": "^2.0.0",
3780
+ "micromark-util-types": "^2.0.0"
3781
+ },
3782
+ "funding": {
3783
+ "type": "opencollective",
3784
+ "url": "https://opencollective.com/unified"
3785
+ }
3786
+ },
3787
+ "node_modules/micromark-extension-mdxjs-esm": {
3788
+ "version": "3.0.0",
3789
+ "license": "MIT",
3790
+ "dependencies": {
3791
+ "@types/estree": "^1.0.0",
3792
+ "devlop": "^1.0.0",
3793
+ "micromark-core-commonmark": "^2.0.0",
3794
+ "micromark-util-character": "^2.0.0",
3795
+ "micromark-util-events-to-acorn": "^2.0.0",
3796
+ "micromark-util-symbol": "^2.0.0",
3797
+ "micromark-util-types": "^2.0.0",
3798
+ "unist-util-position-from-estree": "^2.0.0",
3799
+ "vfile-message": "^4.0.0"
3800
+ },
3801
+ "funding": {
3802
+ "type": "opencollective",
3803
+ "url": "https://opencollective.com/unified"
3804
+ }
3805
+ },
3806
+ "node_modules/micromark-factory-destination": {
3807
+ "version": "2.0.1",
3808
+ "funding": [
3809
+ {
3810
+ "type": "GitHub Sponsors",
3811
+ "url": "https://github.com/sponsors/unifiedjs"
3812
+ },
3813
+ {
3814
+ "type": "OpenCollective",
3815
+ "url": "https://opencollective.com/unified"
3816
+ }
3817
+ ],
3818
+ "license": "MIT",
3819
+ "dependencies": {
3820
+ "micromark-util-character": "^2.0.0",
3821
+ "micromark-util-symbol": "^2.0.0",
3822
+ "micromark-util-types": "^2.0.0"
3823
+ }
3824
+ },
3825
+ "node_modules/micromark-factory-label": {
3826
+ "version": "2.0.1",
3827
+ "funding": [
3828
+ {
3829
+ "type": "GitHub Sponsors",
3830
+ "url": "https://github.com/sponsors/unifiedjs"
3831
+ },
3832
+ {
3833
+ "type": "OpenCollective",
3834
+ "url": "https://opencollective.com/unified"
3835
+ }
3836
+ ],
3837
+ "license": "MIT",
3838
+ "dependencies": {
3839
+ "devlop": "^1.0.0",
3840
+ "micromark-util-character": "^2.0.0",
3841
+ "micromark-util-symbol": "^2.0.0",
3842
+ "micromark-util-types": "^2.0.0"
3843
+ }
3844
+ },
3845
+ "node_modules/micromark-factory-mdx-expression": {
3846
+ "version": "2.0.3",
3847
+ "funding": [
3848
+ {
3849
+ "type": "GitHub Sponsors",
3850
+ "url": "https://github.com/sponsors/unifiedjs"
3851
+ },
3852
+ {
3853
+ "type": "OpenCollective",
3854
+ "url": "https://opencollective.com/unified"
3855
+ }
3856
+ ],
3857
+ "license": "MIT",
3858
+ "dependencies": {
3859
+ "@types/estree": "^1.0.0",
3860
+ "devlop": "^1.0.0",
3861
+ "micromark-factory-space": "^2.0.0",
3862
+ "micromark-util-character": "^2.0.0",
3863
+ "micromark-util-events-to-acorn": "^2.0.0",
3864
+ "micromark-util-symbol": "^2.0.0",
3865
+ "micromark-util-types": "^2.0.0",
3866
+ "unist-util-position-from-estree": "^2.0.0",
3867
+ "vfile-message": "^4.0.0"
3868
+ }
3869
+ },
3870
+ "node_modules/micromark-factory-space": {
3871
+ "version": "2.0.1",
3872
+ "funding": [
3873
+ {
3874
+ "type": "GitHub Sponsors",
3875
+ "url": "https://github.com/sponsors/unifiedjs"
3876
+ },
3877
+ {
3878
+ "type": "OpenCollective",
3879
+ "url": "https://opencollective.com/unified"
3880
+ }
3881
+ ],
3882
+ "license": "MIT",
3883
+ "dependencies": {
3884
+ "micromark-util-character": "^2.0.0",
3885
+ "micromark-util-types": "^2.0.0"
3886
+ }
3887
+ },
3888
+ "node_modules/micromark-factory-title": {
3889
+ "version": "2.0.1",
3890
+ "funding": [
3891
+ {
3892
+ "type": "GitHub Sponsors",
3893
+ "url": "https://github.com/sponsors/unifiedjs"
3894
+ },
3895
+ {
3896
+ "type": "OpenCollective",
3897
+ "url": "https://opencollective.com/unified"
3898
+ }
3899
+ ],
3900
+ "license": "MIT",
3901
+ "dependencies": {
3902
+ "micromark-factory-space": "^2.0.0",
3903
+ "micromark-util-character": "^2.0.0",
3904
+ "micromark-util-symbol": "^2.0.0",
3905
+ "micromark-util-types": "^2.0.0"
3906
+ }
3907
+ },
3908
+ "node_modules/micromark-factory-whitespace": {
3909
+ "version": "2.0.1",
3910
+ "funding": [
3911
+ {
3912
+ "type": "GitHub Sponsors",
3913
+ "url": "https://github.com/sponsors/unifiedjs"
3914
+ },
3915
+ {
3916
+ "type": "OpenCollective",
3917
+ "url": "https://opencollective.com/unified"
3918
+ }
3919
+ ],
3920
+ "license": "MIT",
3921
+ "dependencies": {
3922
+ "micromark-factory-space": "^2.0.0",
3923
+ "micromark-util-character": "^2.0.0",
3924
+ "micromark-util-symbol": "^2.0.0",
3925
+ "micromark-util-types": "^2.0.0"
3926
+ }
3927
+ },
3928
+ "node_modules/micromark-util-character": {
3929
+ "version": "2.1.1",
3930
+ "funding": [
3931
+ {
3932
+ "type": "GitHub Sponsors",
3933
+ "url": "https://github.com/sponsors/unifiedjs"
3934
+ },
3935
+ {
3936
+ "type": "OpenCollective",
3937
+ "url": "https://opencollective.com/unified"
3938
+ }
3939
+ ],
3940
+ "license": "MIT",
3941
+ "dependencies": {
3942
+ "micromark-util-symbol": "^2.0.0",
3943
+ "micromark-util-types": "^2.0.0"
3944
+ }
3945
+ },
3946
+ "node_modules/micromark-util-chunked": {
3947
+ "version": "2.0.1",
3948
+ "funding": [
3949
+ {
3950
+ "type": "GitHub Sponsors",
3951
+ "url": "https://github.com/sponsors/unifiedjs"
3952
+ },
3953
+ {
3954
+ "type": "OpenCollective",
3955
+ "url": "https://opencollective.com/unified"
3956
+ }
3957
+ ],
3958
+ "license": "MIT",
3959
+ "dependencies": {
3960
+ "micromark-util-symbol": "^2.0.0"
3961
+ }
3962
+ },
3963
+ "node_modules/micromark-util-classify-character": {
3964
+ "version": "2.0.1",
3965
+ "funding": [
3966
+ {
3967
+ "type": "GitHub Sponsors",
3968
+ "url": "https://github.com/sponsors/unifiedjs"
3969
+ },
3970
+ {
3971
+ "type": "OpenCollective",
3972
+ "url": "https://opencollective.com/unified"
3973
+ }
3974
+ ],
3975
+ "license": "MIT",
3976
+ "dependencies": {
3977
+ "micromark-util-character": "^2.0.0",
3978
+ "micromark-util-symbol": "^2.0.0",
3979
+ "micromark-util-types": "^2.0.0"
3980
+ }
3981
+ },
3982
+ "node_modules/micromark-util-combine-extensions": {
3983
+ "version": "2.0.1",
3984
+ "funding": [
3985
+ {
3986
+ "type": "GitHub Sponsors",
3987
+ "url": "https://github.com/sponsors/unifiedjs"
3988
+ },
3989
+ {
3990
+ "type": "OpenCollective",
3991
+ "url": "https://opencollective.com/unified"
3992
+ }
3993
+ ],
3994
+ "license": "MIT",
3995
+ "dependencies": {
3996
+ "micromark-util-chunked": "^2.0.0",
3997
+ "micromark-util-types": "^2.0.0"
3998
+ }
3999
+ },
4000
+ "node_modules/micromark-util-decode-numeric-character-reference": {
4001
+ "version": "2.0.2",
4002
+ "funding": [
4003
+ {
4004
+ "type": "GitHub Sponsors",
4005
+ "url": "https://github.com/sponsors/unifiedjs"
4006
+ },
4007
+ {
4008
+ "type": "OpenCollective",
4009
+ "url": "https://opencollective.com/unified"
4010
+ }
4011
+ ],
4012
+ "license": "MIT",
4013
+ "dependencies": {
4014
+ "micromark-util-symbol": "^2.0.0"
4015
+ }
4016
+ },
4017
+ "node_modules/micromark-util-decode-string": {
4018
+ "version": "2.0.1",
4019
+ "funding": [
4020
+ {
4021
+ "type": "GitHub Sponsors",
4022
+ "url": "https://github.com/sponsors/unifiedjs"
4023
+ },
4024
+ {
4025
+ "type": "OpenCollective",
4026
+ "url": "https://opencollective.com/unified"
4027
+ }
4028
+ ],
4029
+ "license": "MIT",
4030
+ "dependencies": {
4031
+ "decode-named-character-reference": "^1.0.0",
4032
+ "micromark-util-character": "^2.0.0",
4033
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
4034
+ "micromark-util-symbol": "^2.0.0"
4035
+ }
4036
+ },
4037
+ "node_modules/micromark-util-encode": {
4038
+ "version": "2.0.1",
4039
+ "funding": [
4040
+ {
4041
+ "type": "GitHub Sponsors",
4042
+ "url": "https://github.com/sponsors/unifiedjs"
4043
+ },
4044
+ {
4045
+ "type": "OpenCollective",
4046
+ "url": "https://opencollective.com/unified"
4047
+ }
4048
+ ],
4049
+ "license": "MIT"
4050
+ },
4051
+ "node_modules/micromark-util-events-to-acorn": {
4052
+ "version": "2.0.3",
4053
+ "funding": [
4054
+ {
4055
+ "type": "GitHub Sponsors",
4056
+ "url": "https://github.com/sponsors/unifiedjs"
4057
+ },
4058
+ {
4059
+ "type": "OpenCollective",
4060
+ "url": "https://opencollective.com/unified"
4061
+ }
4062
+ ],
4063
+ "license": "MIT",
4064
+ "dependencies": {
4065
+ "@types/estree": "^1.0.0",
4066
+ "@types/unist": "^3.0.0",
4067
+ "devlop": "^1.0.0",
4068
+ "estree-util-visit": "^2.0.0",
4069
+ "micromark-util-symbol": "^2.0.0",
4070
+ "micromark-util-types": "^2.0.0",
4071
+ "vfile-message": "^4.0.0"
4072
+ }
4073
+ },
4074
+ "node_modules/micromark-util-html-tag-name": {
4075
+ "version": "2.0.1",
4076
+ "funding": [
4077
+ {
4078
+ "type": "GitHub Sponsors",
4079
+ "url": "https://github.com/sponsors/unifiedjs"
4080
+ },
4081
+ {
4082
+ "type": "OpenCollective",
4083
+ "url": "https://opencollective.com/unified"
4084
+ }
4085
+ ],
4086
+ "license": "MIT"
4087
+ },
4088
+ "node_modules/micromark-util-normalize-identifier": {
4089
+ "version": "2.0.1",
4090
+ "funding": [
4091
+ {
4092
+ "type": "GitHub Sponsors",
4093
+ "url": "https://github.com/sponsors/unifiedjs"
4094
+ },
4095
+ {
4096
+ "type": "OpenCollective",
4097
+ "url": "https://opencollective.com/unified"
4098
+ }
4099
+ ],
4100
+ "license": "MIT",
4101
+ "dependencies": {
4102
+ "micromark-util-symbol": "^2.0.0"
4103
+ }
4104
+ },
4105
+ "node_modules/micromark-util-resolve-all": {
4106
+ "version": "2.0.1",
4107
+ "funding": [
4108
+ {
4109
+ "type": "GitHub Sponsors",
4110
+ "url": "https://github.com/sponsors/unifiedjs"
4111
+ },
4112
+ {
4113
+ "type": "OpenCollective",
4114
+ "url": "https://opencollective.com/unified"
4115
+ }
4116
+ ],
4117
+ "license": "MIT",
4118
+ "dependencies": {
4119
+ "micromark-util-types": "^2.0.0"
4120
+ }
4121
+ },
4122
+ "node_modules/micromark-util-sanitize-uri": {
4123
+ "version": "2.0.1",
4124
+ "funding": [
4125
+ {
4126
+ "type": "GitHub Sponsors",
4127
+ "url": "https://github.com/sponsors/unifiedjs"
4128
+ },
4129
+ {
4130
+ "type": "OpenCollective",
4131
+ "url": "https://opencollective.com/unified"
4132
+ }
4133
+ ],
4134
+ "license": "MIT",
4135
+ "dependencies": {
4136
+ "micromark-util-character": "^2.0.0",
4137
+ "micromark-util-encode": "^2.0.0",
4138
+ "micromark-util-symbol": "^2.0.0"
4139
+ }
4140
+ },
4141
+ "node_modules/micromark-util-subtokenize": {
4142
+ "version": "2.1.0",
4143
+ "funding": [
4144
+ {
4145
+ "type": "GitHub Sponsors",
4146
+ "url": "https://github.com/sponsors/unifiedjs"
4147
+ },
4148
+ {
4149
+ "type": "OpenCollective",
4150
+ "url": "https://opencollective.com/unified"
4151
+ }
4152
+ ],
4153
+ "license": "MIT",
4154
+ "dependencies": {
4155
+ "devlop": "^1.0.0",
4156
+ "micromark-util-chunked": "^2.0.0",
4157
+ "micromark-util-symbol": "^2.0.0",
4158
+ "micromark-util-types": "^2.0.0"
4159
+ }
4160
+ },
4161
+ "node_modules/micromark-util-symbol": {
4162
+ "version": "2.0.1",
4163
+ "funding": [
4164
+ {
4165
+ "type": "GitHub Sponsors",
4166
+ "url": "https://github.com/sponsors/unifiedjs"
4167
+ },
4168
+ {
4169
+ "type": "OpenCollective",
4170
+ "url": "https://opencollective.com/unified"
4171
+ }
4172
+ ],
4173
+ "license": "MIT"
4174
+ },
4175
+ "node_modules/micromark-util-types": {
4176
+ "version": "2.0.2",
4177
+ "funding": [
4178
+ {
4179
+ "type": "GitHub Sponsors",
4180
+ "url": "https://github.com/sponsors/unifiedjs"
4181
+ },
4182
+ {
4183
+ "type": "OpenCollective",
4184
+ "url": "https://opencollective.com/unified"
4185
+ }
4186
+ ],
4187
+ "license": "MIT"
4188
+ },
4189
+ "node_modules/mrmime": {
4190
+ "version": "2.0.1",
4191
+ "license": "MIT",
4192
+ "engines": {
4193
+ "node": ">=10"
4194
+ }
4195
+ },
4196
+ "node_modules/ms": {
4197
+ "version": "2.1.3",
4198
+ "license": "MIT"
4199
+ },
4200
+ "node_modules/nanoid": {
4201
+ "version": "3.3.11",
4202
+ "funding": [
4203
+ {
4204
+ "type": "github",
4205
+ "url": "https://github.com/sponsors/ai"
4206
+ }
4207
+ ],
4208
+ "license": "MIT",
4209
+ "bin": {
4210
+ "nanoid": "bin/nanoid.cjs"
4211
+ },
4212
+ "engines": {
4213
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
4214
+ }
4215
+ },
4216
+ "node_modules/neotraverse": {
4217
+ "version": "0.6.18",
4218
+ "license": "MIT",
4219
+ "engines": {
4220
+ "node": ">= 10"
4221
+ }
4222
+ },
4223
+ "node_modules/nlcst-to-string": {
4224
+ "version": "4.0.0",
4225
+ "license": "MIT",
4226
+ "dependencies": {
4227
+ "@types/nlcst": "^2.0.0"
4228
+ },
4229
+ "funding": {
4230
+ "type": "opencollective",
4231
+ "url": "https://opencollective.com/unified"
4232
+ }
4233
+ },
4234
+ "node_modules/node-fetch-native": {
4235
+ "version": "1.6.7",
4236
+ "license": "MIT"
4237
+ },
4238
+ "node_modules/node-mock-http": {
4239
+ "version": "1.0.4",
4240
+ "license": "MIT"
4241
+ },
4242
+ "node_modules/normalize-path": {
4243
+ "version": "3.0.0",
4244
+ "license": "MIT",
4245
+ "engines": {
4246
+ "node": ">=0.10.0"
4247
+ }
4248
+ },
4249
+ "node_modules/nth-check": {
4250
+ "version": "2.1.1",
4251
+ "license": "BSD-2-Clause",
4252
+ "dependencies": {
4253
+ "boolbase": "^1.0.0"
4254
+ },
4255
+ "funding": {
4256
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
4257
+ }
4258
+ },
4259
+ "node_modules/ofetch": {
4260
+ "version": "1.5.1",
4261
+ "license": "MIT",
4262
+ "dependencies": {
4263
+ "destr": "^2.0.5",
4264
+ "node-fetch-native": "^1.6.7",
4265
+ "ufo": "^1.6.1"
4266
+ }
4267
+ },
4268
+ "node_modules/ohash": {
4269
+ "version": "2.0.11",
4270
+ "license": "MIT"
4271
+ },
4272
+ "node_modules/oniguruma-parser": {
4273
+ "version": "0.12.1",
4274
+ "license": "MIT"
4275
+ },
4276
+ "node_modules/oniguruma-to-es": {
4277
+ "version": "4.3.4",
4278
+ "license": "MIT",
4279
+ "dependencies": {
4280
+ "oniguruma-parser": "^0.12.1",
4281
+ "regex": "^6.0.1",
4282
+ "regex-recursion": "^6.0.2"
4283
+ }
4284
+ },
4285
+ "node_modules/p-limit": {
4286
+ "version": "6.2.0",
4287
+ "license": "MIT",
4288
+ "dependencies": {
4289
+ "yocto-queue": "^1.1.1"
4290
+ },
4291
+ "engines": {
4292
+ "node": ">=18"
4293
+ },
4294
+ "funding": {
4295
+ "url": "https://github.com/sponsors/sindresorhus"
4296
+ }
4297
+ },
4298
+ "node_modules/p-queue": {
4299
+ "version": "8.1.1",
4300
+ "license": "MIT",
4301
+ "dependencies": {
4302
+ "eventemitter3": "^5.0.1",
4303
+ "p-timeout": "^6.1.2"
4304
+ },
4305
+ "engines": {
4306
+ "node": ">=18"
4307
+ },
4308
+ "funding": {
4309
+ "url": "https://github.com/sponsors/sindresorhus"
4310
+ }
4311
+ },
4312
+ "node_modules/p-timeout": {
4313
+ "version": "6.1.4",
4314
+ "license": "MIT",
4315
+ "engines": {
4316
+ "node": ">=14.16"
4317
+ },
4318
+ "funding": {
4319
+ "url": "https://github.com/sponsors/sindresorhus"
4320
+ }
4321
+ },
4322
+ "node_modules/package-manager-detector": {
4323
+ "version": "1.6.0",
4324
+ "license": "MIT"
4325
+ },
4326
+ "node_modules/pagefind": {
4327
+ "version": "1.4.0",
4328
+ "license": "MIT",
4329
+ "bin": {
4330
+ "pagefind": "lib/runner/bin.cjs"
4331
+ },
4332
+ "optionalDependencies": {
4333
+ "@pagefind/darwin-arm64": "1.4.0",
4334
+ "@pagefind/darwin-x64": "1.4.0",
4335
+ "@pagefind/freebsd-x64": "1.4.0",
4336
+ "@pagefind/linux-arm64": "1.4.0",
4337
+ "@pagefind/linux-x64": "1.4.0",
4338
+ "@pagefind/windows-x64": "1.4.0"
4339
+ }
4340
+ },
4341
+ "node_modules/parse-entities": {
4342
+ "version": "4.0.2",
4343
+ "license": "MIT",
4344
+ "dependencies": {
4345
+ "@types/unist": "^2.0.0",
4346
+ "character-entities-legacy": "^3.0.0",
4347
+ "character-reference-invalid": "^2.0.0",
4348
+ "decode-named-character-reference": "^1.0.0",
4349
+ "is-alphanumerical": "^2.0.0",
4350
+ "is-decimal": "^2.0.0",
4351
+ "is-hexadecimal": "^2.0.0"
4352
+ },
4353
+ "funding": {
4354
+ "type": "github",
4355
+ "url": "https://github.com/sponsors/wooorm"
4356
+ }
4357
+ },
4358
+ "node_modules/parse-entities/node_modules/@types/unist": {
4359
+ "version": "2.0.11",
4360
+ "license": "MIT"
4361
+ },
4362
+ "node_modules/parse-latin": {
4363
+ "version": "7.0.0",
4364
+ "license": "MIT",
4365
+ "dependencies": {
4366
+ "@types/nlcst": "^2.0.0",
4367
+ "@types/unist": "^3.0.0",
4368
+ "nlcst-to-string": "^4.0.0",
4369
+ "unist-util-modify-children": "^4.0.0",
4370
+ "unist-util-visit-children": "^3.0.0",
4371
+ "vfile": "^6.0.0"
4372
+ },
4373
+ "funding": {
4374
+ "type": "github",
4375
+ "url": "https://github.com/sponsors/wooorm"
4376
+ }
4377
+ },
4378
+ "node_modules/parse5": {
4379
+ "version": "7.3.0",
4380
+ "license": "MIT",
4381
+ "dependencies": {
4382
+ "entities": "^6.0.0"
4383
+ },
4384
+ "funding": {
4385
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
4386
+ }
4387
+ },
4388
+ "node_modules/piccolore": {
4389
+ "version": "0.1.3",
4390
+ "license": "ISC"
4391
+ },
4392
+ "node_modules/picocolors": {
4393
+ "version": "1.1.1",
4394
+ "license": "ISC"
4395
+ },
4396
+ "node_modules/picomatch": {
4397
+ "version": "4.0.3",
4398
+ "license": "MIT",
4399
+ "engines": {
4400
+ "node": ">=12"
4401
+ },
4402
+ "funding": {
4403
+ "url": "https://github.com/sponsors/jonschlinkert"
4404
+ }
4405
+ },
4406
+ "node_modules/postcss": {
4407
+ "version": "8.5.6",
4408
+ "funding": [
4409
+ {
4410
+ "type": "opencollective",
4411
+ "url": "https://opencollective.com/postcss/"
4412
+ },
4413
+ {
4414
+ "type": "tidelift",
4415
+ "url": "https://tidelift.com/funding/github/npm/postcss"
4416
+ },
4417
+ {
4418
+ "type": "github",
4419
+ "url": "https://github.com/sponsors/ai"
4420
+ }
4421
+ ],
4422
+ "license": "MIT",
4423
+ "dependencies": {
4424
+ "nanoid": "^3.3.11",
4425
+ "picocolors": "^1.1.1",
4426
+ "source-map-js": "^1.2.1"
4427
+ },
4428
+ "engines": {
4429
+ "node": "^10 || ^12 || >=14"
4430
+ }
4431
+ },
4432
+ "node_modules/postcss-nested": {
4433
+ "version": "6.2.0",
4434
+ "funding": [
4435
+ {
4436
+ "type": "opencollective",
4437
+ "url": "https://opencollective.com/postcss/"
4438
+ },
4439
+ {
4440
+ "type": "github",
4441
+ "url": "https://github.com/sponsors/ai"
4442
+ }
4443
+ ],
4444
+ "license": "MIT",
4445
+ "dependencies": {
4446
+ "postcss-selector-parser": "^6.1.1"
4447
+ },
4448
+ "engines": {
4449
+ "node": ">=12.0"
4450
+ },
4451
+ "peerDependencies": {
4452
+ "postcss": "^8.2.14"
4453
+ }
4454
+ },
4455
+ "node_modules/postcss-selector-parser": {
4456
+ "version": "6.1.2",
4457
+ "license": "MIT",
4458
+ "dependencies": {
4459
+ "cssesc": "^3.0.0",
4460
+ "util-deprecate": "^1.0.2"
4461
+ },
4462
+ "engines": {
4463
+ "node": ">=4"
4464
+ }
4465
+ },
4466
+ "node_modules/prismjs": {
4467
+ "version": "1.30.0",
4468
+ "license": "MIT",
4469
+ "engines": {
4470
+ "node": ">=6"
4471
+ }
4472
+ },
4473
+ "node_modules/prompts": {
4474
+ "version": "2.4.2",
4475
+ "license": "MIT",
4476
+ "dependencies": {
4477
+ "kleur": "^3.0.3",
4478
+ "sisteransi": "^1.0.5"
4479
+ },
4480
+ "engines": {
4481
+ "node": ">= 6"
4482
+ }
4483
+ },
4484
+ "node_modules/property-information": {
4485
+ "version": "7.1.0",
4486
+ "license": "MIT",
4487
+ "funding": {
4488
+ "type": "github",
4489
+ "url": "https://github.com/sponsors/wooorm"
4490
+ }
4491
+ },
4492
+ "node_modules/radix3": {
4493
+ "version": "1.1.2",
4494
+ "license": "MIT"
4495
+ },
4496
+ "node_modules/readdirp": {
4497
+ "version": "5.0.0",
4498
+ "license": "MIT",
4499
+ "engines": {
4500
+ "node": ">= 20.19.0"
4501
+ },
4502
+ "funding": {
4503
+ "type": "individual",
4504
+ "url": "https://paulmillr.com/funding/"
4505
+ }
4506
+ },
4507
+ "node_modules/recma-build-jsx": {
4508
+ "version": "1.0.0",
4509
+ "license": "MIT",
4510
+ "dependencies": {
4511
+ "@types/estree": "^1.0.0",
4512
+ "estree-util-build-jsx": "^3.0.0",
4513
+ "vfile": "^6.0.0"
4514
+ },
4515
+ "funding": {
4516
+ "type": "opencollective",
4517
+ "url": "https://opencollective.com/unified"
4518
+ }
4519
+ },
4520
+ "node_modules/recma-jsx": {
4521
+ "version": "1.0.1",
4522
+ "license": "MIT",
4523
+ "dependencies": {
4524
+ "acorn-jsx": "^5.0.0",
4525
+ "estree-util-to-js": "^2.0.0",
4526
+ "recma-parse": "^1.0.0",
4527
+ "recma-stringify": "^1.0.0",
4528
+ "unified": "^11.0.0"
4529
+ },
4530
+ "funding": {
4531
+ "type": "opencollective",
4532
+ "url": "https://opencollective.com/unified"
4533
+ },
4534
+ "peerDependencies": {
4535
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
4536
+ }
4537
+ },
4538
+ "node_modules/recma-parse": {
4539
+ "version": "1.0.0",
4540
+ "license": "MIT",
4541
+ "dependencies": {
4542
+ "@types/estree": "^1.0.0",
4543
+ "esast-util-from-js": "^2.0.0",
4544
+ "unified": "^11.0.0",
4545
+ "vfile": "^6.0.0"
4546
+ },
4547
+ "funding": {
4548
+ "type": "opencollective",
4549
+ "url": "https://opencollective.com/unified"
4550
+ }
4551
+ },
4552
+ "node_modules/recma-stringify": {
4553
+ "version": "1.0.0",
4554
+ "license": "MIT",
4555
+ "dependencies": {
4556
+ "@types/estree": "^1.0.0",
4557
+ "estree-util-to-js": "^2.0.0",
4558
+ "unified": "^11.0.0",
4559
+ "vfile": "^6.0.0"
4560
+ },
4561
+ "funding": {
4562
+ "type": "opencollective",
4563
+ "url": "https://opencollective.com/unified"
4564
+ }
4565
+ },
4566
+ "node_modules/regex": {
4567
+ "version": "6.1.0",
4568
+ "license": "MIT",
4569
+ "dependencies": {
4570
+ "regex-utilities": "^2.3.0"
4571
+ }
4572
+ },
4573
+ "node_modules/regex-recursion": {
4574
+ "version": "6.0.2",
4575
+ "license": "MIT",
4576
+ "dependencies": {
4577
+ "regex-utilities": "^2.3.0"
4578
+ }
4579
+ },
4580
+ "node_modules/regex-utilities": {
4581
+ "version": "2.3.0",
4582
+ "license": "MIT"
4583
+ },
4584
+ "node_modules/rehype": {
4585
+ "version": "13.0.2",
4586
+ "license": "MIT",
4587
+ "dependencies": {
4588
+ "@types/hast": "^3.0.0",
4589
+ "rehype-parse": "^9.0.0",
4590
+ "rehype-stringify": "^10.0.0",
4591
+ "unified": "^11.0.0"
4592
+ },
4593
+ "funding": {
4594
+ "type": "opencollective",
4595
+ "url": "https://opencollective.com/unified"
4596
+ }
4597
+ },
4598
+ "node_modules/rehype-expressive-code": {
4599
+ "version": "0.41.6",
4600
+ "license": "MIT",
4601
+ "dependencies": {
4602
+ "expressive-code": "^0.41.6"
4603
+ }
4604
+ },
4605
+ "node_modules/rehype-format": {
4606
+ "version": "5.0.1",
4607
+ "license": "MIT",
4608
+ "dependencies": {
4609
+ "@types/hast": "^3.0.0",
4610
+ "hast-util-format": "^1.0.0"
4611
+ },
4612
+ "funding": {
4613
+ "type": "opencollective",
4614
+ "url": "https://opencollective.com/unified"
4615
+ }
4616
+ },
4617
+ "node_modules/rehype-parse": {
4618
+ "version": "9.0.1",
4619
+ "license": "MIT",
4620
+ "dependencies": {
4621
+ "@types/hast": "^3.0.0",
4622
+ "hast-util-from-html": "^2.0.0",
4623
+ "unified": "^11.0.0"
4624
+ },
4625
+ "funding": {
4626
+ "type": "opencollective",
4627
+ "url": "https://opencollective.com/unified"
4628
+ }
4629
+ },
4630
+ "node_modules/rehype-raw": {
4631
+ "version": "7.0.0",
4632
+ "license": "MIT",
4633
+ "dependencies": {
4634
+ "@types/hast": "^3.0.0",
4635
+ "hast-util-raw": "^9.0.0",
4636
+ "vfile": "^6.0.0"
4637
+ },
4638
+ "funding": {
4639
+ "type": "opencollective",
4640
+ "url": "https://opencollective.com/unified"
4641
+ }
4642
+ },
4643
+ "node_modules/rehype-recma": {
4644
+ "version": "1.0.0",
4645
+ "license": "MIT",
4646
+ "dependencies": {
4647
+ "@types/estree": "^1.0.0",
4648
+ "@types/hast": "^3.0.0",
4649
+ "hast-util-to-estree": "^3.0.0"
4650
+ },
4651
+ "funding": {
4652
+ "type": "opencollective",
4653
+ "url": "https://opencollective.com/unified"
4654
+ }
4655
+ },
4656
+ "node_modules/rehype-stringify": {
4657
+ "version": "10.0.1",
4658
+ "license": "MIT",
4659
+ "dependencies": {
4660
+ "@types/hast": "^3.0.0",
4661
+ "hast-util-to-html": "^9.0.0",
4662
+ "unified": "^11.0.0"
4663
+ },
4664
+ "funding": {
4665
+ "type": "opencollective",
4666
+ "url": "https://opencollective.com/unified"
4667
+ }
4668
+ },
4669
+ "node_modules/remark-directive": {
4670
+ "version": "3.0.1",
4671
+ "license": "MIT",
4672
+ "dependencies": {
4673
+ "@types/mdast": "^4.0.0",
4674
+ "mdast-util-directive": "^3.0.0",
4675
+ "micromark-extension-directive": "^3.0.0",
4676
+ "unified": "^11.0.0"
4677
+ },
4678
+ "funding": {
4679
+ "type": "opencollective",
4680
+ "url": "https://opencollective.com/unified"
4681
+ }
4682
+ },
4683
+ "node_modules/remark-gfm": {
4684
+ "version": "4.0.1",
4685
+ "license": "MIT",
4686
+ "dependencies": {
4687
+ "@types/mdast": "^4.0.0",
4688
+ "mdast-util-gfm": "^3.0.0",
4689
+ "micromark-extension-gfm": "^3.0.0",
4690
+ "remark-parse": "^11.0.0",
4691
+ "remark-stringify": "^11.0.0",
4692
+ "unified": "^11.0.0"
4693
+ },
4694
+ "funding": {
4695
+ "type": "opencollective",
4696
+ "url": "https://opencollective.com/unified"
4697
+ }
4698
+ },
4699
+ "node_modules/remark-mdx": {
4700
+ "version": "3.1.1",
4701
+ "license": "MIT",
4702
+ "dependencies": {
4703
+ "mdast-util-mdx": "^3.0.0",
4704
+ "micromark-extension-mdxjs": "^3.0.0"
4705
+ },
4706
+ "funding": {
4707
+ "type": "opencollective",
4708
+ "url": "https://opencollective.com/unified"
4709
+ }
4710
+ },
4711
+ "node_modules/remark-parse": {
4712
+ "version": "11.0.0",
4713
+ "license": "MIT",
4714
+ "dependencies": {
4715
+ "@types/mdast": "^4.0.0",
4716
+ "mdast-util-from-markdown": "^2.0.0",
4717
+ "micromark-util-types": "^2.0.0",
4718
+ "unified": "^11.0.0"
4719
+ },
4720
+ "funding": {
4721
+ "type": "opencollective",
4722
+ "url": "https://opencollective.com/unified"
4723
+ }
4724
+ },
4725
+ "node_modules/remark-rehype": {
4726
+ "version": "11.1.2",
4727
+ "license": "MIT",
4728
+ "dependencies": {
4729
+ "@types/hast": "^3.0.0",
4730
+ "@types/mdast": "^4.0.0",
4731
+ "mdast-util-to-hast": "^13.0.0",
4732
+ "unified": "^11.0.0",
4733
+ "vfile": "^6.0.0"
4734
+ },
4735
+ "funding": {
4736
+ "type": "opencollective",
4737
+ "url": "https://opencollective.com/unified"
4738
+ }
4739
+ },
4740
+ "node_modules/remark-smartypants": {
4741
+ "version": "3.0.2",
4742
+ "license": "MIT",
4743
+ "dependencies": {
4744
+ "retext": "^9.0.0",
4745
+ "retext-smartypants": "^6.0.0",
4746
+ "unified": "^11.0.4",
4747
+ "unist-util-visit": "^5.0.0"
4748
+ },
4749
+ "engines": {
4750
+ "node": ">=16.0.0"
4751
+ }
4752
+ },
4753
+ "node_modules/remark-stringify": {
4754
+ "version": "11.0.0",
4755
+ "license": "MIT",
4756
+ "dependencies": {
4757
+ "@types/mdast": "^4.0.0",
4758
+ "mdast-util-to-markdown": "^2.0.0",
4759
+ "unified": "^11.0.0"
4760
+ },
4761
+ "funding": {
4762
+ "type": "opencollective",
4763
+ "url": "https://opencollective.com/unified"
4764
+ }
4765
+ },
4766
+ "node_modules/retext": {
4767
+ "version": "9.0.0",
4768
+ "license": "MIT",
4769
+ "dependencies": {
4770
+ "@types/nlcst": "^2.0.0",
4771
+ "retext-latin": "^4.0.0",
4772
+ "retext-stringify": "^4.0.0",
4773
+ "unified": "^11.0.0"
4774
+ },
4775
+ "funding": {
4776
+ "type": "opencollective",
4777
+ "url": "https://opencollective.com/unified"
4778
+ }
4779
+ },
4780
+ "node_modules/retext-latin": {
4781
+ "version": "4.0.0",
4782
+ "license": "MIT",
4783
+ "dependencies": {
4784
+ "@types/nlcst": "^2.0.0",
4785
+ "parse-latin": "^7.0.0",
4786
+ "unified": "^11.0.0"
4787
+ },
4788
+ "funding": {
4789
+ "type": "opencollective",
4790
+ "url": "https://opencollective.com/unified"
4791
+ }
4792
+ },
4793
+ "node_modules/retext-smartypants": {
4794
+ "version": "6.2.0",
4795
+ "license": "MIT",
4796
+ "dependencies": {
4797
+ "@types/nlcst": "^2.0.0",
4798
+ "nlcst-to-string": "^4.0.0",
4799
+ "unist-util-visit": "^5.0.0"
4800
+ },
4801
+ "funding": {
4802
+ "type": "opencollective",
4803
+ "url": "https://opencollective.com/unified"
4804
+ }
4805
+ },
4806
+ "node_modules/retext-stringify": {
4807
+ "version": "4.0.0",
4808
+ "license": "MIT",
4809
+ "dependencies": {
4810
+ "@types/nlcst": "^2.0.0",
4811
+ "nlcst-to-string": "^4.0.0",
4812
+ "unified": "^11.0.0"
4813
+ },
4814
+ "funding": {
4815
+ "type": "opencollective",
4816
+ "url": "https://opencollective.com/unified"
4817
+ }
4818
+ },
4819
+ "node_modules/rollup": {
4820
+ "version": "4.55.3",
4821
+ "license": "MIT",
4822
+ "dependencies": {
4823
+ "@types/estree": "1.0.8"
4824
+ },
4825
+ "bin": {
4826
+ "rollup": "dist/bin/rollup"
4827
+ },
4828
+ "engines": {
4829
+ "node": ">=18.0.0",
4830
+ "npm": ">=8.0.0"
4831
+ },
4832
+ "optionalDependencies": {
4833
+ "@rollup/rollup-android-arm-eabi": "4.55.3",
4834
+ "@rollup/rollup-android-arm64": "4.55.3",
4835
+ "@rollup/rollup-darwin-arm64": "4.55.3",
4836
+ "@rollup/rollup-darwin-x64": "4.55.3",
4837
+ "@rollup/rollup-freebsd-arm64": "4.55.3",
4838
+ "@rollup/rollup-freebsd-x64": "4.55.3",
4839
+ "@rollup/rollup-linux-arm-gnueabihf": "4.55.3",
4840
+ "@rollup/rollup-linux-arm-musleabihf": "4.55.3",
4841
+ "@rollup/rollup-linux-arm64-gnu": "4.55.3",
4842
+ "@rollup/rollup-linux-arm64-musl": "4.55.3",
4843
+ "@rollup/rollup-linux-loong64-gnu": "4.55.3",
4844
+ "@rollup/rollup-linux-loong64-musl": "4.55.3",
4845
+ "@rollup/rollup-linux-ppc64-gnu": "4.55.3",
4846
+ "@rollup/rollup-linux-ppc64-musl": "4.55.3",
4847
+ "@rollup/rollup-linux-riscv64-gnu": "4.55.3",
4848
+ "@rollup/rollup-linux-riscv64-musl": "4.55.3",
4849
+ "@rollup/rollup-linux-s390x-gnu": "4.55.3",
4850
+ "@rollup/rollup-linux-x64-gnu": "4.55.3",
4851
+ "@rollup/rollup-linux-x64-musl": "4.55.3",
4852
+ "@rollup/rollup-openbsd-x64": "4.55.3",
4853
+ "@rollup/rollup-openharmony-arm64": "4.55.3",
4854
+ "@rollup/rollup-win32-arm64-msvc": "4.55.3",
4855
+ "@rollup/rollup-win32-ia32-msvc": "4.55.3",
4856
+ "@rollup/rollup-win32-x64-gnu": "4.55.3",
4857
+ "@rollup/rollup-win32-x64-msvc": "4.55.3",
4858
+ "fsevents": "~2.3.2"
4859
+ }
4860
+ },
4861
+ "node_modules/sax": {
4862
+ "version": "1.4.4",
4863
+ "license": "BlueOak-1.0.0",
4864
+ "engines": {
4865
+ "node": ">=11.0.0"
4866
+ }
4867
+ },
4868
+ "node_modules/semver": {
4869
+ "version": "7.7.3",
4870
+ "license": "ISC",
4871
+ "bin": {
4872
+ "semver": "bin/semver.js"
4873
+ },
4874
+ "engines": {
4875
+ "node": ">=10"
4876
+ }
4877
+ },
4878
+ "node_modules/sharp": {
4879
+ "version": "0.34.5",
4880
+ "hasInstallScript": true,
4881
+ "license": "Apache-2.0",
4882
+ "dependencies": {
4883
+ "@img/colour": "^1.0.0",
4884
+ "detect-libc": "^2.1.2",
4885
+ "semver": "^7.7.3"
4886
+ },
4887
+ "engines": {
4888
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
4889
+ },
4890
+ "funding": {
4891
+ "url": "https://opencollective.com/libvips"
4892
+ },
4893
+ "optionalDependencies": {
4894
+ "@img/sharp-darwin-arm64": "0.34.5",
4895
+ "@img/sharp-darwin-x64": "0.34.5",
4896
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
4897
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
4898
+ "@img/sharp-libvips-linux-arm": "1.2.4",
4899
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
4900
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
4901
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
4902
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
4903
+ "@img/sharp-libvips-linux-x64": "1.2.4",
4904
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
4905
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
4906
+ "@img/sharp-linux-arm": "0.34.5",
4907
+ "@img/sharp-linux-arm64": "0.34.5",
4908
+ "@img/sharp-linux-ppc64": "0.34.5",
4909
+ "@img/sharp-linux-riscv64": "0.34.5",
4910
+ "@img/sharp-linux-s390x": "0.34.5",
4911
+ "@img/sharp-linux-x64": "0.34.5",
4912
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
4913
+ "@img/sharp-linuxmusl-x64": "0.34.5",
4914
+ "@img/sharp-wasm32": "0.34.5",
4915
+ "@img/sharp-win32-arm64": "0.34.5",
4916
+ "@img/sharp-win32-ia32": "0.34.5",
4917
+ "@img/sharp-win32-x64": "0.34.5"
4918
+ }
4919
+ },
4920
+ "node_modules/shiki": {
4921
+ "version": "3.21.0",
4922
+ "license": "MIT",
4923
+ "dependencies": {
4924
+ "@shikijs/core": "3.21.0",
4925
+ "@shikijs/engine-javascript": "3.21.0",
4926
+ "@shikijs/engine-oniguruma": "3.21.0",
4927
+ "@shikijs/langs": "3.21.0",
4928
+ "@shikijs/themes": "3.21.0",
4929
+ "@shikijs/types": "3.21.0",
4930
+ "@shikijs/vscode-textmate": "^10.0.2",
4931
+ "@types/hast": "^3.0.4"
4932
+ }
4933
+ },
4934
+ "node_modules/sisteransi": {
4935
+ "version": "1.0.5",
4936
+ "license": "MIT"
4937
+ },
4938
+ "node_modules/sitemap": {
4939
+ "version": "8.0.2",
4940
+ "license": "MIT",
4941
+ "dependencies": {
4942
+ "@types/node": "^17.0.5",
4943
+ "@types/sax": "^1.2.1",
4944
+ "arg": "^5.0.0",
4945
+ "sax": "^1.4.1"
4946
+ },
4947
+ "bin": {
4948
+ "sitemap": "dist/cli.js"
4949
+ },
4950
+ "engines": {
4951
+ "node": ">=14.0.0",
4952
+ "npm": ">=6.0.0"
4953
+ }
4954
+ },
4955
+ "node_modules/sitemap/node_modules/@types/node": {
4956
+ "version": "17.0.45",
4957
+ "resolved": "https://registry.npmmirror.com/@types/node/-/node-17.0.45.tgz",
4958
+ "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
4959
+ "license": "MIT"
4960
+ },
4961
+ "node_modules/smol-toml": {
4962
+ "version": "1.6.0",
4963
+ "license": "BSD-3-Clause",
4964
+ "engines": {
4965
+ "node": ">= 18"
4966
+ },
4967
+ "funding": {
4968
+ "url": "https://github.com/sponsors/cyyynthia"
4969
+ }
4970
+ },
4971
+ "node_modules/source-map": {
4972
+ "version": "0.7.6",
4973
+ "license": "BSD-3-Clause",
4974
+ "engines": {
4975
+ "node": ">= 12"
4976
+ }
4977
+ },
4978
+ "node_modules/source-map-js": {
4979
+ "version": "1.2.1",
4980
+ "license": "BSD-3-Clause",
4981
+ "engines": {
4982
+ "node": ">=0.10.0"
4983
+ }
4984
+ },
4985
+ "node_modules/space-separated-tokens": {
4986
+ "version": "2.0.2",
4987
+ "license": "MIT",
4988
+ "funding": {
4989
+ "type": "github",
4990
+ "url": "https://github.com/sponsors/wooorm"
4991
+ }
4992
+ },
4993
+ "node_modules/stream-replace-string": {
4994
+ "version": "2.0.0",
4995
+ "license": "MIT"
4996
+ },
4997
+ "node_modules/string-width": {
4998
+ "version": "7.2.0",
4999
+ "license": "MIT",
5000
+ "dependencies": {
5001
+ "emoji-regex": "^10.3.0",
5002
+ "get-east-asian-width": "^1.0.0",
5003
+ "strip-ansi": "^7.1.0"
5004
+ },
5005
+ "engines": {
5006
+ "node": ">=18"
5007
+ },
5008
+ "funding": {
5009
+ "url": "https://github.com/sponsors/sindresorhus"
5010
+ }
5011
+ },
5012
+ "node_modules/stringify-entities": {
5013
+ "version": "4.0.4",
5014
+ "license": "MIT",
5015
+ "dependencies": {
5016
+ "character-entities-html4": "^2.0.0",
5017
+ "character-entities-legacy": "^3.0.0"
5018
+ },
5019
+ "funding": {
5020
+ "type": "github",
5021
+ "url": "https://github.com/sponsors/wooorm"
5022
+ }
5023
+ },
5024
+ "node_modules/strip-ansi": {
5025
+ "version": "7.1.2",
5026
+ "license": "MIT",
5027
+ "dependencies": {
5028
+ "ansi-regex": "^6.0.1"
5029
+ },
5030
+ "engines": {
5031
+ "node": ">=12"
5032
+ },
5033
+ "funding": {
5034
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
5035
+ }
5036
+ },
5037
+ "node_modules/style-to-js": {
5038
+ "version": "1.1.21",
5039
+ "license": "MIT",
5040
+ "dependencies": {
5041
+ "style-to-object": "1.0.14"
5042
+ }
5043
+ },
5044
+ "node_modules/style-to-object": {
5045
+ "version": "1.0.14",
5046
+ "license": "MIT",
5047
+ "dependencies": {
5048
+ "inline-style-parser": "0.2.7"
5049
+ }
5050
+ },
5051
+ "node_modules/svgo": {
5052
+ "version": "4.0.0",
5053
+ "license": "MIT",
5054
+ "dependencies": {
5055
+ "commander": "^11.1.0",
5056
+ "css-select": "^5.1.0",
5057
+ "css-tree": "^3.0.1",
5058
+ "css-what": "^6.1.0",
5059
+ "csso": "^5.0.5",
5060
+ "picocolors": "^1.1.1",
5061
+ "sax": "^1.4.1"
5062
+ },
5063
+ "bin": {
5064
+ "svgo": "bin/svgo.js"
5065
+ },
5066
+ "engines": {
5067
+ "node": ">=16"
5068
+ },
5069
+ "funding": {
5070
+ "type": "opencollective",
5071
+ "url": "https://opencollective.com/svgo"
5072
+ }
5073
+ },
5074
+ "node_modules/tiny-inflate": {
5075
+ "version": "1.0.3",
5076
+ "license": "MIT"
5077
+ },
5078
+ "node_modules/tinyexec": {
5079
+ "version": "1.0.2",
5080
+ "license": "MIT",
5081
+ "engines": {
5082
+ "node": ">=18"
5083
+ }
5084
+ },
5085
+ "node_modules/tinyglobby": {
5086
+ "version": "0.2.15",
5087
+ "license": "MIT",
5088
+ "dependencies": {
5089
+ "fdir": "^6.5.0",
5090
+ "picomatch": "^4.0.3"
5091
+ },
5092
+ "engines": {
5093
+ "node": ">=12.0.0"
5094
+ },
5095
+ "funding": {
5096
+ "url": "https://github.com/sponsors/SuperchupuDev"
5097
+ }
5098
+ },
5099
+ "node_modules/trim-lines": {
5100
+ "version": "3.0.1",
5101
+ "license": "MIT",
5102
+ "funding": {
5103
+ "type": "github",
5104
+ "url": "https://github.com/sponsors/wooorm"
5105
+ }
5106
+ },
5107
+ "node_modules/trough": {
5108
+ "version": "2.2.0",
5109
+ "license": "MIT",
5110
+ "funding": {
5111
+ "type": "github",
5112
+ "url": "https://github.com/sponsors/wooorm"
5113
+ }
5114
+ },
5115
+ "node_modules/tsconfck": {
5116
+ "version": "3.1.6",
5117
+ "license": "MIT",
5118
+ "bin": {
5119
+ "tsconfck": "bin/tsconfck.js"
5120
+ },
5121
+ "engines": {
5122
+ "node": "^18 || >=20"
5123
+ },
5124
+ "peerDependencies": {
5125
+ "typescript": "^5.0.0"
5126
+ },
5127
+ "peerDependenciesMeta": {
5128
+ "typescript": {
5129
+ "optional": true
5130
+ }
5131
+ }
5132
+ },
5133
+ "node_modules/tslib": {
5134
+ "version": "2.8.1",
5135
+ "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
5136
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
5137
+ "license": "0BSD",
5138
+ "optional": true
5139
+ },
5140
+ "node_modules/type-fest": {
5141
+ "version": "4.41.0",
5142
+ "license": "(MIT OR CC0-1.0)",
5143
+ "engines": {
5144
+ "node": ">=16"
5145
+ },
5146
+ "funding": {
5147
+ "url": "https://github.com/sponsors/sindresorhus"
5148
+ }
5149
+ },
5150
+ "node_modules/typescript": {
5151
+ "version": "5.9.3",
5152
+ "license": "Apache-2.0",
5153
+ "peer": true,
5154
+ "bin": {
5155
+ "tsc": "bin/tsc",
5156
+ "tsserver": "bin/tsserver"
5157
+ },
5158
+ "engines": {
5159
+ "node": ">=14.17"
5160
+ }
5161
+ },
5162
+ "node_modules/ufo": {
5163
+ "version": "1.6.3",
5164
+ "license": "MIT"
5165
+ },
5166
+ "node_modules/ultrahtml": {
5167
+ "version": "1.6.0",
5168
+ "license": "MIT"
5169
+ },
5170
+ "node_modules/uncrypto": {
5171
+ "version": "0.1.3",
5172
+ "license": "MIT"
5173
+ },
5174
+ "node_modules/undici-types": {
5175
+ "version": "8.3.0",
5176
+ "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-8.3.0.tgz",
5177
+ "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
5178
+ "license": "MIT"
5179
+ },
5180
+ "node_modules/unified": {
5181
+ "version": "11.0.5",
5182
+ "license": "MIT",
5183
+ "dependencies": {
5184
+ "@types/unist": "^3.0.0",
5185
+ "bail": "^2.0.0",
5186
+ "devlop": "^1.0.0",
5187
+ "extend": "^3.0.0",
5188
+ "is-plain-obj": "^4.0.0",
5189
+ "trough": "^2.0.0",
5190
+ "vfile": "^6.0.0"
5191
+ },
5192
+ "funding": {
5193
+ "type": "opencollective",
5194
+ "url": "https://opencollective.com/unified"
5195
+ }
5196
+ },
5197
+ "node_modules/unifont": {
5198
+ "version": "0.7.3",
5199
+ "license": "MIT",
5200
+ "dependencies": {
5201
+ "css-tree": "^3.1.0",
5202
+ "ofetch": "^1.5.1",
5203
+ "ohash": "^2.0.11"
5204
+ }
5205
+ },
5206
+ "node_modules/unist-util-find-after": {
5207
+ "version": "5.0.0",
5208
+ "license": "MIT",
5209
+ "dependencies": {
5210
+ "@types/unist": "^3.0.0",
5211
+ "unist-util-is": "^6.0.0"
5212
+ },
5213
+ "funding": {
5214
+ "type": "opencollective",
5215
+ "url": "https://opencollective.com/unified"
5216
+ }
5217
+ },
5218
+ "node_modules/unist-util-is": {
5219
+ "version": "6.0.1",
5220
+ "license": "MIT",
5221
+ "dependencies": {
5222
+ "@types/unist": "^3.0.0"
5223
+ },
5224
+ "funding": {
5225
+ "type": "opencollective",
5226
+ "url": "https://opencollective.com/unified"
5227
+ }
5228
+ },
5229
+ "node_modules/unist-util-modify-children": {
5230
+ "version": "4.0.0",
5231
+ "license": "MIT",
5232
+ "dependencies": {
5233
+ "@types/unist": "^3.0.0",
5234
+ "array-iterate": "^2.0.0"
5235
+ },
5236
+ "funding": {
5237
+ "type": "opencollective",
5238
+ "url": "https://opencollective.com/unified"
5239
+ }
5240
+ },
5241
+ "node_modules/unist-util-position": {
5242
+ "version": "5.0.0",
5243
+ "license": "MIT",
5244
+ "dependencies": {
5245
+ "@types/unist": "^3.0.0"
5246
+ },
5247
+ "funding": {
5248
+ "type": "opencollective",
5249
+ "url": "https://opencollective.com/unified"
5250
+ }
5251
+ },
5252
+ "node_modules/unist-util-position-from-estree": {
5253
+ "version": "2.0.0",
5254
+ "license": "MIT",
5255
+ "dependencies": {
5256
+ "@types/unist": "^3.0.0"
5257
+ },
5258
+ "funding": {
5259
+ "type": "opencollective",
5260
+ "url": "https://opencollective.com/unified"
5261
+ }
5262
+ },
5263
+ "node_modules/unist-util-remove-position": {
5264
+ "version": "5.0.0",
5265
+ "license": "MIT",
5266
+ "dependencies": {
5267
+ "@types/unist": "^3.0.0",
5268
+ "unist-util-visit": "^5.0.0"
5269
+ },
5270
+ "funding": {
5271
+ "type": "opencollective",
5272
+ "url": "https://opencollective.com/unified"
5273
+ }
5274
+ },
5275
+ "node_modules/unist-util-stringify-position": {
5276
+ "version": "4.0.0",
5277
+ "license": "MIT",
5278
+ "dependencies": {
5279
+ "@types/unist": "^3.0.0"
5280
+ },
5281
+ "funding": {
5282
+ "type": "opencollective",
5283
+ "url": "https://opencollective.com/unified"
5284
+ }
5285
+ },
5286
+ "node_modules/unist-util-visit": {
5287
+ "version": "5.0.0",
5288
+ "license": "MIT",
5289
+ "dependencies": {
5290
+ "@types/unist": "^3.0.0",
5291
+ "unist-util-is": "^6.0.0",
5292
+ "unist-util-visit-parents": "^6.0.0"
5293
+ },
5294
+ "funding": {
5295
+ "type": "opencollective",
5296
+ "url": "https://opencollective.com/unified"
5297
+ }
5298
+ },
5299
+ "node_modules/unist-util-visit-children": {
5300
+ "version": "3.0.0",
5301
+ "license": "MIT",
5302
+ "dependencies": {
5303
+ "@types/unist": "^3.0.0"
5304
+ },
5305
+ "funding": {
5306
+ "type": "opencollective",
5307
+ "url": "https://opencollective.com/unified"
5308
+ }
5309
+ },
5310
+ "node_modules/unist-util-visit-parents": {
5311
+ "version": "6.0.2",
5312
+ "license": "MIT",
5313
+ "dependencies": {
5314
+ "@types/unist": "^3.0.0",
5315
+ "unist-util-is": "^6.0.0"
5316
+ },
5317
+ "funding": {
5318
+ "type": "opencollective",
5319
+ "url": "https://opencollective.com/unified"
5320
+ }
5321
+ },
5322
+ "node_modules/unstorage": {
5323
+ "version": "1.17.4",
5324
+ "license": "MIT",
5325
+ "dependencies": {
5326
+ "anymatch": "^3.1.3",
5327
+ "chokidar": "^5.0.0",
5328
+ "destr": "^2.0.5",
5329
+ "h3": "^1.15.5",
5330
+ "lru-cache": "^11.2.0",
5331
+ "node-fetch-native": "^1.6.7",
5332
+ "ofetch": "^1.5.1",
5333
+ "ufo": "^1.6.3"
5334
+ },
5335
+ "peerDependencies": {
5336
+ "@azure/app-configuration": "^1.8.0",
5337
+ "@azure/cosmos": "^4.2.0",
5338
+ "@azure/data-tables": "^13.3.0",
5339
+ "@azure/identity": "^4.6.0",
5340
+ "@azure/keyvault-secrets": "^4.9.0",
5341
+ "@azure/storage-blob": "^12.26.0",
5342
+ "@capacitor/preferences": "^6 || ^7 || ^8",
5343
+ "@deno/kv": ">=0.9.0",
5344
+ "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0",
5345
+ "@planetscale/database": "^1.19.0",
5346
+ "@upstash/redis": "^1.34.3",
5347
+ "@vercel/blob": ">=0.27.1",
5348
+ "@vercel/functions": "^2.2.12 || ^3.0.0",
5349
+ "@vercel/kv": "^1 || ^2 || ^3",
5350
+ "aws4fetch": "^1.0.20",
5351
+ "db0": ">=0.2.1",
5352
+ "idb-keyval": "^6.2.1",
5353
+ "ioredis": "^5.4.2",
5354
+ "uploadthing": "^7.4.4"
5355
+ },
5356
+ "peerDependenciesMeta": {
5357
+ "@azure/app-configuration": {
5358
+ "optional": true
5359
+ },
5360
+ "@azure/cosmos": {
5361
+ "optional": true
5362
+ },
5363
+ "@azure/data-tables": {
5364
+ "optional": true
5365
+ },
5366
+ "@azure/identity": {
5367
+ "optional": true
5368
+ },
5369
+ "@azure/keyvault-secrets": {
5370
+ "optional": true
5371
+ },
5372
+ "@azure/storage-blob": {
5373
+ "optional": true
5374
+ },
5375
+ "@capacitor/preferences": {
5376
+ "optional": true
5377
+ },
5378
+ "@deno/kv": {
5379
+ "optional": true
5380
+ },
5381
+ "@netlify/blobs": {
5382
+ "optional": true
5383
+ },
5384
+ "@planetscale/database": {
5385
+ "optional": true
5386
+ },
5387
+ "@upstash/redis": {
5388
+ "optional": true
5389
+ },
5390
+ "@vercel/blob": {
5391
+ "optional": true
5392
+ },
5393
+ "@vercel/functions": {
5394
+ "optional": true
5395
+ },
5396
+ "@vercel/kv": {
5397
+ "optional": true
5398
+ },
5399
+ "aws4fetch": {
5400
+ "optional": true
5401
+ },
5402
+ "db0": {
5403
+ "optional": true
5404
+ },
5405
+ "idb-keyval": {
5406
+ "optional": true
5407
+ },
5408
+ "ioredis": {
5409
+ "optional": true
5410
+ },
5411
+ "uploadthing": {
5412
+ "optional": true
5413
+ }
5414
+ }
5415
+ },
5416
+ "node_modules/util-deprecate": {
5417
+ "version": "1.0.2",
5418
+ "license": "MIT"
5419
+ },
5420
+ "node_modules/vfile": {
5421
+ "version": "6.0.3",
5422
+ "license": "MIT",
5423
+ "dependencies": {
5424
+ "@types/unist": "^3.0.0",
5425
+ "vfile-message": "^4.0.0"
5426
+ },
5427
+ "funding": {
5428
+ "type": "opencollective",
5429
+ "url": "https://opencollective.com/unified"
5430
+ }
5431
+ },
5432
+ "node_modules/vfile-location": {
5433
+ "version": "5.0.3",
5434
+ "license": "MIT",
5435
+ "dependencies": {
5436
+ "@types/unist": "^3.0.0",
5437
+ "vfile": "^6.0.0"
5438
+ },
5439
+ "funding": {
5440
+ "type": "opencollective",
5441
+ "url": "https://opencollective.com/unified"
5442
+ }
5443
+ },
5444
+ "node_modules/vfile-message": {
5445
+ "version": "4.0.3",
5446
+ "license": "MIT",
5447
+ "dependencies": {
5448
+ "@types/unist": "^3.0.0",
5449
+ "unist-util-stringify-position": "^4.0.0"
5450
+ },
5451
+ "funding": {
5452
+ "type": "opencollective",
5453
+ "url": "https://opencollective.com/unified"
5454
+ }
5455
+ },
5456
+ "node_modules/vite": {
5457
+ "version": "6.4.1",
5458
+ "license": "MIT",
5459
+ "dependencies": {
5460
+ "esbuild": "^0.25.0",
5461
+ "fdir": "^6.4.4",
5462
+ "picomatch": "^4.0.2",
5463
+ "postcss": "^8.5.3",
5464
+ "rollup": "^4.34.9",
5465
+ "tinyglobby": "^0.2.13"
5466
+ },
5467
+ "bin": {
5468
+ "vite": "bin/vite.js"
5469
+ },
5470
+ "engines": {
5471
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
5472
+ },
5473
+ "funding": {
5474
+ "url": "https://github.com/vitejs/vite?sponsor=1"
5475
+ },
5476
+ "optionalDependencies": {
5477
+ "fsevents": "~2.3.3"
5478
+ },
5479
+ "peerDependencies": {
5480
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
5481
+ "jiti": ">=1.21.0",
5482
+ "less": "*",
5483
+ "lightningcss": "^1.21.0",
5484
+ "sass": "*",
5485
+ "sass-embedded": "*",
5486
+ "stylus": "*",
5487
+ "sugarss": "*",
5488
+ "terser": "^5.16.0",
5489
+ "tsx": "^4.8.1",
5490
+ "yaml": "^2.4.2"
5491
+ },
5492
+ "peerDependenciesMeta": {
5493
+ "@types/node": {
5494
+ "optional": true
5495
+ },
5496
+ "jiti": {
5497
+ "optional": true
5498
+ },
5499
+ "less": {
5500
+ "optional": true
5501
+ },
5502
+ "lightningcss": {
5503
+ "optional": true
5504
+ },
5505
+ "sass": {
5506
+ "optional": true
5507
+ },
5508
+ "sass-embedded": {
5509
+ "optional": true
5510
+ },
5511
+ "stylus": {
5512
+ "optional": true
5513
+ },
5514
+ "sugarss": {
5515
+ "optional": true
5516
+ },
5517
+ "terser": {
5518
+ "optional": true
5519
+ },
5520
+ "tsx": {
5521
+ "optional": true
5522
+ },
5523
+ "yaml": {
5524
+ "optional": true
5525
+ }
5526
+ }
5527
+ },
5528
+ "node_modules/vitefu": {
5529
+ "version": "1.1.1",
5530
+ "license": "MIT",
5531
+ "workspaces": [
5532
+ "tests/deps/*",
5533
+ "tests/projects/*",
5534
+ "tests/projects/workspace/packages/*"
5535
+ ],
5536
+ "peerDependencies": {
5537
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0"
5538
+ },
5539
+ "peerDependenciesMeta": {
5540
+ "vite": {
5541
+ "optional": true
5542
+ }
5543
+ }
5544
+ },
5545
+ "node_modules/web-namespaces": {
5546
+ "version": "2.0.1",
5547
+ "license": "MIT",
5548
+ "funding": {
5549
+ "type": "github",
5550
+ "url": "https://github.com/sponsors/wooorm"
5551
+ }
5552
+ },
5553
+ "node_modules/which-pm-runs": {
5554
+ "version": "1.1.0",
5555
+ "license": "MIT",
5556
+ "engines": {
5557
+ "node": ">=4"
5558
+ }
5559
+ },
5560
+ "node_modules/widest-line": {
5561
+ "version": "5.0.0",
5562
+ "license": "MIT",
5563
+ "dependencies": {
5564
+ "string-width": "^7.0.0"
5565
+ },
5566
+ "engines": {
5567
+ "node": ">=18"
5568
+ },
5569
+ "funding": {
5570
+ "url": "https://github.com/sponsors/sindresorhus"
5571
+ }
5572
+ },
5573
+ "node_modules/wrap-ansi": {
5574
+ "version": "9.0.2",
5575
+ "license": "MIT",
5576
+ "dependencies": {
5577
+ "ansi-styles": "^6.2.1",
5578
+ "string-width": "^7.0.0",
5579
+ "strip-ansi": "^7.1.0"
5580
+ },
5581
+ "engines": {
5582
+ "node": ">=18"
5583
+ },
5584
+ "funding": {
5585
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
5586
+ }
5587
+ },
5588
+ "node_modules/xxhash-wasm": {
5589
+ "version": "1.1.0",
5590
+ "license": "MIT"
5591
+ },
5592
+ "node_modules/yargs-parser": {
5593
+ "version": "21.1.1",
5594
+ "license": "ISC",
5595
+ "engines": {
5596
+ "node": ">=12"
5597
+ }
5598
+ },
5599
+ "node_modules/yocto-queue": {
5600
+ "version": "1.2.2",
5601
+ "license": "MIT",
5602
+ "engines": {
5603
+ "node": ">=12.20"
5604
+ },
5605
+ "funding": {
5606
+ "url": "https://github.com/sponsors/sindresorhus"
5607
+ }
5608
+ },
5609
+ "node_modules/yocto-spinner": {
5610
+ "version": "0.2.3",
5611
+ "license": "MIT",
5612
+ "dependencies": {
5613
+ "yoctocolors": "^2.1.1"
5614
+ },
5615
+ "engines": {
5616
+ "node": ">=18.19"
5617
+ },
5618
+ "funding": {
5619
+ "url": "https://github.com/sponsors/sindresorhus"
5620
+ }
5621
+ },
5622
+ "node_modules/yoctocolors": {
5623
+ "version": "2.1.2",
5624
+ "license": "MIT",
5625
+ "engines": {
5626
+ "node": ">=18"
5627
+ },
5628
+ "funding": {
5629
+ "url": "https://github.com/sponsors/sindresorhus"
5630
+ }
5631
+ },
5632
+ "node_modules/zod": {
5633
+ "version": "3.25.76",
5634
+ "license": "MIT",
5635
+ "funding": {
5636
+ "url": "https://github.com/sponsors/colinhacks"
5637
+ }
5638
+ },
5639
+ "node_modules/zod-to-json-schema": {
5640
+ "version": "3.25.1",
5641
+ "license": "ISC",
5642
+ "peerDependencies": {
5643
+ "zod": "^3.25 || ^4"
5644
+ }
5645
+ },
5646
+ "node_modules/zod-to-ts": {
5647
+ "version": "1.2.0",
5648
+ "peerDependencies": {
5649
+ "typescript": "^4.9.4 || ^5.0.2",
5650
+ "zod": "^3"
5651
+ }
5652
+ },
5653
+ "node_modules/zwitch": {
5654
+ "version": "2.0.4",
5655
+ "license": "MIT",
5656
+ "funding": {
5657
+ "type": "github",
5658
+ "url": "https://github.com/sponsors/wooorm"
5659
+ }
5660
+ }
5661
+ }
5662
+}
0
5663
▼public/logo-dark.svg
+29-0
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 72" fill="none" role="img" aria-labelledby="ochDocsLogoDarkTitle ochDocsLogoDarkDesc">
2
+ <title id="ochDocsLogoDarkTitle">OpenCodeHub logo</title>
3
+ <desc id="ochDocsLogoDarkDesc">OpenCodeHub wordmark with a rounded gradient code mark and connected hub node.</desc>
4
+ <defs>
5
+ <linearGradient id="ochDocsWordmarkDarkGradient" x1="10" y1="10" x2="62" y2="62" gradientUnits="userSpaceOnUse">
6
+ <stop offset="0" stop-color="#38BDF8"/>
7
+ <stop offset="0.52" stop-color="#8B5CF6"/>
8
+ <stop offset="1" stop-color="#EC4899"/>
9
+ </linearGradient>
10
+ <linearGradient id="ochDocsWordmarkDarkHighlight" x1="20" y1="16" x2="48" y2="52" gradientUnits="userSpaceOnUse">
11
+ <stop offset="0" stop-color="#FFFFFF" stop-opacity="0.34"/>
12
+ <stop offset="1" stop-color="#FFFFFF" stop-opacity="0.06"/>
13
+ </linearGradient>
14
+ </defs>
15
+ <g transform="translate(4 4)">
16
+ <rect x="8" y="4" width="56" height="56" rx="18" fill="url(#ochDocsWordmarkDarkGradient)"/>
17
+ <rect x="17" y="13" width="38" height="38" rx="13" fill="url(#ochDocsWordmarkDarkHighlight)" stroke="rgba(255,255,255,0.18)"/>
18
+ <path d="M31.5 23 23.5 32l8 9" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/>
19
+ <path d="m39 21-5 22" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round"/>
20
+ <path d="m40.5 23 8 9-8 9" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/>
21
+ <path d="M40 24.5 49.5 18" stroke="#E0F2FE" stroke-width="2.3" stroke-linecap="round" opacity="0.95"/>
22
+ <circle cx="52.5" cy="16" r="3.5" fill="#F8FAFC"/>
23
+ <circle cx="52.5" cy="16" r="1.4" fill="#7C3AED"/>
24
+ </g>
25
+ <text x="84" y="44" font-size="30" font-weight="700" font-family="Inter, ui-sans-serif, system-ui, sans-serif" letter-spacing="-0.045em">
26
+ <tspan fill="#64748B">Open</tspan>
27
+ <tspan dx="8" fill="#0F172A">CodeHub</tspan>
28
+ </text>
29
+</svg>
0
30
▼public/logo-light.svg
+29-0
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 72" fill="none" role="img" aria-labelledby="ochDocsLogoLightTitle ochDocsLogoLightDesc">
2
+ <title id="ochDocsLogoLightTitle">OpenCodeHub logo</title>
3
+ <desc id="ochDocsLogoLightDesc">OpenCodeHub wordmark with a rounded gradient code mark and connected hub node.</desc>
4
+ <defs>
5
+ <linearGradient id="ochDocsWordmarkLightGradient" x1="10" y1="10" x2="62" y2="62" gradientUnits="userSpaceOnUse">
6
+ <stop offset="0" stop-color="#38BDF8"/>
7
+ <stop offset="0.52" stop-color="#8B5CF6"/>
8
+ <stop offset="1" stop-color="#EC4899"/>
9
+ </linearGradient>
10
+ <linearGradient id="ochDocsWordmarkLightHighlight" x1="20" y1="16" x2="48" y2="52" gradientUnits="userSpaceOnUse">
11
+ <stop offset="0" stop-color="#FFFFFF" stop-opacity="0.34"/>
12
+ <stop offset="1" stop-color="#FFFFFF" stop-opacity="0.06"/>
13
+ </linearGradient>
14
+ </defs>
15
+ <g transform="translate(4 4)">
16
+ <rect x="8" y="4" width="56" height="56" rx="18" fill="url(#ochDocsWordmarkLightGradient)"/>
17
+ <rect x="17" y="13" width="38" height="38" rx="13" fill="url(#ochDocsWordmarkLightHighlight)" stroke="rgba(255,255,255,0.18)"/>
18
+ <path d="M31.5 23 23.5 32l8 9" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/>
19
+ <path d="m39 21-5 22" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round"/>
20
+ <path d="m40.5 23 8 9-8 9" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/>
21
+ <path d="M40 24.5 49.5 18" stroke="#E0F2FE" stroke-width="2.3" stroke-linecap="round" opacity="0.95"/>
22
+ <circle cx="52.5" cy="16" r="3.5" fill="#F8FAFC"/>
23
+ <circle cx="52.5" cy="16" r="1.4" fill="#7C3AED"/>
24
+ </g>
25
+ <text x="84" y="44" font-size="30" font-weight="700" font-family="Inter, ui-sans-serif, system-ui, sans-serif" letter-spacing="-0.045em">
26
+ <tspan fill="#CBD5E1">Open</tspan>
27
+ <tspan dx="8" fill="#F8FAFC">CodeHub</tspan>
28
+ </text>
29
+</svg>
0
30
▼src/assets/logo-dark.svg
+29-0
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 72" fill="none" role="img" aria-labelledby="ochDocsAssetLogoDarkTitle ochDocsAssetLogoDarkDesc">
2
+ <title id="ochDocsAssetLogoDarkTitle">OpenCodeHub logo</title>
3
+ <desc id="ochDocsAssetLogoDarkDesc">OpenCodeHub wordmark with a rounded gradient code mark and connected hub node.</desc>
4
+ <defs>
5
+ <linearGradient id="ochDocsAssetWordmarkDarkGradient" x1="10" y1="10" x2="62" y2="62" gradientUnits="userSpaceOnUse">
6
+ <stop offset="0" stop-color="#38BDF8"/>
7
+ <stop offset="0.52" stop-color="#8B5CF6"/>
8
+ <stop offset="1" stop-color="#EC4899"/>
9
+ </linearGradient>
10
+ <linearGradient id="ochDocsAssetWordmarkDarkHighlight" x1="20" y1="16" x2="48" y2="52" gradientUnits="userSpaceOnUse">
11
+ <stop offset="0" stop-color="#FFFFFF" stop-opacity="0.34"/>
12
+ <stop offset="1" stop-color="#FFFFFF" stop-opacity="0.06"/>
13
+ </linearGradient>
14
+ </defs>
15
+ <g transform="translate(4 4)">
16
+ <rect x="8" y="4" width="56" height="56" rx="18" fill="url(#ochDocsAssetWordmarkDarkGradient)"/>
17
+ <rect x="17" y="13" width="38" height="38" rx="13" fill="url(#ochDocsAssetWordmarkDarkHighlight)" stroke="rgba(255,255,255,0.18)"/>
18
+ <path d="M31.5 23 23.5 32l8 9" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/>
19
+ <path d="m39 21-5 22" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round"/>
20
+ <path d="m40.5 23 8 9-8 9" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/>
21
+ <path d="M40 24.5 49.5 18" stroke="#E0F2FE" stroke-width="2.3" stroke-linecap="round" opacity="0.95"/>
22
+ <circle cx="52.5" cy="16" r="3.5" fill="#F8FAFC"/>
23
+ <circle cx="52.5" cy="16" r="1.4" fill="#7C3AED"/>
24
+ </g>
25
+ <text x="84" y="44" font-size="30" font-weight="700" font-family="Inter, ui-sans-serif, system-ui, sans-serif" letter-spacing="-0.045em">
26
+ <tspan fill="#64748B">Open</tspan>
27
+ <tspan dx="8" fill="#0F172A">CodeHub</tspan>
28
+ </text>
29
+</svg>
0
30
▼src/assets/logo-light.svg
+29-0
1
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 72" fill="none" role="img" aria-labelledby="ochDocsAssetLogoLightTitle ochDocsAssetLogoLightDesc">
2
+ <title id="ochDocsAssetLogoLightTitle">OpenCodeHub logo</title>
3
+ <desc id="ochDocsAssetLogoLightDesc">OpenCodeHub wordmark with a rounded gradient code mark and connected hub node.</desc>
4
+ <defs>
5
+ <linearGradient id="ochDocsAssetWordmarkLightGradient" x1="10" y1="10" x2="62" y2="62" gradientUnits="userSpaceOnUse">
6
+ <stop offset="0" stop-color="#38BDF8"/>
7
+ <stop offset="0.52" stop-color="#8B5CF6"/>
8
+ <stop offset="1" stop-color="#EC4899"/>
9
+ </linearGradient>
10
+ <linearGradient id="ochDocsAssetWordmarkLightHighlight" x1="20" y1="16" x2="48" y2="52" gradientUnits="userSpaceOnUse">
11
+ <stop offset="0" stop-color="#FFFFFF" stop-opacity="0.34"/>
12
+ <stop offset="1" stop-color="#FFFFFF" stop-opacity="0.06"/>
13
+ </linearGradient>
14
+ </defs>
15
+ <g transform="translate(4 4)">
16
+ <rect x="8" y="4" width="56" height="56" rx="18" fill="url(#ochDocsAssetWordmarkLightGradient)"/>
17
+ <rect x="17" y="13" width="38" height="38" rx="13" fill="url(#ochDocsAssetWordmarkLightHighlight)" stroke="rgba(255,255,255,0.18)"/>
18
+ <path d="M31.5 23 23.5 32l8 9" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/>
19
+ <path d="m39 21-5 22" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round"/>
20
+ <path d="m40.5 23 8 9-8 9" stroke="#F8FAFC" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/>
21
+ <path d="M40 24.5 49.5 18" stroke="#E0F2FE" stroke-width="2.3" stroke-linecap="round" opacity="0.95"/>
22
+ <circle cx="52.5" cy="16" r="3.5" fill="#F8FAFC"/>
23
+ <circle cx="52.5" cy="16" r="1.4" fill="#7C3AED"/>
24
+ </g>
25
+ <text x="84" y="44" font-size="30" font-weight="700" font-family="Inter, ui-sans-serif, system-ui, sans-serif" letter-spacing="-0.045em">
26
+ <tspan fill="#CBD5E1">Open</tspan>
27
+ <tspan dx="8" fill="#F8FAFC">CodeHub</tspan>
28
+ </text>
29
+</svg>
0
30
▼src/content/docs/FREE-DEPLOYMENT.md
+399-0
1
+---
2
+title: "Free Deployment Options"
3
+---
4
+
5
+# OpenCodeHub — Free Deployment Options
6
+
7
+> Deploy OpenCodeHub for free with persistent file storage for git repositories.
8
+
9
+---
10
+
11
+## Quick Comparison
12
+
13
+| Platform | Cost | Storage | RAM | CPU | Best For |
14
+|----------|------|---------|-----|-----|----------|
15
+| **Oracle Cloud Free** | $0 forever | 200GB | 24GB | 4 ARM cores | Best overall |
16
+| **Home Server/NAS** | $0 | Unlimited | Your hardware | Your hardware | Privacy-focused |
17
+| **Fly.io** | $0 (limited) | 3GB free | 256MB | Shared | Quick testing |
18
+| **Google Cloud Free** | $0 forever | 30GB | 1GB | 0.25 vCPU | Light usage |
19
+| **Railway** | $5 trial | 1GB | 512MB | Shared | Quick demo |
20
+| **Hetzner** | ~€4/mo | 40GB | 4GB | 2 vCPU | Best value paid |
21
+
22
+---
23
+
24
+## Option 1: Oracle Cloud Free Tier (Recommended)
25
+
26
+**Always Free** — No credit card charge, no time limit.
27
+
28
+### What You Get
29
+- 4 ARM cores (Ampere A1)
30
+- 24 GB RAM
31
+- 200 GB boot volume
32
+- 2 x 1TB block volumes (total 2TB)
33
+- Free PostgreSQL database
34
+- Free Redis
35
+
36
+### Steps
37
+
38
+```bash
39
+# 1. Sign up at cloud.oracle.com
40
+# 2. Create a VM instance:
41
+# - Name: opencodehub
42
+# - Image: Ubuntu 22.04
43
+# - Shape: VM.Standard.A1.Flex (4 OCPU, 24 GB RAM)
44
+# - Upload SSH key
45
+# - Create boot volume: 100 GB
46
+
47
+# 3. SSH into your instance
48
+ssh -i ~/.ssh/key ubuntu@YOUR_PUBLIC_IP
49
+
50
+# 4. Install Docker
51
+curl -fsSL https://get.docker.com -o get-docker.sh
52
+sudo sh get-docker.sh
53
+sudo usermod -aG docker $USER
54
+
55
+# 5. Install Docker Compose
56
+sudo apt install docker-compose-plugin -y
57
+
58
+# 6. Clone OpenCodeHub
59
+git clone https://github.com/swadhinbiswas/OpencodeHub.git
60
+cd OpencodeHub
61
+
62
+# 7. Configure
63
+cp .env.example .env
64
+nano .env # Edit secrets
65
+
66
+# 8. Start
67
+sudo docker compose up -d
68
+
69
+# 9. Create admin
70
+sudo docker compose exec app bun run scripts/seed-admin.ts
71
+```
72
+
73
+### Access Your Instance
74
+```
75
+Web: http://YOUR_PUBLIC_IP:4321
76
+SSH: ssh://git@YOUR_PUBLIC_IP:2222/owner/repo.git
77
+HTTPS: Set up Nginx + Let's Encrypt (free)
78
+```
79
+
80
+---
81
+
82
+## Option 2: Home Server / NAS
83
+
84
+**$0 forever** — Use hardware you already own.
85
+
86
+### What You Need
87
+- Any computer running Linux/Mac/Windows
88
+- 2GB+ RAM recommended
89
+- 20GB+ free disk space
90
+
91
+### Quick Start (Linux/Mac)
92
+
93
+```bash
94
+# Install Docker
95
+curl -fsSL https://get.docker.com | sh
96
+
97
+# Clone and start
98
+git clone https://github.com/swadhinbiswas/OpencodeHub.git
99
+cd OpencodeHub
100
+cp .env.example .env
101
+nano .env # Set secrets
102
+docker compose up -d
103
+
104
+# Create admin
105
+docker compose exec app bun run scripts/seed-admin.ts
106
+```
107
+
108
+### NAS Deployment
109
+
110
+**Synology / TrueNAS / QNAP:**
111
+1. Install Docker from Package Center
112
+2. Use Docker Compose or Portainer
113
+3. Mount a shared folder for `/data`
114
+
115
+### Access from Anywhere
116
+- **Tailscale** (free): `tailscale up` → access via Tailscale IP
117
+- **Cloudflare Tunnel** (free): Expose without opening ports
118
+- **Port forwarding**: Open port 4321 on your router
119
+
120
+---
121
+
122
+## Option 3: Fly.io Free Tier
123
+
124
+**Free** — 3GB persistent volume included.
125
+
126
+### Steps
127
+
128
+```bash
129
+# 1. Install flyctl
130
+curl -L https://fly.io/install.sh | sh
131
+
132
+# 2. Login
133
+fly auth login
134
+
135
+# 3. Launch
136
+fly launch --name opencodehub
137
+
138
+# 4. Add persistent volume
139
+fly volume create opencodehub_data --region sjc --size 3
140
+
141
+# 5. Set secrets
142
+fly secrets set JWT_SECRET=$(openssl rand -hex 32)
143
+fly secrets set SESSION_SECRET=$(openssl rand -hex 32)
144
+fly secrets set DATABASE_URL="postgresql://..."
145
+fly secrets set REDIS_URL="redis://..."
146
+
147
+# 6. Deploy
148
+fly deploy
149
+```
150
+
151
+### Limitations
152
+- 3GB storage (enough for small repos)
153
+- 256MB RAM (may be slow for large repos)
154
+- Apps休眠 after inactivity (cold starts take ~30s)
155
+
156
+---
157
+
158
+## Option 4: Google Cloud Free Tier
159
+
160
+**Always Free** — e2-micro instance.
161
+
162
+### Steps
163
+
164
+```bash
165
+# 1. Sign up at cloud.google.com
166
+# 2. Create e2-micro VM:
167
+# - Machine type: e2-micro (0.25 vCPU, 1GB RAM)
168
+# - Boot disk: 30GB SSD (free)
169
+# - Firewall: Allow HTTP (80), SSH (22)
170
+
171
+# 3. SSH in and install Docker
172
+ssh -i ~/.ssh/key USER@EXTERNAL_IP
173
+sudo apt update && sudo apt install docker.io docker-compose-plugin -y
174
+
175
+# 4. Deploy OpenCodeHub
176
+git clone https://github.com/swadhinbiswas/OpencodeHub.git
177
+cd OpencodeHub
178
+cp .env.example .env
179
+nano .env
180
+docker compose up -d
181
+```
182
+
183
+### Limitations
184
+- Only 1GB RAM (tight for production)
185
+- 0.25 vCPU (slow builds)
186
+- Good for personal/light use
187
+
188
+---
189
+
190
+## Option 5: Self-Hosted on Existing VPS
191
+
192
+If you already have a VPS (Hetzner, DigitalOcean, Linode, etc.):
193
+
194
+```bash
195
+# SSH into your server
196
+ssh root@YOUR_SERVER_IP
197
+
198
+# One-line install
199
+curl -fsSL https://raw.githubusercontent.com/swadhinbiswas/OpencodeHub/main/install.sh | bash
200
+```
201
+
202
+---
203
+
204
+## Option 6: Docker on Windows/Mac
205
+
206
+For local development or personal use:
207
+
208
+```bash
209
+# Install Docker Desktop for Windows/Mac
210
+# https://docs.docker.com/get-docker/
211
+
212
+# Clone and start
213
+git clone https://github.com/swadhinbiswas/OpencodeHub.git
214
+cd OpencodeHub
215
+cp .env.example .env
216
+nano .env
217
+docker compose up -d
218
+
219
+# Create admin
220
+docker compose exec app bun run scripts/seed-admin.ts
221
+```
222
+
223
+---
224
+
225
+## Storage Configuration
226
+
227
+### Local Storage (Default)
228
+```bash
229
+STORAGE_TYPE=local
230
+STORAGE_PATH=/data/storage
231
+GIT_REPOS_PATH=/data/repositories
232
+```
233
+
234
+### S3-Compatible (MinIO on same server)
235
+```bash
236
+# Add to docker-compose.yml:
237
+minio:
238
+ image: minio/minio
239
+ command: server /data --console-address ":9001"
240
+ volumes:
241
+ - ./data/minio:/data
242
+ ports:
243
+ - "9001:9001"
244
+
245
+STORAGE_TYPE=s3
246
+STORAGE_ENDPOINT=http://minio:9000
247
+STORAGE_BUCKET=opencodehub
248
+STORAGE_ACCESS_KEY_ID=minioadmin
249
+STORAGE_SECRET_ACCESS_KEY=minioadmin
250
+```
251
+
252
+---
253
+
254
+## HTTPS Setup (Free)
255
+
256
+### With Let's Encrypt + Nginx
257
+
258
+```bash
259
+# Install Nginx and Certbot
260
+sudo apt install nginx certbot python3-certbot-nginx -y
261
+
262
+# Create Nginx config
263
+sudo nano /etc/nginx/sites-available/opencodehub
264
+```
265
+
266
+```nginx
267
+server {
268
+ listen 80;
269
+ server_name git.yourdomain.com;
270
+ return 301 https://$host$request_uri;
271
+}
272
+
273
+server {
274
+ listen 443 ssl http2;
275
+ server_name git.yourdomain.com;
276
+
277
+ ssl_certificate /etc/letsencrypt/live/git.yourdomain.com/fullchain.pem;
278
+ ssl_certificate_key /etc/letsencrypt/live/git.yourdomain.com/privkey.pem;
279
+
280
+ client_max_body_size 500M;
281
+
282
+ location / {
283
+ proxy_pass http://localhost:4321;
284
+ proxy_set_header Host $host;
285
+ proxy_set_header X-Real-IP $remote_addr;
286
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
287
+ proxy_set_header X-Forwarded-Proto $scheme;
288
+ }
289
+
290
+ # WebSocket support
291
+ location /api/realtime {
292
+ proxy_pass http://localhost:4321;
293
+ proxy_http_version 1.1;
294
+ proxy_set_header Upgrade $http_upgrade;
295
+ proxy_set_header Connection "upgrade";
296
+ }
297
+}
298
+```
299
+
300
+```bash
301
+# Enable and get SSL
302
+sudo ln -s /etc/nginx/sites-available/opencodehub /etc/nginx/sites-enabled/
303
+sudo certbot --nginx -d git.yourdomain.com
304
+```
305
+
306
+---
307
+
308
+## Environment Variables (Production)
309
+
310
+```bash
311
+# Generate all secrets
312
+JWT_SECRET=$(openssl rand -hex 32)
313
+SESSION_SECRET=$(openssl rand -hex 32)
314
+INTERNAL_HOOK_SECRET=$(openssl rand -hex 32)
315
+CRON_SECRET=$(openssl rand -hex 32)
316
+RUNNER_SECRET=$(openssl rand -hex 32)
317
+AI_CONFIG_ENCRYPTION_KEY=$(openssl rand -hex 32)
318
+WORKFLOW_SECRET_ENCRYPTION_KEY=$(openssl rand -hex 32)
319
+
320
+# Your .env file
321
+DATABASE_DRIVER=postgres
322
+DATABASE_URL=postgresql://opencodehub:PASSWORD@localhost:5432/opencodehub
323
+DATABASE_SSL=false
324
+REDIS_URL=redis://localhost:6379
325
+SITE_URL=https://git.yourdomain.com
326
+STORAGE_TYPE=local
327
+GIT_REPOS_PATH=/data/repositories
328
+NODE_ENV=production
329
+```
330
+
331
+---
332
+
333
+## Backup Strategy
334
+
335
+### Automated Backup Script
336
+```bash
337
+#!/bin/bash
338
+# backup.sh — Run daily via cron
339
+BACKUP_DIR="/backups/$(date +%Y-%m-%d)"
340
+mkdir -p "$BACKUP_DIR"
341
+
342
+# Database dump
343
+docker compose exec -T postgres pg_dump -U opencodehub opencodehub > "$BACKUP_DIR/db.sql"
344
+
345
+# Git repos
346
+tar czf "$BACKUP_DIR/repos.tar.gz" ./data/repositories/
347
+
348
+# Upload to S3 (optional)
349
+# aws s3 sync "$BACKUP_DIR" s3://your-backup-bucket/opencodehub/
350
+```
351
+
352
+### Cron Job
353
+```bash
354
+# Add to crontab
355
+crontab -e
356
+0 2 * * * /path/to/backup.sh
357
+```
358
+
359
+---
360
+
361
+## Monitoring
362
+
363
+### Health Check
364
+```bash
365
+# Check if app is running
366
+curl -f http://localhost:4321/api/health || echo "DOWN"
367
+
368
+# Check Docker status
369
+docker compose ps
370
+docker compose logs --tail=50 app
371
+```
372
+
373
+### Uptime Robot (Free)
374
+1. Sign up at uptimerobot.com
375
+2. Add HTTP monitor: `http://YOUR_IP:4321/api/health`
376
+3. Get notified if your instance goes down
377
+
378
+---
379
+
380
+## Recommended Free Setup
381
+
382
+For a **personal Git server** that stores all your code:
383
+
384
+| Component | Choice |
385
+|-----------|--------|
386
+| **Cloud** | Oracle Cloud Free Tier |
387
+| **Server** | ARM A1 (4 cores, 24GB RAM) |
388
+| **Storage** | 100GB boot + 1TB block volume |
389
+| **Database** | PostgreSQL (Docker) |
390
+| **Cache** | Redis (Docker) |
391
+| **HTTPS** | Nginx + Let's Encrypt |
392
+| **Access** | Tailscale (private) or port forwarding |
393
+| **Backups** | Cron script + local S3 |
394
+
395
+**Total cost: $0/month forever.**
396
+
397
+---
398
+
399
+*Generated for OpenCodeHub free deployment.*
0
400
▼src/content/docs/RENDER-DEPLOYMENT.md
+167-0
1
+---
2
+title: "Render Deployment Guide"
3
+---
4
+
5
+# OpenCodeHub — Render Deployment Guide
6
+
7
+> Deploy to Render (Singapore) with free PostgreSQL + Upstash Redis. $0/month.
8
+
9
+---
10
+
11
+## What You Get
12
+
13
+- OpenCodeHub running in Asia (Singapore)
14
+- Free PostgreSQL database
15
+- Free Redis via Upstash
16
+- 1GB persistent storage for git repos
17
+- HTTPS included
18
+- Admin account
19
+
20
+---
21
+
22
+## Step 1: Create Upstash Redis (2 min)
23
+
24
+1. Go to **https://upstash.com** → Sign up (free)
25
+2. Click **Create Database**
26
+3. Settings:
27
+ - **Name**: `opencodehub`
28
+ - **Region**: **Asia Pacific (Singapore)**
29
+ - **Plan**: Pay as you go (free tier: 10K commands/day)
30
+4. Click **Create**
31
+5. Copy the **Redis URL** (looks like `rediss://...@...`)
32
+6. Keep this tab open — you'll need it in Step 3
33
+
34
+---
35
+
36
+## Step 2: Deploy to Render (5 min)
37
+
38
+1. Go to **https://render.com** → Sign up (free)
39
+2. Click **New** → **Blueprint**
40
+3. Connect your GitHub account
41
+4. Select your OpenCodeHub repository
42
+5. Render detects `render.yaml` and shows:
43
+ - `opencodehub-db` (PostgreSQL — Singapore)
44
+ - `opencodehub` (Web Service — Singapore)
45
+6. Click **Apply**
46
+7. Wait for deployment (~3-5 min first time)
47
+
48
+---
49
+
50
+## Step 3: Set Redis URL (1 min)
51
+
52
+1. Go to your Web Service → **Environment** tab
53
+2. Find `REDIS_URL` (shows "Not set")
54
+3. Click the pencil icon → Paste your **Upstash Redis URL**
55
+4. Click **Save**
56
+
57
+---
58
+
59
+## Step 4: Set Site URL (1 min)
60
+
61
+1. In the same **Environment** tab
62
+2. Find `SITE_URL` (shows "Not set")
63
+3. Click the pencil icon → Enter your Render URL:
64
+ ```
65
+ https://opencodehub.onrender.com
66
+ ```
67
+ (Replace with your actual URL from the service overview)
68
+4. Click **Save**
69
+
70
+---
71
+
72
+## Step 5: Manual Deploy
73
+
74
+1. Go to your Web Service → **Manual Deploy**
75
+2. Click **Deploy latest commit**
76
+3. Wait for build to complete (~2-3 min)
77
+4. Click the **URL** at the top to open your instance
78
+
79
+---
80
+
81
+## Step 6: Create Admin Account
82
+
83
+You'll see the **Setup Wizard**. Fill in:
84
+
85
+| Field | Value |
86
+|-------|-------|
87
+| Username | `admin` (or your choice) |
88
+| Email | Your email |
89
+| Password | Strong password |
90
+
91
+Click **Create Account** — you're now logged in as admin!
92
+
93
+---
94
+
95
+## Step 7: Test It
96
+
97
+```bash
98
+# Create a repo via web UI, then clone:
99
+git clone https://opencodehub.onrender.com/your-username/my-repo.git
100
+
101
+# Push code:
102
+cd my-repo
103
+echo "# Hello" > README.md
104
+git add . && git commit -m "Initial"
105
+git push origin main
106
+```
107
+
108
+---
109
+
110
+## Done! Summary
111
+
112
+| Component | Service | Region | Cost |
113
+|-----------|---------|--------|------|
114
+| App | Render Free | Singapore | $0 |
115
+| PostgreSQL | Render Free | Singapore | $0 |
116
+| Redis | Upstash Free | Singapore | $0 |
117
+| Storage | Render Disk 1GB | Singapore | $0 |
118
+| **Total** | | | **$0/month** |
119
+
120
+---
121
+
122
+## Keep Alive (Optional)
123
+
124
+Render free tier spins down after 15min inactivity. To prevent:
125
+
126
+1. Go to **https://uptimerobot.com** → Sign up (free)
127
+2. Add Monitor → Type: HTTP(s)
128
+3. URL: `https://opencodehub.onrender.com/api/health`
129
+4. Monitoring interval: 5 minutes
130
+5. Save — your app stays awake
131
+
132
+---
133
+
134
+## Upgrade Path (When You Grow)
135
+
136
+| Need | Upgrade | Cost |
137
+|------|---------|------|
138
+| Always-on (no spin-down) | Render Starter | $7/mo |
139
+| More storage (10GB+) | Render Disk upgrade | $1-7/mo |
140
+| More Redis commands | Upstash Pay-as-you-go | ~$0.20/10K |
141
+| PostgreSQL expiry | Render Starter DB | $7/mo |
142
+
143
+---
144
+
145
+## Troubleshooting
146
+
147
+**App won't start?**
148
+- Check **Logs** tab in Render
149
+- Verify `REDIS_URL` is set correctly
150
+- Ensure `SITE_URL` matches your Render URL
151
+
152
+**Redis connection failed?**
153
+- Verify Redis URL from Upstash (starts with `rediss://`)
154
+- Check Upstash dashboard shows "Active"
155
+- Ensure region is Singapore
156
+
157
+**Git clone fails?**
158
+- Use HTTPS: `git clone https://your-url.onrender.com/user/repo.git`
159
+- SSH not available on Render free tier (use HTTPS)
160
+
161
+**Slow first request?**
162
+- Normal for free tier (cold start ~30s)
163
+- Add UptimeRobot ping to keep it warm
164
+
165
+---
166
+
167
+*OpenCodeHub — Deployed on Render, Asia Region, $0/month.*
0
168
▼src/content/docs/administration/circleci-cloud.md
+431-0
1
+---
2
+title: "Run Workers on CircleCI Cloud"
3
+description: "Run OpenCodeHub background workers using managed CircleCI Cloud with external PostgreSQL and Redis"
4
+---
5
+
6
+> **Platform:** CircleCI Cloud (managed SaaS) | **Database:** PostgreSQL | **Difficulty:** Easy-Medium
7
+
8
+This guide is specifically for **CircleCI Cloud** (the managed service at circleci.com), NOT self-hosted runners. If you want to use self-hosted runners, see [CircleCI Self-Hosted Runner Guide](/administration/circleci-worker/).
9
+
10
+---
11
+
12
+## How CircleCI Cloud Works for Workers
13
+
14
+CircleCI Cloud runs jobs in **ephemeral Docker containers** that are destroyed after the job ends. This is fundamentally different from a traditional background worker:
15
+
16
+| Feature | Traditional Worker | CircleCI Cloud |
17
+|---------|-------------------|----------------|
18
+| Lifetime | Runs forever | Max 5 hours per job |
19
+| Storage | Persistent disk | Ephemeral (lost after job) |
20
+| Database | Local or network | Must be external (network-accessible) |
21
+| Redis | Local or network | Must be external |
22
+| Cost | Server rental | Compute minutes |
23
+
24
+**Bottom line:** CircleCI Cloud workers run in short bursts and connect to external services. This is actually perfect for OpenCodeHub's architecture because the worker code is stateless — all state lives in PostgreSQL + Redis.
25
+
26
+---
27
+
28
+## Prerequisites
29
+
30
+Before you start, you need:
31
+
32
+1. **CircleCI Account** (free tier works)
33
+2. **External PostgreSQL** database (required — local DB won't persist)
34
+3. **External Redis** (required — local Redis won't persist)
35
+4. **Git repository** pushed to GitHub/GitLab/Bitbucket (CircleCI connects to it)
36
+
37
+### Recommended PostgreSQL Providers
38
+
39
+| Provider | Free Tier | Best For |
40
+|----------|-----------|----------|
41
+| **Supabase** | 500MB, 2GB egress | Full-featured, good dashboard |
42
+| **Neon** | 500MB, 3 databases | Serverless, scales to zero |
43
+| **Railway** | $5 credit | Simple, pay-as-you-go |
44
+| **Render** | 1GB | Easy setup |
45
+| **AWS RDS** | None | Enterprise |
46
+
47
+### Recommended Redis Providers
48
+
49
+| Provider | Free Tier | Best For |
50
+|----------|-----------|----------|
51
+| **Upstash** | 10,000 commands/day | Serverless, HTTP API |
52
+| **Redis Cloud** | 30MB | Managed Redis |
53
+| **Railway** | $5 credit | Easy setup |
54
+| **KeyDB** | Self-host | Performance |
55
+
56
+---
57
+
58
+## Step 1: Set Up External PostgreSQL
59
+
60
+### Using Supabase (Recommended)
61
+
62
+1. Go to [supabase.com](https://supabase.com) and create a project
63
+2. In **Project Settings** → **Database**, copy the connection string:
64
+ ```
65
+ postgresql://postgres:[password]@db.xxxxxxxxxx.supabase.co:5432/postgres
66
+ ```
67
+3. Create the `opencodehub` database:
68
+ ```sql
69
+ CREATE DATABASE opencodehub;
70
+ ```
71
+
72
+### Using Neon
73
+
74
+1. Go to [neon.tech](https://neon.tech) and create a project
75
+2. Copy the connection string from the dashboard
76
+3. Create the database:
77
+ ```sql
78
+ CREATE DATABASE opencodehub;
79
+ ```
80
+
81
+---
82
+
83
+## Step 2: Set Up External Redis
84
+
85
+### Using Upstash (Recommended for Serverless)
86
+
87
+1. Go to [upstash.com](https://upstash.com) and create a Redis database
88
+2. Copy the **Redis URL**:
89
+ ```
90
+ rediss://default:[password]@xxxx.upstash.io:6379
91
+ ```
92
+3. Enable **TLS** (Upstash requires it)
93
+
94
+---
95
+
96
+## Step 3: Configure CircleCI Project
97
+
98
+### 3.1 Connect Repository
99
+
100
+1. Go to [app.circleci.com](https://app.circleci.com)
101
+2. Click **Projects** → **Set Up Project**
102
+3. Select your OpenCodeHub repository
103
+4. CircleCI will detect `.circleci/config.yml`
104
+
105
+### 3.2 Create a Context (Recommended)
106
+
107
+Contexts let you share environment variables across jobs securely.
108
+
109
+1. Go to **Organization Settings** → **Contexts**
110
+2. Click **Create Context**
111
+3. Name it: `opencodehub-production`
112
+4. Add these environment variables:
113
+
114
+| Variable | Value | Description |
115
+|----------|-------|-------------|
116
+| `DATABASE_URL` | `postgresql://...` | Your PostgreSQL connection string |
117
+| `DATABASE_DRIVER` | `postgres` | Explicitly set driver |
118
+| `REDIS_URL` | `redis://...` or `rediss://...` | Your Redis URL |
119
+| `JWT_SECRET` | `openssl rand -hex 32` | Generate this |
120
+| `SESSION_SECRET` | `openssl rand -hex 32` | Generate this |
121
+| `INTERNAL_HOOK_SECRET` | `openssl rand -hex 32` | Generate this |
122
+| `CRON_SECRET` | `openssl rand -hex 32` | Generate this |
123
+| `RUNNER_SECRET` | `openssl rand -hex 32` | Generate this |
124
+| `WORKFLOW_SECRET_ENCRYPTION_KEY` | `openssl rand -hex 32` | Generate this |
125
+| `SITE_URL` | `https://git.yourdomain.com` | Your OpenCodeHub URL |
126
+| `SKIP_REDIS_CHECK` | `1` | Skip Redis check during build |
127
+
128
+> **Security:** Never commit these values to git. Always use CircleCI contexts or project environment variables.
129
+
130
+### 3.3 Alternative: Project-Level Environment Variables
131
+
132
+If you don't want to use contexts:
133
+
134
+1. Go to **Project Settings** → **Environment Variables**
135
+2. Add each variable individually
136
+
137
+---
138
+
139
+## Step 4: Initialize Database Schema
140
+
141
+Before the worker can run, the database schema must exist. Run this once:
142
+
143
+```bash
144
+# On your local machine with DATABASE_URL set
145
+export DATABASE_URL="postgresql://postgres:[password]@db.xxxxxxxxxx.supabase.co:5432/opencodehub"
146
+
147
+# Install dependencies
148
+bun install
149
+
150
+# Push schema to database
151
+bun run db:push
152
+
153
+# Or generate and run migrations
154
+bun run db:generate
155
+bun run db:migrate
156
+
157
+# Create admin user
158
+bun run scripts/seed-admin.ts
159
+```
160
+
161
+> **Important:** Do this from your local machine or a one-time job. The CircleCI worker job won't create the schema automatically.
162
+
163
+---
164
+
165
+## Step 5: Understanding the CircleCI Cloud Config
166
+
167
+The `.circleci/config.yml` in your repo has multiple approaches:
168
+
169
+### Option A: Scheduled Tasks (Recommended for Free Plan)
170
+
171
+Jobs run on a cron schedule. Each job starts, does its work, and exits.
172
+
173
+```yaml
174
+workflows:
175
+ scheduled-merge-queue:
176
+ triggers:
177
+ - schedule:
178
+ cron: "*/15 * * * *" # Every 15 minutes
179
+ jobs:
180
+ - merge-queue:
181
+ context: opencodehub-production
182
+```
183
+
184
+**What happens:**
185
+1. CircleCI starts a Docker container every 15 minutes
186
+2. Installs Bun and dependencies
187
+3. Runs `bun run scripts/worker.ts` for 30 minutes
188
+4. Processes all pending merge queue items
189
+5. Container is destroyed
190
+
191
+**Pros:** Works on free plan, reliable, no timeouts
192
+**Cons:** 15-minute delay between processing (jobs only run on schedule)
193
+
194
+### Option B: Continuous Worker (Performance Plan)
195
+
196
+One long-running job that stays active until timeout.
197
+
198
+```yaml
199
+workflows:
200
+ worker-continuous:
201
+ jobs:
202
+ - worker:
203
+ context: opencodehub-production
204
+```
205
+
206
+**What happens:**
207
+1. CircleCI starts a container
208
+2. Worker runs continuously, processing items every 5 seconds
209
+3. Job runs until the 5-hour timeout
210
+4. CircleCI restarts the job automatically
211
+
212
+**Pros:** Near real-time processing
213
+**Cons:** Requires Performance plan (5h jobs), uses more compute minutes
214
+
215
+### Option C: API-Triggered (Event-Driven)
216
+
217
+OpenCodeHub calls CircleCI API when events happen.
218
+
219
+In your OpenCodeHub webhook handler:
220
+
221
+```typescript
222
+// When merge queue needs processing
223
+async function triggerCircleCIWorker(eventType: string, repoId: string) {
224
+ const response = await fetch(
225
+ `https://circleci.com/api/v2/project/gh/${org}/${repo}/pipeline`,
226
+ {
227
+ method: "POST",
228
+ headers: {
229
+ "Circle-Token": process.env.CIRCLECI_API_TOKEN!,
230
+ "Content-Type": "application/json",
231
+ },
232
+ body: JSON.stringify({
233
+ branch: "main",
234
+ parameters: {
235
+ event_type: eventType,
236
+ repo_id: repoId,
237
+ },
238
+ }),
239
+ }
240
+ );
241
+ return response.json();
242
+}
243
+```
244
+
245
+**Pros:** Only runs when needed, most efficient
246
+**Cons:** Requires code changes in OpenCodeHub, more complex setup
247
+
248
+---
249
+
250
+## Step 6: Choose Your Plan
251
+
252
+### Free Plan (Recommended to Start)
253
+
254
+```yaml
255
+workflows:
256
+ scheduled-merge-queue:
257
+ triggers:
258
+ - schedule:
259
+ cron: "*/15 * * * *" # Every 15 min
260
+ jobs:
261
+ - merge-queue:
262
+ context: opencodehub-production
263
+```
264
+
265
+**Monthly usage:** ~2,880 minutes (48 runs/day × 30 days × 2 min avg)
266
+**Free tier:** 6,000 minutes/month ✅
267
+
268
+### Performance Plan (For Production)
269
+
270
+```yaml
271
+workflows:
272
+ worker-continuous:
273
+ jobs:
274
+ - worker:
275
+ context: opencodehub-production
276
+```
277
+
278
+**Monthly usage:** ~7,200 minutes (5h × 24/day × 30 days)
279
+**Performance plan:** Included in price
280
+
281
+---
282
+
283
+## Step 7: Database Connection from CircleCI Cloud
284
+
285
+Since CircleCI Cloud containers are ephemeral, the database must be network-accessible.
286
+
287
+### Connection String Format
288
+
289
+```bash
290
+# Supabase
291
+DATABASE_URL=postgresql://postgres:[password]@db.xxxxxxxxxx.supabase.co:5432/opencodehub
292
+
293
+# Neon (with SSL)
294
+DATABASE_URL=postgresql://[user]:[password]@ep-xxxxx.us-east-1.aws.neon.tech:5432/opencodehub?sslmode=require
295
+
296
+# Railway
297
+DATABASE_URL=postgresql://postgres:[password]@containers-xxxxx.railway.app:5432/railway
298
+
299
+# AWS RDS (with SSL)
300
+DATABASE_URL=postgresql://opencodehub:[password]@my-db.xxxxx.us-east-1.rds.amazonaws.com:5432/opencodehub?sslmode=require
301
+```
302
+
303
+### SSL/TLS Configuration
304
+
305
+Most managed PostgreSQL require SSL. The worker handles this automatically when `sslmode=require` is in the URL.
306
+
307
+For Supabase, add this to your environment variables:
308
+```bash
309
+DATABASE_SSL=true
310
+DATABASE_SSL_REJECT_UNAUTHORIZED=false # Supabase uses self-signed certs
311
+```
312
+
313
+---
314
+
315
+## Step 8: Redis Connection from CircleCI Cloud
316
+
317
+### Upstash Redis URL
318
+
319
+```bash
320
+REDIS_URL=rediss://default:[password]@xxxx.upstash.io:6379
321
+```
322
+
323
+> Note: `rediss://` (with double s) = TLS enabled. Upstash requires TLS.
324
+
325
+### Redis Cloud
326
+
327
+```bash
328
+REDIS_URL=redis://default:[password]@redis-xxxxx.redis-cloud.com:12345
329
+```
330
+
331
+### Testing Connection
332
+
333
+You can test the connection from CircleCI by running the `health-check` job:
334
+
335
+```bash
336
+# Trigger manually from CircleCI dashboard
337
+# or wait for the scheduled health check
338
+```
339
+
340
+---
341
+
342
+## Step 9: Monitoring
343
+
344
+### View Job Logs
345
+
346
+1. Go to [app.circleci.com](https://app.circleci.com)
347
+2. Select your project
348
+3. Click on any job to see real-time logs
349
+
350
+### Set Up Notifications
351
+
352
+1. **Project Settings** → **Notifications**
353
+2. Connect Slack, email, or webhooks
354
+3. Get alerts when jobs fail
355
+
356
+### Track Compute Usage
357
+
358
+1. **Plan** → **Usage**
359
+2. Monitor minutes used per month
360
+3. Set up usage alerts
361
+
362
+---
363
+
364
+## Step 10: Troubleshooting
365
+
366
+| Problem | Solution |
367
+|---------|----------|
368
+| **"Database connection refused"** | Your PostgreSQL doesn't allow external connections. Check provider's "Connection Pooling" or "Network" settings. For Supabase, go to Database → Connection Pooling. |
369
+| **"Redis connection timeout"** | Redis provider blocks unknown IPs. Add CircleCI's IP ranges to allowlist. Or use Upstash which doesn't require IP allowlisting. |
370
+| **Job killed after 1 hour** | Free plan default timeout is 1 hour. Add `no_output_timeout: 5h` or upgrade to Performance plan. |
371
+| **"Out of memory"** | Use `resource_class: large` instead of `medium`. Or optimize the worker memory usage. |
372
+| **"bun install fails"** | Network issues. The config has retry logic, but you can also try `npm install` as fallback. |
373
+| **"Schema doesn't exist"** | Run `bun run db:push` from your local machine first to create tables. |
374
+| **Worker starts but does nothing** | Check that `DATABASE_URL` points to the right database and that the `mergeQueueItems` table has rows with `status = 'queued'`. |
375
+| **"SSL certificate verify failed"** | Add `DATABASE_SSL_REJECT_UNAUTHORIZED=false` for providers with self-signed certs (Supabase). |
376
+
377
+---
378
+
379
+## Architecture Diagram
380
+
381
+```
382
+┌─────────────────────────────────────────────────────────────┐
383
+│ CircleCI Cloud │
384
+│ ┌─────────────────┐ ┌─────────────────┐ │
385
+│ │ Docker Container │ │ Docker Container │ ... │
386
+│ │ (every 15 min) │ │ (every 15 min) │ │
387
+│ │ │ │ │ │
388
+│ │ bun run worker.ts│ │ bun run worker.ts│ │
389
+│ │ │ │ │ │
390
+│ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │
391
+│ │ │ Node.js/Bun │ │ │ │ Node.js/Bun │ │ │
392
+│ │ │ Worker Loop │ │ │ │ Worker Loop │ │ │
393
+│ │ └─────────────┘ │ │ └─────────────┘ │ │
394
+│ └────────┬─────────┘ └────────┬─────────┘ │
395
+└───────────┼─────────────────────┼────────────────────────────┘
396
+ │ │
397
+ │ TCP/IP (Internet) │
398
+ ▼ ▼
399
+ ┌──────────────┐ ┌──────────────┐
400
+ │ PostgreSQL │ │ Redis │
401
+ │ (Supabase) │ │ (Upstash) │
402
+ │ │ │ │
403
+ │ merge_queue │ │ sessions │
404
+ │ repositories │ │ rate limits │
405
+ │ pull_requests │ │ job queues │
406
+ └──────────────┘ └──────────────┘
407
+```
408
+
409
+---
410
+
411
+## Quick Start Checklist
412
+
413
+- [ ] Create PostgreSQL database (Supabase/Neon/Railway)
414
+- [ ] Create Redis database (Upstash/Redis Cloud)
415
+- [ ] Run `bun run db:push` from local machine
416
+- [ ] Push OpenCodeHub code to GitHub
417
+- [ ] Connect repo to CircleCI
418
+- [ ] Create Context `opencodehub-production` with all env vars
419
+- [ ] Verify `.circleci/config.yml` is in repo root
420
+- [ ] Trigger first job manually from CircleCI dashboard
421
+- [ ] Check job logs for "✅ Worker started"
422
+- [ ] Create a test PR and verify merge queue processes it
423
+
424
+---
425
+
426
+## Next Steps
427
+
428
+- [CircleCI Integration Guide](/guides/circleci-integration/) — For CI/CD pipelines (separate from worker)
429
+- [Deployment Guide](/administration/deployment/) — Full production setup
430
+- [Self-Hosted Runner Guide](/administration/circleci-worker/) — If you prefer self-hosted over Cloud
431
+- [Merge Queue](/features/merge-queue/) — How merge queue works
0
432
▼src/content/docs/administration/circleci-worker.md
+566-0
1
+---
2
+title: "Run Workers on CircleCI"
3
+description: "Run OpenCodeHub background workers using CircleCI instead of GitHub Actions"
4
+---
5
+
6
+> **Goal:** Run OpenCodeHub background workers using CircleCI instead of GitHub Actions.
7
+
8
+OpenCodeHub's worker (`scripts/worker.ts`) is a **long-running background process** that continuously processes:
9
+- Merge queue items
10
+- Mirror sync jobs
11
+- Cleanup tasks
12
+- Webhook deliveries
13
+
14
+Since CircleCI is primarily a CI/CD platform (not a background process host), there are **three approaches** to run the worker on CircleCI infrastructure.
15
+
16
+---
17
+
18
+## Approach 1: Self-Hosted CircleCI Runner (Recommended)
19
+
20
+Use CircleCI's [self-hosted runner](https://circleci.com/docs/runner-overview/) on your own VPS. The runner stays online and executes the worker process continuously.
21
+
22
+### Why This Works Best
23
+- The runner is a persistent agent on your server
24
+- Can run long-lived processes like the OpenCodeHub worker
25
+- You control the machine (RAM, disk, Docker access)
26
+- Can also run CI/CD jobs for repositories
27
+
28
+### Step 1: Install CircleCI Runner on Your VPS
29
+
30
+```bash
31
+# Download and install the runner
32
+curl -sSL https://runner.circleci.com/install.sh | bash
33
+
34
+# Configure the runner
35
+sudo mkdir -p /var/lib/circleci-runner
36
+cat > /var/lib/circleci-runner/launch-agent-config.yaml << 'EOF'
37
+api:
38
+ auth_token: "${CIRCLECI_RUNNER_TOKEN}"
39
+runner:
40
+ name: opencodehub-worker-1
41
+ working_directory: /var/lib/circleci-runner/workdir
42
+ cleanup_working_directory: true
43
+EOF
44
+
45
+# Start the runner service
46
+sudo circleci-runner service install
47
+sudo circleci-runner service start
48
+```
49
+
50
+### Step 2: Create `.circleci/config.yml` in OpenCodeHub Repo
51
+
52
+```yaml
53
+version: 2.1
54
+
55
+executors:
56
+ och-worker:
57
+ machine:
58
+ image: ubuntu-2204:current
59
+ resource_class: your-namespace/opencodehub-runner # Your self-hosted runner
60
+
61
+jobs:
62
+ # ──────────────────────────────────────────────
63
+ # Job 1: Run Background Worker (Continuous)
64
+ # ──────────────────────────────────────────────
65
+ worker:
66
+ executor: och-worker
67
+ environment:
68
+ NODE_ENV: production
69
+ DATABASE_URL: ${DATABASE_URL}
70
+ REDIS_URL: ${REDIS_URL}
71
+ JWT_SECRET: ${JWT_SECRET}
72
+ WORKER_INTERVAL: 5000
73
+ WORKER_HEALTH_PORT: 9090
74
+ steps:
75
+ - checkout
76
+
77
+ - run:
78
+ name: Install Bun
79
+ command: |
80
+ curl -fsSL https://bun.sh/install | bash
81
+ echo 'export PATH="$HOME/.bun/bin:$PATH"' >> $BASH_ENV
82
+ source $BASH_ENV
83
+
84
+ - run:
85
+ name: Install dependencies
86
+ command: |
87
+ for i in 1 2 3; do
88
+ bun install --frozen-lockfile && break
89
+ echo "Attempt $i failed, retrying..."
90
+ sleep 10
91
+ done
92
+
93
+ - run:
94
+ name: Start OpenCodeHub Worker
95
+ command: |
96
+ echo "Starting OpenCodeHub background worker..."
97
+ bun run scripts/worker.ts &
98
+ WORKER_PID=$!
99
+ echo "Worker PID: $WORKER_PID"
100
+
101
+ # Wait for health check to pass
102
+ for i in $(seq 1 30); do
103
+ if curl -sf http://localhost:9090/health; then
104
+ echo "✅ Worker is healthy"
105
+ break
106
+ fi
107
+ echo "Waiting for worker to start... ($i/30)"
108
+ sleep 2
109
+ done
110
+
111
+ # Keep the job alive (CircleCI will show it as "Running")
112
+ echo "Worker running. Press Ctrl+C to stop."
113
+ wait $WORKER_PID
114
+ no_output_timeout: 24h # Keep worker running for up to 24 hours
115
+
116
+ - run:
117
+ name: Worker crashed - restart logic
118
+ command: |
119
+ echo "Worker exited. Checking logs..."
120
+ # CircleCI will automatically retry based on job settings
121
+ when: on_fail
122
+
123
+ # ──────────────────────────────────────────────
124
+ # Job 2: Run Worker Tasks On-Demand
125
+ # ──────────────────────────────────────────────
126
+ worker-tasks:
127
+ executor: och-worker
128
+ environment:
129
+ NODE_ENV: production
130
+ DATABASE_URL: ${DATABASE_URL}
131
+ REDIS_URL: ${REDIS_URL}
132
+ steps:
133
+ - checkout
134
+
135
+ - run:
136
+ name: Install Bun
137
+ command: |
138
+ curl -fsSL https://bun.sh/install | bash
139
+ echo 'export PATH="$HOME/.bun/bin:$PATH"' >> $BASH_ENV
140
+ source $BASH_ENV
141
+
142
+ - run:
143
+ name: Install dependencies
144
+ command: |
145
+ for i in 1 2 3; do
146
+ bun install --frozen-lockfile && break
147
+ echo "Attempt $i failed, retrying..."
148
+ sleep 10
149
+ done
150
+
151
+ - run:
152
+ name: Run Merge Queue Processor
153
+ command: |
154
+ echo "Processing merge queues..."
155
+ bun run scripts/worker.ts --once # If you add a --once flag
156
+ # OR run a specific task script
157
+ # bun run scripts/process-merge-queue.ts
158
+
159
+ - run:
160
+ name: Run Mirror Sync
161
+ command: |
162
+ echo "Syncing mirrors..."
163
+ # bun run scripts/sync-mirrors.ts
164
+
165
+ - run:
166
+ name: Run Cleanup
167
+ command: |
168
+ echo "Running cleanup tasks..."
169
+ # bun run scripts/cleanup-repos.ts
170
+
171
+ # ──────────────────────────────────────────────
172
+ # Job 3: Health Check (Scheduled)
173
+ # ──────────────────────────────────────────────
174
+ worker-health-check:
175
+ executor: och-worker
176
+ steps:
177
+ - run:
178
+ name: Check Worker Health
179
+ command: |
180
+ curl -sf http://localhost:9090/health || exit 1
181
+ echo "✅ Worker is healthy"
182
+
183
+workflows:
184
+ version: 2
185
+
186
+ # Continuous worker (always running)
187
+ worker-continuous:
188
+ jobs:
189
+ - worker:
190
+ filters:
191
+ branches:
192
+ only:
193
+ - main
194
+
195
+ # Scheduled tasks (every 5 minutes)
196
+ worker-scheduled:
197
+ triggers:
198
+ - schedule:
199
+ cron: "*/5 * * * *"
200
+ filters:
201
+ branches:
202
+ only:
203
+ - main
204
+ jobs:
205
+ - worker-tasks
206
+
207
+ # Health check every hour
208
+ worker-health:
209
+ triggers:
210
+ - schedule:
211
+ cron: "0 * * * *"
212
+ filters:
213
+ branches:
214
+ only:
215
+ - main
216
+ jobs:
217
+ - worker-health-check
218
+```
219
+
220
+### Step 3: Set Environment Variables in CircleCI
221
+
222
+Go to **Project Settings** → **Environment Variables**:
223
+
224
+| Variable | Value | Description |
225
+|----------|-------|-------------|
226
+| `DATABASE_URL` | `postgresql://...` | Your PostgreSQL connection string |
227
+| `REDIS_URL` | `redis://...` | Your Redis connection string |
228
+| `JWT_SECRET` | `...` | JWT secret |
229
+| `SESSION_SECRET` | `...` | Session secret |
230
+| `WORKFLOW_SECRET_ENCRYPTION_KEY` | `...` | For CI secrets |
231
+| `CIRCLECI_RUNNER_TOKEN` | `...` | Runner registration token |
232
+
233
+---
234
+
235
+## Approach 2: CircleCI Scheduled Pipelines (No Self-Hosted Runner)
236
+
237
+If you don't want to manage a self-hosted runner, use CircleCI's [scheduled pipelines](https://circleci.com/docs/scheduled-pipelines/) to run the worker periodically.
238
+
239
+### Limitations
240
+- Jobs have a maximum runtime (5 hours on free plan, longer on paid)
241
+- Worker will restart every 5 hours
242
+- Not truly "continuous" but works for light workloads
243
+
244
+### `.circleci/config.yml`
245
+
246
+```yaml
247
+version: 2.1
248
+
249
+executors:
250
+ bun-executor:
251
+ docker:
252
+ - image: oven/bun:1
253
+ resource_class: medium
254
+
255
+jobs:
256
+ merge-queue-worker:
257
+ executor: bun-executor
258
+ environment:
259
+ NODE_ENV: production
260
+ DATABASE_URL: ${DATABASE_URL}
261
+ REDIS_URL: ${REDIS_URL}
262
+ WORKER_INTERVAL: 5000
263
+ WORKER_STALE_TIMEOUT: 300000
264
+ steps:
265
+ - checkout
266
+
267
+ - run:
268
+ name: Install dependencies
269
+ command: |
270
+ for i in 1 2 3; do
271
+ bun install --frozen-lockfile && break
272
+ echo "Attempt $i failed, retrying..."
273
+ sleep 10
274
+ done
275
+
276
+ - run:
277
+ name: Run Merge Queue Worker
278
+ command: |
279
+ echo "Starting worker for 4.5 hours..."
280
+ timeout 16200 bun run scripts/worker.ts || true
281
+ echo "Worker cycle complete. Will restart on next schedule."
282
+ no_output_timeout: 4.5h
283
+
284
+ mirror-sync:
285
+ executor: bun-executor
286
+ environment:
287
+ NODE_ENV: production
288
+ DATABASE_URL: ${DATABASE_URL}
289
+ steps:
290
+ - checkout
291
+
292
+ - run:
293
+ name: Install dependencies
294
+ command: bun install --frozen-lockfile
295
+
296
+ - run:
297
+ name: Sync Mirrors
298
+ command: bun run scripts/worker.ts --task=mirror-sync
299
+
300
+ cleanup:
301
+ executor: bun-executor
302
+ environment:
303
+ NODE_ENV: production
304
+ DATABASE_URL: ${DATABASE_URL}
305
+ steps:
306
+ - checkout
307
+
308
+ - run:
309
+ name: Install dependencies
310
+ command: bun install --frozen-lockfile
311
+
312
+ - run:
313
+ name: Run Cleanup
314
+ command: bun run scripts/worker.ts --task=cleanup
315
+
316
+workflows:
317
+ # Run merge queue worker every 5 hours
318
+ merge-queue-schedule:
319
+ triggers:
320
+ - schedule:
321
+ cron: "0 */5 * * *"
322
+ filters:
323
+ branches:
324
+ only: main
325
+ jobs:
326
+ - merge-queue-worker
327
+
328
+ # Run mirror sync every hour
329
+ mirror-sync-schedule:
330
+ triggers:
331
+ - schedule:
332
+ cron: "0 * * * *"
333
+ filters:
334
+ branches:
335
+ only: main
336
+ jobs:
337
+ - mirror-sync
338
+
339
+ # Run cleanup daily at 3 AM
340
+ cleanup-schedule:
341
+ triggers:
342
+ - schedule:
343
+ cron: "0 3 * * *"
344
+ filters:
345
+ branches:
346
+ only: main
347
+ jobs:
348
+ - cleanup
349
+```
350
+
351
+---
352
+
353
+## Approach 3: CircleCI Webhook-Triggered Worker
354
+
355
+Trigger the worker via API/webhook when specific events happen (push, PR created, merge queue updated).
356
+
357
+### API Triggered Workflow
358
+
359
+```yaml
360
+version: 2.1
361
+
362
+executors:
363
+ bun-executor:
364
+ docker:
365
+ - image: oven/bun:1
366
+
367
+parameters:
368
+ event_type:
369
+ type: string
370
+ default: "merge-queue"
371
+ repo_id:
372
+ type: string
373
+ default: ""
374
+ pr_id:
375
+ type: string
376
+ default: ""
377
+
378
+jobs:
379
+ process-event:
380
+ executor: bun-executor
381
+ environment:
382
+ NODE_ENV: production
383
+ DATABASE_URL: ${DATABASE_URL}
384
+ REDIS_URL: ${REDIS_URL}
385
+ steps:
386
+ - checkout
387
+
388
+ - run:
389
+ name: Install dependencies
390
+ command: bun install --frozen-lockfile
391
+
392
+ - run:
393
+ name: Process Event
394
+ command: |
395
+ echo "Processing event: << pipeline.parameters.event_type >>"
396
+ case "<< pipeline.parameters.event_type >>" in
397
+ merge-queue)
398
+ bun run scripts/worker.ts --task=merge-queue --repo-id=<< pipeline.parameters.repo_id >>
399
+ ;;
400
+ mirror-sync)
401
+ bun run scripts/worker.ts --task=mirror-sync
402
+ ;;
403
+ cleanup)
404
+ bun run scripts/worker.ts --task=cleanup
405
+ ;;
406
+ *)
407
+ echo "Unknown event type"
408
+ exit 1
409
+ ;;
410
+ esac
411
+
412
+workflows:
413
+ event-driven-worker:
414
+ when:
415
+ equal: [ webhook, << pipeline.trigger_source >> ]
416
+ jobs:
417
+ - process-event
418
+```
419
+
420
+### Trigger via API from OpenCodeHub
421
+
422
+In your OpenCodeHub webhook handler, trigger CircleCI:
423
+
424
+```typescript
425
+// When merge queue is updated
426
+transportToCircleCI({
427
+ event_type: "merge-queue",
428
+ repo_id: repository.id,
429
+ pr_id: pullRequest.id,
430
+});
431
+
432
+async function transportToCircleCI(params: { event_type: string; repo_id: string; pr_id?: string }) {
433
+ const response = await fetch(
434
+ `https://circleci.com/api/v2/project/gh/${org}/${repo}/pipeline`,
435
+ {
436
+ method: "POST",
437
+ headers: {
438
+ "Circle-Token": process.env.CIRCLECI_API_TOKEN!,
439
+ "Content-Type": "application/json",
440
+ },
441
+ body: JSON.stringify({
442
+ branch: "main",
443
+ parameters: params,
444
+ }),
445
+ }
446
+ );
447
+ return response.json();
448
+}
449
+```
450
+
451
+---
452
+
453
+## Approach Comparison
454
+
455
+| Feature | Self-Hosted Runner | Scheduled Pipelines | Webhook-Triggered |
456
+|---------|-------------------|---------------------|-------------------|
457
+| **Continuous?** | ✅ Yes | ⚠️ Every 5 hours | ✅ Event-driven |
458
+| **Setup Complexity** | Medium (VPS needed) | Low | Medium |
459
+| **Cost** | VPS cost only | CircleCI compute minutes | CircleCI compute minutes |
460
+| **Best For** | Production workloads | Light workloads | Event-specific tasks |
461
+| **Docker Support** | ✅ Full | ✅ Yes | ✅ Yes |
462
+| **Persistence** | ✅ Local disk | ❌ Ephemeral | ❌ Ephemeral |
463
+
464
+---
465
+
466
+## Recommended Setup for Production
467
+
468
+### Architecture
469
+
470
+```
471
+VPS (e.g., Hetzner/DigitalOcean)
472
+├── OpenCodeHub Main App (port 4321)
473
+├── PostgreSQL (port 5432)
474
+├── Redis (port 6379)
475
+└── CircleCI Self-Hosted Runner
476
+ └── Runs: bun run scripts/worker.ts
477
+```
478
+
479
+### Why Self-Hosted Runner Wins
480
+1. **Persistence** — Runner stays on your VPS, has access to local git repos
481
+2. **Network** — Can reach PostgreSQL/Redis on `localhost`
482
+3. **Cost** — No CircleCI compute minutes used
483
+4. **Control** — You manage the machine
484
+
485
+### Quick Start Script
486
+
487
+```bash
488
+#!/bin/bash
489
+# setup-circleci-worker.sh
490
+
491
+# 1. Install CircleCI runner
492
+curl -sSL https://runner.circleci.com/install.sh | bash
493
+
494
+# 2. Create runner config
495
+mkdir -p /var/lib/circleci-runner
496
+cat > /var/lib/circleci-runner/launch-agent-config.yaml << EOF
497
+api:
498
+ auth_token: "$CIRCLECI_RUNNER_TOKEN"
499
+runner:
500
+ name: "opencodehub-worker-$(hostname)"
501
+ working_directory: /var/lib/circleci-runner/workdir
502
+ cleanup_working_directory: true
503
+EOF
504
+
505
+# 3. Install and start service
506
+circleci-runner service install
507
+circleci-runner service start
508
+
509
+# 4. Verify
510
+systemctl status circleci-runner
511
+```
512
+
513
+---
514
+
515
+## Monitoring
516
+
517
+### Worker Health Check
518
+
519
+```bash
520
+# Check if worker is running
521
+curl http://localhost:9090/health
522
+
523
+# Expected output
524
+{
525
+ "status": "healthy",
526
+ "uptime": 86400,
527
+ "lastQueueRun": "2026-05-02T12:00:00.000Z",
528
+ "consecutiveErrors": 0,
529
+ "shuttingDown": false
530
+}
531
+```
532
+
533
+### CircleCI Dashboard
534
+
535
+Monitor runner status at:
536
+```
537
+https://app.circleci.com/settings/runner
538
+```
539
+
540
+### Alerts
541
+
542
+Set up alerts in CircleCI when:
543
+- Runner goes offline
544
+- Job fails more than 3 times
545
+- Worker health check returns `unhealthy`
546
+
547
+---
548
+
549
+## Troubleshooting
550
+
551
+| Problem | Solution |
552
+|---------|----------|
553
+| **"Runner not picking up jobs"** | Check runner token is correct. Verify runner is online in CircleCI dashboard. |
554
+| **"Database connection refused"** | Ensure DATABASE_URL uses correct host. For self-hosted runner on same VPS, use `localhost`. |
555
+| **"Worker exits after 5 hours"** | Scheduled pipeline limit. Use self-hosted runner for continuous operation. |
556
+| **"No output for 10 minutes"** | CircleCI kills idle jobs. The worker logs regularly, but add `no_output_timeout: 24h`. |
557
+| **"Cannot find module"** | Make sure `bun install` ran successfully. Check `node_modules` exists. |
558
+| **"Permission denied on repos"** | Runner user needs read/write access to OpenCodeHub's repo storage directory. |
559
+
560
+---
561
+
562
+## Next Steps
563
+
564
+- [CircleCI Integration Guide](/guides/circleci-integration/) — For CI/CD pipelines
565
+- [Deployment Guide](/administration/deployment/) — Production setup
566
+- [Merge Queue](/features/merge-queue/) — How merge queue works
0
567
▼src/content/docs/administration/configuration.md
+187-32
2
2
title: "Configuration Reference"
3
3
---
4
4
5
+OpenCodeHub is configured via environment variables. Copy `.env.example` to `.env` and edit.
5
6
6
-OpenCodeHub is configured exclusively via environment variables.
7
+## Server
7
8
8
-## Core
9
+| Variable | Description | Default |
10
+|----------|-------------|---------|
11
+| `HOST` | Bind address | `0.0.0.0` |
12
+| `PORT` | HTTP port | `4321` |
13
+| `SITE_URL` | Public URL of the instance | `http://localhost:4321` |
14
+| `APP_NAME` | Instance name | `OpenCodeHub` |
15
+| `NODE_ENV` | `development` or `production` | `development` |
9
16
10
-| Variable | Description | Required | Default |
11
-|----------|-------------|----------|---------|
12
-| `SITE_URL` | Public URL of the instance | Yes | `http://localhost:3000` |
13
-| `PORT` | Port to listen on | No | `3000` |
14
-| `NODE_ENV` | `development` or `production` | No | `development` |
17
+## Database
15
18
16
-## Security (Critical)
19
+| Variable | Description | Default |
20
+|----------|-------------|---------|
21
+| `DATABASE_DRIVER` | `postgres`, `sqlite`, or `turso` (LibSQL) | `postgres` |
22
+| `DATABASE_URL` | Connection string | — |
23
+| `DATABASE_POOL_SIZE` | Connection pool size | `10` |
24
+| `DATABASE_SSL` | Enable PostgreSQL SSL | `false` |
25
+| `DATABASE_AUTH_TOKEN` | Auth token (Turso/LibSQL only) | — |
26
+
27
+:::caution[Production]
28
+PostgreSQL is **required** for production. All schemas use `pgTable`. SQLite is for development only.
29
+:::
30
+
31
+## Redis
32
+
33
+| Variable | Description | Default |
34
+|----------|-------------|---------|
35
+| `REDIS_URL` | Redis connection string | `redis://localhost:6379` |
36
+| `REDIS_PASSWORD` | Redis password | — |
37
+
38
+Redis is required in production for distributed locking, rate limiting, and sessions. For edge deployments (Vercel), use Upstash Redis with `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN`.
39
+
40
+## Authentication
17
41
18
42
| Variable | Description | Generate With |
19
43
|----------|-------------|---------------|
20
-| `JWT_SECRET` | Signs auth tokens | `openssl rand -hex 32` |
21
-| `SESSION_SECRET` | Signs session cookies | `openssl rand -hex 32` |
22
-| `INTERNAL_HOOK_SECRET` | Secures git hooks | `openssl rand -hex 32` |
44
+| `JWT_SECRET` | Signs auth tokens | `openssl rand -base64 32` |
45
+| `JWT_EXPIRES_IN` | Token expiry | `7d` |
46
+| `SESSION_SECRET` | Signs session cookies | `openssl rand -base64 32` |
23
47
24
-## Database
48
+## Security Secrets
25
49
26
-| Variable | Description | Example |
50
+All secrets below must be unique. Generate each with `openssl rand -hex 32`.
51
+
52
+| Variable | Purpose |
53
+|----------|---------|
54
+| `INTERNAL_HOOK_SECRET` | Secures git hook communication between Git server and app |
55
+| `CRON_SECRET` | Protects cron endpoints (GC, mirror sync, notification digests) |
56
+| `AI_CONFIG_ENCRYPTION_KEY` | Encrypts AI provider API keys at rest |
57
+| `WORKFLOW_SECRET_ENCRYPTION_KEY` | Encrypts CI/CD workflow secrets at rest |
58
+| `RUNNER_SECRET` | Shared secret between server and CI runners |
59
+
60
+## OAuth Providers
61
+
62
+| Variable | Description |
63
+|----------|-------------|
64
+| `OAUTH_GOOGLE_CLIENT_ID` | Google OAuth client ID |
65
+| `OAUTH_GOOGLE_CLIENT_SECRET` | Google OAuth client secret |
66
+| `OAUTH_GITHUB_CLIENT_ID` | GitHub OAuth client ID |
67
+| `OAUTH_GITHUB_CLIENT_SECRET` | GitHub OAuth client secret |
68
+| `OAUTH_GITLAB_CLIENT_ID` | GitLab OAuth client ID |
69
+| `OAUTH_GITLAB_CLIENT_SECRET` | GitLab OAuth client secret |
70
+
71
+OpenCodeHub also supports SSO via SAML and OIDC. Configure these through the admin dashboard.
72
+
73
+## Git Configuration
74
+
75
+| Variable | Description | Default |
27
76
|----------|-------------|---------|
28
-| `DATABASE_DRIVER` | `postgres`, `mysql`, `sqlite`, `libsql` | `postgres` |
29
-| `DATABASE_URL` | Connection string | `postgresql://user:pass@host:5432/db` |
30
-| `DATABASE_AUTH_TOKEN`| Auth token (Turso/LibSQL only) | |
77
+| `GIT_REPOS_PATH` | Directory for git repositories | `./data/repositories` |
78
+| `GIT_SSH_PORT` | SSH git server port | `2222` |
79
+| `GIT_SSH_HOST_KEY` | Path to SSH host key | `./data/ssh/host_key` |
31
80
32
81
## Storage
33
82
34
83
| Variable | Description | Default |
35
84
|----------|-------------|---------|
36
-| `STORAGE_TYPE` | `local`, `s3`, `gdrive`, `azure` | `local` |
37
-| `STORAGE_PATH` | Path for local storage | `./data` |
38
-| `STORAGE_BUCKET` | Bucket name (S3/GCP) | |
39
-| `STORAGE_REGION` | AWS Region | `us-east-1` |
40
-| `STORAGE_ENDPOINT` | Custom S3 endpoint | |
41
-| `S3_ACCESS_KEY` | AWS Access Key | |
42
-| `S3_SECRET_KEY` | AWS Secret Key | |
85
+| `STORAGE_TYPE` | `local` or `s3` | `local` |
86
+| `STORAGE_PATH` | Local storage path | `./data/storage` |
87
+
88
+### S3-Compatible Storage
43
89
44
-## AI Review
90
+Works with AWS S3, MinIO, Cloudflare R2, Garage, SeaweedFS, Ceph RGW, Wasabi, Backblaze B2, and any S3-compatible service.
45
91
46
92
| Variable | Description |
47
93
|----------|-------------|
48
-| `AI_PROVIDER` | `openai` or `anthropic` |
49
-| `OPENAI_API_KEY` | OpenAI API Key |
50
-| `ANTHROPIC_API_KEY` | Anthropic API Key |
94
+| `STORAGE_BUCKET` | Bucket name (required for S3) |
95
+| `STORAGE_REGION` | S3 region (default: `us-east-1`) |
96
+| `STORAGE_ENDPOINT` | Custom S3 endpoint (for MinIO, R2, etc.) |
97
+| `STORAGE_ACCESS_KEY_ID` | S3 access key |
98
+| `STORAGE_SECRET_ACCESS_KEY` | S3 secret key |
99
+
100
+:::tip[Performance]
101
+For best performance, use **local SSD storage**. Object storage (S3/R2) introduces latency. Use S3 for multi-node deployments or backup.
102
+:::
103
+
104
+## CI/CD Runner
105
+
106
+| Variable | Description | Default |
107
+|----------|-------------|---------|
108
+| `RUNNER_ENABLED` | Enable the CI runner | `true` |
109
+| `RUNNER_DOCKER_SOCKET` | Docker socket path | `/var/run/docker.sock` |
110
+| `RUNNER_WORKSPACE_PATH` | Workspace directory | `./data/runner/workspaces` |
111
+| `RUNNER_ARTIFACTS_PATH` | Artifacts directory | `./data/runner/artifacts` |
112
+| `RUNNER_CONCURRENT_JOBS` | Max concurrent jobs | `2` |
113
+| `RUNNER_TIMEOUT` | Job timeout in seconds | `3600` |
114
+| `RUNNER_REGISTRATION_TOKEN_TTL_DAYS` | Token TTL | `90` |
51
115
52
116
## Email (SMTP)
53
117
118
+| Variable | Description | Default |
119
+|----------|-------------|---------|
120
+| `SMTP_HOST` | SMTP hostname | — |
121
+| `SMTP_PORT` | SMTP port | `587` |
122
+| `SMTP_USER` | SMTP username | — |
123
+| `SMTP_PASSWORD` | SMTP password | — |
124
+| `SMTP_FROM` | From address | `[email protected]` |
125
+
126
+## Logging
127
+
128
+| Variable | Description | Default |
129
+|----------|-------------|---------|
130
+| `LOG_LEVEL` | `debug`, `info`, `warn`, `error` | `info` |
131
+| `LOG_FILE` | Log file path | `./data/logs/opencodehub.log` |
132
+
133
+## Rate Limiting
134
+
135
+| Variable | Description | Default |
136
+|----------|-------------|---------|
137
+| `RATE_LIMIT_ENABLED` | Enable rate limiting | `true` |
138
+| `RATE_LIMIT_AUTH` | Auth endpoints (req/15min) | `5` |
139
+| `RATE_LIMIT_API` | API endpoints (req/min) | `100` |
140
+| `RATE_LIMIT_GIT` | Git operations (req/min) | `200` |
141
+| `RATE_LIMIT_GENERAL` | General endpoints (req/min) | `60` |
142
+| `RATE_LIMIT_SKIP_DEV` | Skip in development | `false` |
143
+| `CSRF_SKIP_DEV` | Skip CSRF in development | `false` |
144
+
145
+## CORS & Request Limits
146
+
147
+| Variable | Description | Default |
148
+|----------|-------------|---------|
149
+| `ALLOWED_ORIGINS` | Comma-separated allowed origins | `http://localhost:4321` |
150
+| `MAX_REQUEST_BODY_MB` | Max request body size (MB) | `10` |
151
+| `MAX_PACK_SIZE_MB` | Max git pack size (MB) | `500` |
152
+| `GIT_PROCESS_TIMEOUT_SECS` | Git process timeout (sec) | `300` |
153
+
154
+## Feature Flags
155
+
156
+| Variable | Description | Default |
157
+|----------|-------------|---------|
158
+| `ENABLE_REGISTRATION` | Allow new user signups | `true` |
159
+| `ENABLE_WIKI` | Enable repository wikis | `true` |
160
+| `ENABLE_ISSUES` | Enable issue tracking | `true` |
161
+| `ENABLE_ACTIONS` | Enable CI/CD pipelines | `true` |
162
+| `ENABLE_PACKAGES` | Enable package registry | `false` |
163
+| `ENABLE_AI_ASSISTANT` | Enable AI code review | `true` |
164
+
165
+## AI Providers
166
+
167
+Configure one or more AI providers for code review. Keys are encrypted at rest using `AI_CONFIG_ENCRYPTION_KEY`.
168
+
169
+| Variable | Provider |
170
+|----------|----------|
171
+| `OPENAI_API_KEY` | OpenAI (GPT-4, GPT-4o) |
172
+| `ANTHROPIC_API_KEY` | Anthropic (Claude) |
173
+| `GROQ_API_KEY` | Groq (fast inference) |
174
+| `BYTEZ_API_KEY` | Bytez |
175
+| `OPENROUTER_API_KEY` | OpenRouter (multi-model) |
176
+| `TOGETHER_API_KEY` | Together AI |
177
+| `GOOGLE_AI_API_KEY` | Google AI (Gemini) |
178
+
179
+Ollama is supported for local/self-hosted AI. No API key required — just set the Ollama endpoint in the admin dashboard.
180
+
181
+## External Review Agent
182
+
183
+| Variable | Description |
184
+|----------|-------------|
185
+| `EXTERNAL_AGENT_WEBHOOK_URL` | Webhook URL for external AI agent |
186
+| `EXTERNAL_AGENT_API_KEY` | API key for the external agent |
187
+| `EXTERNAL_AGENT_CALLBACK_SECRET` | Callback verification secret |
188
+
189
+## Backup
190
+
191
+| Variable | Description | Default |
192
+|----------|-------------|---------|
193
+| `BACKUP_ENCRYPTION_KEY` | Encryption key for backups | — |
194
+| `BACKUP_S3_BUCKET` | S3 bucket for backups | — |
195
+| `BACKUP_S3_PREFIX` | S3 prefix | `opencodehub-backups` |
196
+| `BACKUP_RETENTION_DAYS` | Retention period | `30` |
197
+| `BACKUP_DIR` | Local backup directory | `./backups` |
198
+
199
+## Air-gapped Mode
200
+
201
+| Variable | Description | Default |
202
+|----------|-------------|---------|
203
+| `AIR_GAPPED_MODE` | Disable all external API calls | `false` |
204
+
205
+When enabled, OpenCodeHub operates fully offline. AI features are disabled unless you run a local model (e.g., Ollama).
206
+
207
+## Observability
208
+
54
209
| Variable | Description |
55
210
|----------|-------------|
56
-| `SMTP_HOST` | Hostname (e.g. `smtp.gmail.com`) |
57
-| `SMTP_PORT` | Port (e.g. `587`) |
58
-| `SMTP_USER` | Username |
59
-| `SMTP_PASSWORD`| Password |
60
-| `SMTP_FROM` | From address |
211
+| `GRAFANA_OTLP_ENDPOINT` | Grafana Cloud OTLP endpoint |
212
+| `GRAFANA_INSTANCE_ID` | Grafana Cloud instance ID |
213
+| `GRAFANA_API_KEY` | Grafana Cloud API key |
214
+
215
+OpenCodeHub exports OpenTelemetry traces and Prometheus metrics. See [Monitoring](/administration/monitoring/) for setup details.
61
216
▼src/content/docs/administration/deploy-cloudflare.md
+4-4
130
130
STORAGE_BUCKET=opencodehub-repos
131
131
STORAGE_REGION=auto
132
132
STORAGE_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
133
-S3_ACCESS_KEY=<your-r2-access-key-id>
134
-S3_SECRET_KEY=<your-r2-secret-access-key>
133
+STORAGE_ACCESS_KEY_ID=<your-r2-access-key-id>
134
+STORAGE_SECRET_ACCESS_KEY=<your-r2-secret-access-key>
135
135
```
136
136
137
137
Find your account ID in Cloudflare Dashboard → R2 → Overview.
298
298
STORAGE_BUCKET=opencodehub-repos
299
299
STORAGE_REGION=auto
300
300
STORAGE_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
301
-S3_ACCESS_KEY=<r2-access-key>
302
-S3_SECRET_KEY=<r2-secret-key>
301
+STORAGE_ACCESS_KEY_ID=<r2-access-key>
302
+STORAGE_SECRET_ACCESS_KEY=<r2-secret-key>
303
303
```
304
304
305
305
---
306
306
▼src/content/docs/administration/deploy-coolify.md
+347-0
1
+---
2
+title: "Deploy on Coolify"
3
+description: "Deploy OpenCodeHub on Coolify, the self-hosted PaaS alternative to Heroku and Render"
4
+---
5
+
6
+> **Difficulty:** Easy | **Time:** 20 minutes | **Method:** Docker Compose (Git-based)
7
+
8
+Coolify is an open-source, self-hosted alternative to Heroku, Netlify, and Render. It makes deploying OpenCodeHub incredibly simple with built-in SSL, automatic deployments, and managed databases.
9
+
10
+---
11
+
12
+## Prerequisites
13
+
14
+- A server (VPS) with Ubuntu 22.04/24.04, Debian 12, or CentOS 9
15
+- Minimum **2 CPU cores, 4GB RAM, 40GB SSD**
16
+- A domain name pointed to your server (e.g., `git.yourdomain.com`)
17
+- Coolify v4 installed on your server
18
+
19
+---
20
+
21
+## Step 1: Install Coolify
22
+
23
+If you haven't installed Coolify yet, run this on your server:
24
+
25
+```bash
26
+curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
27
+```
28
+
29
+After installation:
30
+1. Open `http://your-server-ip:8000`
31
+2. Complete the onboarding wizard
32
+3. Set up your domain (e.g., `coolify.yourdomain.com`)
33
+
34
+---
35
+
36
+## Step 2: Create Resources in Coolify
37
+
38
+### 2.1 Create a Project
39
+
40
+1. In Coolify dashboard, click **Projects** → **Add**
41
+2. Name it `OpenCodeHub`
42
+3. Select your server and environment (e.g., `production`)
43
+
44
+### 2.2 Create a PostgreSQL Database
45
+
46
+1. Go to your project → **Resources** → **Add New Resource** → **Database**
47
+2. Select **PostgreSQL**
48
+3. Configuration:
49
+ ```
50
+ Name: opencodehub-postgres
51
+ Version: 16
52
+ Database: opencodehub
53
+ Username: opencodehub
54
+ Password: <generate-strong-password>
55
+ ```
56
+4. Click **Start**
57
+5. **Note down the internal connection string** (e.g., `postgresql://opencodehub:password@opencodehub-postgres:5432/opencodehub`)
58
+
59
+### 2.3 Create a Redis Instance
60
+
61
+1. **Add New Resource** → **Database** → **Redis**
62
+2. Configuration:
63
+ ```
64
+ Name: opencodehub-redis
65
+ Version: 7-alpine
66
+ Password: <generate-strong-password>
67
+ ```
68
+3. Click **Start**
69
+4. **Note down the internal URL** (e.g., `redis://:password@opencodehub-redis:6379`)
70
+
71
+---
72
+
73
+## Step 3: Deploy OpenCodeHub Application
74
+
75
+### 3.1 Add the Git Repository
76
+
77
+1. Go to your project → **Resources** → **Add New Resource** → **Application**
78
+2. Select **Public Repository**
79
+3. Repository URL: `https://github.com/swadhinbiswas/OpencodeHub.git`
80
+4. Branch: `main`
81
+5. Build Pack: **Docker Compose**
82
+6. Click **Continue**
83
+
84
+### 3.2 Configure the Docker Compose
85
+
86
+Coolify will auto-detect the `docker-compose.yml`. You need to customize it for Coolify's environment:
87
+
88
+Replace the detected compose with this Coolify-optimized version:
89
+
90
+```yaml
91
+services:
92
+ app:
93
+ build:
94
+ context: .
95
+ dockerfile: Dockerfile
96
+ container_name: opencodehub
97
+ restart: unless-stopped
98
+ ports:
99
+ - "4321:4321"
100
+ environment:
101
+ - NODE_ENV=production
102
+ - DATABASE_URL=${DATABASE_URL}
103
+ - REDIS_URL=${REDIS_URL}
104
+ - JWT_SECRET=${JWT_SECRET}
105
+ - SESSION_SECRET=${SESSION_SECRET}
106
+ - INTERNAL_HOOK_SECRET=${INTERNAL_HOOK_SECRET}
107
+ - CRON_SECRET=${CRON_SECRET}
108
+ - RUNNER_SECRET=${RUNNER_SECRET}
109
+ - WORKFLOW_SECRET_ENCRYPTION_KEY=${WORKFLOW_SECRET_ENCRYPTION_KEY}
110
+ - SITE_URL=${COOLIFY_FQDN:-http://localhost:4321}
111
+ - SSH_HOST_KEY_PATH=/data/ssh/host_key
112
+ - STORAGE_TYPE=local
113
+ - STORAGE_PATH=/data/storage
114
+ - REPOS_PATH=/data/repos
115
+ volumes:
116
+ - opencodehub-repos:/data/repos
117
+ - opencodehub-storage:/data/storage
118
+ - opencodehub-ssh:/data/ssh
119
+ - opencodehub-cache:/data/cache
120
+ healthcheck:
121
+ test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:4321/api/health"]
122
+ interval: 30s
123
+ timeout: 10s
124
+ retries: 3
125
+ start_period: 15s
126
+
127
+volumes:
128
+ opencodehub-repos:
129
+ opencodehub-storage:
130
+ opencodehub-ssh:
131
+ opencodehub-cache:
132
+```
133
+
134
+### 3.3 Set Environment Variables
135
+
136
+In Coolify, go to your app → **Environment Variables** and add:
137
+
138
+| Variable | Value | Description |
139
+|----------|-------|-------------|
140
+| `DATABASE_URL` | `postgresql://opencodehub:YOUR_PASS@opencodehub-postgres:5432/opencodehub` | From Step 2.2 |
141
+| `REDIS_URL` | `redis://:YOUR_PASS@opencodehub-redis:6379` | From Step 2.3 |
142
+| `JWT_SECRET` | `openssl rand -hex 32` | Generate this |
143
+| `SESSION_SECRET` | `openssl rand -hex 32` | Generate this |
144
+| `INTERNAL_HOOK_SECRET` | `openssl rand -hex 32` | Generate this |
145
+| `CRON_SECRET` | `openssl rand -hex 32` | Generate this |
146
+| `RUNNER_SECRET` | `openssl rand -hex 32` | Generate this |
147
+| `WORKFLOW_SECRET_ENCRYPTION_KEY` | `openssl rand -hex 32` | Generate this |
148
+| `SITE_URL` | `https://git.yourdomain.com` | Your domain |
149
+| `COOLIFY_FQDN` | Leave as-is (auto-set) | Coolify injects this |
150
+
151
+> **Security Tip:** Use Coolify's "Secret" toggle for all `*_SECRET` variables so they are encrypted at rest.
152
+
153
+### 3.4 Configure Persistent Storage
154
+
155
+In your app settings → **Persistent Storage**, verify these volumes are created:
156
+
157
+| Volume Name | Container Path | Purpose |
158
+|------------|----------------|---------|
159
+| `opencodehub-repos` | `/data/repos` | Git repositories |
160
+| `opencodehub-storage` | `/data/storage` | File uploads |
161
+| `opencodehub-ssh` | `/data/ssh` | SSH host keys |
162
+| `opencodehub-cache` | `/data/cache` | Application cache |
163
+
164
+---
165
+
166
+## Step 4: Configure Domain & SSL
167
+
168
+### 4.1 Set Domain
169
+
170
+1. In your app → **Settings** → **Domains**
171
+2. Add your domain: `git.yourdomain.com`
172
+3. Coolify will automatically configure the reverse proxy
173
+
174
+### 4.2 Enable SSL
175
+
176
+1. Go to **Settings** → **SSL/TLS**
177
+2. Select **Let's Encrypt (Auto)**
178
+3. Enable **HTTPS Redirect**
179
+4. Click **Save**
180
+
181
+Coolify handles:
182
+- Nginx reverse proxy
183
+- SSL certificate generation and renewal
184
+- WebSocket support
185
+- Gzip compression
186
+
187
+---
188
+
189
+## Step 5: Deploy
190
+
191
+1. Click **Deploy**
192
+2. Coolify will:
193
+ - Clone the repository
194
+ - Build the Docker image
195
+ - Start the container
196
+ - Run health checks
197
+3. Wait for the "Healthy" status
198
+
199
+---
200
+
201
+## Step 6: Initial Setup
202
+
203
+### 6.1 Create Admin User
204
+
205
+Run the seed script inside the container:
206
+
207
+```bash
208
+# In Coolify dashboard, go to your app → "Execute Command" or use terminal
209
+docker exec -it opencodehub bun run scripts/seed-admin.ts
210
+```
211
+
212
+Or via Coolify's web terminal:
213
+1. Go to your app → **Terminal**
214
+2. Run: `bun run scripts/seed-admin.ts`
215
+3. Enter username, email, and password when prompted
216
+
217
+### 6.2 Verify Installation
218
+
219
+Visit `https://git.yourdomain.com` and log in with the admin credentials.
220
+
221
+Test the API health endpoint:
222
+```bash
223
+curl https://git.yourdomain.com/api/health
224
+```
225
+
226
+---
227
+
228
+## Step 7: Enable CI/CD Runner (Optional)
229
+
230
+If you want to run CI/CD pipelines:
231
+
232
+1. Go to your project → **Resources** → **Add New Resource**
233
+2. Select **Docker Compose** → **Existing Docker Compose**
234
+3. Add the runner service to your compose:
235
+
236
+```yaml
237
+ runner:
238
+ build:
239
+ context: .
240
+ dockerfile: Dockerfile.runner
241
+ container_name: opencodehub-runner
242
+ restart: unless-stopped
243
+ privileged: true
244
+ environment:
245
+ - RUNNER_TOKEN=${RUNNER_TOKEN}
246
+ - SERVER_URL=https://git.yourdomain.com
247
+ - DOCKER_HOST=unix:///var/run/docker.sock
248
+ volumes:
249
+ - /var/run/docker.sock:/var/run/docker.sock
250
+ - runner-work:/work
251
+ - runner-cache:/cache
252
+
253
+volumes:
254
+ runner-work:
255
+ runner-cache:
256
+```
257
+
258
+4. Get the runner token from OpenCodeHub admin panel → Runners → Register Runner
259
+5. Add `RUNNER_TOKEN` to environment variables
260
+6. Deploy the updated compose
261
+
262
+---
263
+
264
+## Step 8: Automated Deployments (GitHub Integration)
265
+
266
+### 8.1 Enable Auto-Deploy
267
+
268
+1. In Coolify, go to your app → **Settings** → **Git**
269
+2. Enable **Auto Deploy on Push**
270
+3. Coolify will automatically rebuild and redeploy on every push to `main`
271
+
272
+### 8.2 Preview Deployments (Optional)
273
+
274
+For pull request previews:
275
+1. Go to **Settings** → **Preview Deployments**
276
+2. Enable **Pull Request Previews**
277
+3. Each PR will get a unique URL like `pr-123.git.yourdomain.com`
278
+
279
+---
280
+
281
+## Maintenance
282
+
283
+### Backup
284
+
285
+Coolify has built-in backup for databases. To back up volumes:
286
+
287
+```bash
288
+# On your server
289
+docker run --rm -v opencodehub-repos:/data -v $(pwd):/backup alpine tar czf /backup/repos-backup.tar.gz -C /data .
290
+docker run --rm -v opencodehub-storage:/data -v $(pwd):/backup alpine tar czf /backup/storage-backup.tar.gz -C /data .
291
+```
292
+
293
+### Update OpenCodeHub
294
+
295
+1. Push new code to your fork/main branch
296
+2. Coolify auto-deploys, OR
297
+3. In Coolify dashboard → your app → **Deploy**
298
+
299
+### Monitor Logs
300
+
301
+In Coolify dashboard:
302
+- Go to your app → **Logs**
303
+- Real-time logs with filtering
304
+- Access historical logs
305
+
306
+---
307
+
308
+## Troubleshooting
309
+
310
+| Problem | Solution |
311
+|---------|----------|
312
+| **Build fails with "ConnectionRefused"** | Retry the build; bun registry might be temporarily unavailable. The Dockerfile has built-in retry logic. |
313
+| **App shows "502 Bad Gateway"** | Wait 2-3 minutes for first startup. Check logs for database connection errors. |
314
+| **Database connection error** | Verify `DATABASE_URL` uses the internal Coolify service name (e.g., `opencodehub-postgres`). |
315
+| **Storage not persisting** | Check that persistent volumes are mounted correctly in Coolify storage settings. |
316
+| **SSL not working** | Ensure your domain DNS points to the Coolify server. Check Coolify's SSL logs. |
317
+| **Git push over SSH fails** | Ensure port 2222 is exposed and not blocked by firewall. Map it in Coolify: `2222:2222`. |
318
+
319
+---
320
+
321
+## Architecture on Coolify
322
+
323
+```
324
+Internet
325
+ |
326
+ v
327
+Cloudflare (optional)
328
+ |
329
+ v
330
+Coolify Server
331
+ |-- Coolify Proxy (Nginx + SSL)
332
+ |-- OpenCodeHub App (Docker)
333
+ | |-- Port 4321: Web UI + API
334
+ | |-- Port 2222: SSH Git
335
+ |-- PostgreSQL (managed)
336
+ |-- Redis (managed)
337
+ |-- OpenCodeHub Runner (optional, privileged Docker)
338
+```
339
+
340
+---
341
+
342
+## Next Steps
343
+
344
+- [Configure Email (SMTP)](/administration/configuration/#email)
345
+- [Set up Storage Adapter (S3/R2)](/guides/storage-adapters/)
346
+- [Enable Branch Protection](/guides/branch-protection/)
347
+- [Set up your First Stack](/tutorials/your-first-stack/)
0
348
▼src/content/docs/administration/deploy-cpanel.md
+429-124
1
1
---
2
-title: "Deploy with cPanel"
3
-description: "Deploy OpenCodeHub on shared hosting using cPanel's Node.js Application feature"
2
+title: "Deploy on cPanel"
3
+description: "Deploy OpenCodeHub on cPanel-based shared hosting or VPS using Node.js"
4
4
---
5
5
6
-cPanel supports Node.js applications through its Application Manager. This guide covers deploying OpenCodeHub on cPanel-based shared hosting.
6
+> **Difficulty:** Intermediate | **Time:** 45-60 minutes | **Method:** Manual Node.js + PostgreSQL
7
7
8
-:::caution[Limitations]
9
-Shared hosting has significant limitations for Git servers:
8
+**cPanel** is widely used on shared hosting and VPS. While cPanel doesn't natively support Docker, you can deploy OpenCodeHub using **Node.js Selector** (if CloudLinux is available) or **Passenger** + **PM2**.
10
9
11
-- No Docker support
12
-- Limited process control
13
-- Shared resources with other users
14
-- May not support persistent processes
15
-
16
-For production use, consider a VPS or dedicated server instead.
17
-:::
10
+---
18
11
19
12
## Prerequisites
20
13
21
-- cPanel hosting with Node.js support (v18+)
22
-- PostgreSQL database addon (or external database)
23
-- SSH access recommended
24
-- Domain configured in cPanel
14
+- cPanel hosting with **SSH access** (essential)
15
+- **Node.js 20+** available (check via cPanel → Software → Select Node.js Version)
16
+- **PostgreSQL** or ability to install it (via cPanel → PostgreSQL Databases)
17
+- Minimum **2 CPU cores, 4GB RAM**
18
+- A domain/subdomain pointed to your hosting (e.g., `git.yourdomain.com`)
25
19
26
20
---
27
21
28
-## Step 1: Create PostgreSQL Database
22
+## Step 1: Prepare Your cPanel Account
29
23
30
-1. Login to cPanel
31
-2. Go to **Databases → PostgreSQL Databases**
32
-3. Create a new database: `opencodehub`
33
-4. Create a new user with a strong password
34
-5. Add user to database with ALL PRIVILEGES
35
-6. Note the connection string:
36
- ```
37
- postgresql://username:password@localhost:5432/opencodehub
24
+### 1.1 Enable SSH Access
25
+
26
+1. Log into cPanel
27
+2. Go to **Security** → **SSH Access**
28
+3. Click **Manage SSH Keys** → **Generate a New Key**
29
+4. Download the private key and authorize it
30
+5. Connect via terminal:
31
+ ```bash
32
+ ssh [email protected] -p 22
38
33
```
39
34
35
+### 1.2 Set Up Domain/Subdomain
36
+
37
+1. In cPanel, go to **Domains** → **Create a New Domain**
38
+2. Enter: `git.yourdomain.com`
39
+3. Document Root: `public_html/git` (or just `public_html`)
40
+4. Enable SSL (Let's Encrypt) in **SSL/TLS Status**
41
+
40
42
---
41
43
42
-## Step 2: Upload Application Files
44
+## Step 2: Install PostgreSQL
45
+
46
+### Option A: cPanel PostgreSQL (Shared Hosting)
47
+
48
+1. In cPanel, go to **Databases** → **PostgreSQL Databases**
49
+2. If not available, ask your host to enable it, OR use **SQLite** (not recommended for production):
50
+ ```bash
51
+ # SQLite is file-based, no server needed
52
+ # Set DATABASE_DRIVER=sqlite in .env later
53
+ ```
54
+
55
+3. Create a database:
56
+ - Database name: `cpaneluser_opencodehub`
57
+ - Username: `cpaneluser_och`
58
+ - Password: `<strong-password>`
59
+
60
+4. Note the connection details. The host is usually `localhost`.
61
+
62
+### Option B: Self-Install PostgreSQL (VPS with cPanel)
43
63
44
-### Option A: Git Clone (if SSH available)
64
+If you have root access on a VPS:
45
65
46
66
```bash
47
48
-cd ~/
49
-git clone https://github.com/swadhinbiswas/OpencodeHub.git opencodehub
67
+# Install PostgreSQL
68
+sudo dnf install postgresql16-server postgresql16-contrib # AlmaLinux/Rocky
69
+sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
70
+sudo systemctl enable --now postgresql-16
71
+
72
+# Create database
73
+sudo -u postgres psql -c "CREATE USER opencodehub WITH PASSWORD 'strongpassword';"
74
+sudo -u postgres psql -c "CREATE DATABASE opencodehub OWNER opencodehub;"
75
+sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE opencodehub TO opencodehub;"
50
76
```
51
77
52
-### Option B: File Manager Upload
78
+---
53
79
54
-1. Download the repository as ZIP from GitHub
55
-2. Go to cPanel → **File Manager**
56
-3. Navigate to your home directory
57
-4. Upload and extract the ZIP file
58
-5. Rename to `opencodehub`
80
+## Step 3: Install Node.js and Bun
59
81
82
+### 3.1 Check Node.js Version
60
83
61
-## Step 3: Create Node.js Application
84
+In cPanel:
85
+1. Go to **Software** → **Select Node.js Version** (if CloudLinux)
86
+2. Select **Node.js 20.x** or higher
87
+3. Click **Set as Current**
62
88
63
-1. Go to cPanel → **Setup Node.js App**
64
-2. Click **Create Application**
65
-3. Configure:
89
+If cPanel doesn't have Node.js selector:
66
90
67
-| Setting | Value |
68
-| ------------------------ | ----------------------- |
69
-| Node.js version | 18.x or 20.x |
70
-| Application mode | Production |
71
-| Application root | `opencodehub` |
72
-| Application URL | `git.yourdomain.com` |
73
-| Application startup file | `dist/server/entry.mjs` |
91
+```bash
92
+# SSH into your account
93
74
94
75
-4. Click **Create**
95
+# Install nvm
96
+curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
97
+source ~/.bashrc
98
+
99
+# Install Node.js 20
100
+nvm install 20
101
+nvm use 20
102
+node -v # Should show v20.x.x
103
+```
104
+
105
+### 3.2 Install Bun
106
+
107
+```bash
108
+curl -fsSL https://bun.sh/install | bash
109
+source ~/.bashrc
110
+bun -v
111
+```
76
112
77
113
---
78
114
79
-## Step 4: Configure Environment Variables
115
+## Step 4: Deploy OpenCodeHub
80
116
81
-In the Node.js Application page:
117
+### 4.1 Clone Repository
82
118
83
-1. Scroll to **Environment Variables**
84
-2. Add the following:
119
+```bash
120
+cd ~
121
+git clone https://github.com/swadhinbiswas/OpencodeHub.git
122
+cd OpenCodeHub
123
+```
124
+
125
+### 4.2 Create Production Environment File
85
126
86
127
```bash
87
-NODE_ENV=production
88
-PORT=3000
89
-SITE_URL=https://git.yourdomain.com
128
+cp .env.example .env
129
+nano .env
130
+```
131
+
132
+Edit `.env` with your cPanel settings:
90
133
134
+```bash
91
135
# Database
92
136
DATABASE_DRIVER=postgres
93
-DATABASE_URL=postgresql://cpuser_dbuser:password@localhost:5432/cpuser_opencodehub
137
+DATABASE_URL=postgresql://cpaneluser_och:YOUR_PASSWORD@localhost:5432/cpaneluser_opencodehub
94
138
95
-# Security (generate with: openssl rand -hex 32)
96
-JWT_SECRET=<64-char-hex>
97
-SESSION_SECRET=<64-char-hex>
98
-INTERNAL_HOOK_SECRET=<64-char-hex>
139
+# For SQLite fallback (if PostgreSQL unavailable)
140
+# DATABASE_DRIVER=sqlite
141
+# DATABASE_URL=file:./data/opencodehub.db
99
142
100
-# Storage
143
+# Secrets (generate with: openssl rand -hex 32)
144
+JWT_SECRET=your-64-char-hex-secret
145
+SESSION_SECRET=your-64-char-hex-secret
146
+INTERNAL_HOOK_SECRET=your-64-char-hex-secret
147
+CRON_SECRET=your-64-char-hex-secret
148
+RUNNER_SECRET=your-64-char-hex-secret
149
+WORKFLOW_SECRET_ENCRYPTION_KEY=your-64-char-hex-secret
150
+
151
+# Site URL (MUST be HTTPS in production)
152
+SITE_URL=https://git.yourdomain.com
153
+NODE_ENV=production
154
+
155
+# Storage (local is fine for single-server cPanel)
101
156
STORAGE_TYPE=local
102
-STORAGE_PATH=./data/repos
157
+STORAGE_PATH=./data/storage
158
+REPOS_PATH=./data/repos
159
+
160
+# Redis (skip if not available, use file sessions)
161
+# REDIS_URL=redis://localhost:6379
162
+
163
+# Skip Redis check during build
164
+SKIP_REDIS_CHECK=1
103
165
```
104
166
105
-3. Click **Save**
167
+> **IMPORTANT:** On cPanel shared hosting, you likely don't have Redis. OpenCodeHub will work without it using in-memory sessions (restart clears sessions) or you can use SQLite for sessions.
106
168
169
+### 4.3 Install Dependencies
170
+
171
+```bash
172
+# Install dependencies (with retry in case of network issues)
173
+for i in 1 2 3; do
174
+ bun install --frozen-lockfile && break
175
+ echo "Attempt $i failed, retrying in 10s..."
176
+ sleep 10
177
+done
178
+```
107
179
108
-## Step 5: Install Dependencies and Build
180
+If bun install fails due to native modules:
181
+```bash
182
+# Some cPanel environments lack build tools
183
+# Install with npm instead for better compatibility
184
+npm install
185
+```
109
186
110
-1. In the Node.js app page, click **Run NPM Install**
111
-2. Connect via SSH and run:
187
+### 4.4 Build the Application
112
188
113
189
```bash
114
-cd ~/opencodehub
190
+export SKIP_REDIS_CHECK=1
191
+bun run build
192
+```
115
193
116
-# Enter virtual environment
117
-source /home/username/nodevenv/opencodehub/18/bin/activate
194
+This creates the `dist/` directory with the production build.
118
195
119
-# Install dependencies
120
-npm install
196
+### 4.5 Initialize Database
121
197
122
-# Build the application
123
-npm run build
198
+```bash
199
+# Push schema to database
200
+bun run db:push
124
201
125
-# Initialize database
126
-npm run db:push
202
+# Or generate and run migrations
203
+bun run db:generate
204
+bun run db:migrate
205
+```
206
+
207
+### 4.6 Create Admin User
127
208
128
-# Create admin user (if script exists)
129
-npm run scripts/seed-admin.ts
209
+```bash
210
+bun run scripts/seed-admin.ts
130
211
```
212
+Enter username, email, and password when prompted.
131
213
132
214
---
133
215
134
-## Step 6: Start Application
216
+## Step 5: Set Up Process Manager (PM2)
135
217
136
-1. In cPanel Node.js app manager, click **Start App**
137
-2. Verify it's running by visiting your domain
218
+cPanel doesn't keep Node.js apps running by default. Use PM2:
138
219
220
+### 5.1 Install PM2
139
221
140
-## Alternative: Using PM2
222
+```bash
223
+npm install -g pm2
224
+```
141
225
142
-If your host supports PM2:
226
+### 5.2 Create PM2 Config
143
227
144
228
```bash
145
-# Install PM2 globally
146
-npm install -g pm2
229
+cat > ~/OpenCodeHub/ecosystem.config.cjs << 'EOF'
230
+module.exports = {
231
+ apps: [{
232
+ name: 'opencodehub',
233
+ script: './dist/server/entry.mjs',
234
+ cwd: '/home/cpaneluser/OpenCodeHub',
235
+ instances: 1,
236
+ exec_mode: 'fork',
237
+ env: {
238
+ NODE_ENV: 'production',
239
+ PORT: 3000,
240
+ HOST: '127.0.0.1'
241
+ },
242
+ error_file: '/home/cpaneluser/logs/opencodehub-error.log',
243
+ out_file: '/home/cpaneluser/logs/opencodehub-out.log',
244
+ log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
245
+ merge_logs: true,
246
+ max_memory_restart: '1G',
247
+ restart_delay: 3000,
248
+ max_restarts: 5,
249
+ min_uptime: '10s',
250
+ watch: false,
251
+ autorestart: true
252
+ }]
253
+};
254
+EOF
255
+```
147
256
148
-# Start with PM2
149
-pm2 start dist/server/entry.mjs --name opencodehub
257
+> Replace `cpaneluser` with your actual cPanel username.
150
258
151
-# Save process list
152
-pm2 save
259
+### 5.3 Create Log Directory
153
260
154
-# Setup startup script
261
+```bash
262
+mkdir -p ~/logs
263
+```
264
+
265
+### 5.4 Start with PM2
266
+
267
+```bash
268
+cd ~/OpenCodeHub
269
+pm2 start ecosystem.config.cjs
270
+pm2 save
155
271
pm2 startup
156
272
```
157
273
274
+The `startup` command will output a command to run with `sudo` (if you have root). On shared hosting without root, add PM2 to your `.bash_profile`:
275
+
276
+```bash
277
+echo 'pm2 resurrect' >> ~/.bash_profile
278
+```
279
+
158
280
---
159
281
160
-## Handling Git Operations
282
+## Step 6: Configure Reverse Proxy
283
+
284
+### 6.1 Using .htaccess (Apache - Most Common)
285
+
286
+In your `public_html` directory, create/edit `.htaccess`:
287
+
288
+```apache
289
+<IfModule mod_rewrite.c>
290
+ RewriteEngine On
291
+ RewriteBase /
161
292
162
-:::warning[Important]
163
-cPanel's Node.js apps may not handle long-running Git operations well. For push/pull with large repos, you may experience timeouts.
164
-:::
293
+ # Redirect HTTP to HTTPS
294
+ RewriteCond %{HTTPS} off
295
+ RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
165
296
166
-### Workarounds
297
+ # Proxy all requests to Node.js app
298
+ RewriteCond %{REQUEST_FILENAME} !-f
299
+ RewriteCond %{REQUEST_FILENAME} !-d
300
+ RewriteRule ^(.*)$ http://127.0.0.1:3000/$1 [P,L]
301
+</IfModule>
167
302
168
-1. **Increase PHP/Node timeout** (if available in hosting settings)
169
-2. **Use external storage** (S3) to reduce local I/O
170
-3. **Consider VPS** for better control
303
+# Enable proxy modules (host must have these enabled)
304
+<IfModule mod_proxy.c>
305
+ ProxyPass / http://127.0.0.1:3000/
306
+ ProxyPassReverse / http://127.0.0.1:3000/
307
+
308
+ # WebSocket support
309
+ RewriteCond %{HTTP:Upgrade} websocket [NC]
310
+ RewriteCond %{HTTP:Connection} upgrade [NC]
311
+ RewriteRule ^/?(.*) "ws://127.0.0.1:3000/$1" [P,L]
312
+</IfModule>
313
+
314
+# Increase limits for Git operations
315
+<IfModule mod_reqtimeout.c>
316
+ RequestReadTimeout header=20-40,minrate=500
317
+ RequestReadTimeout body=10,minrate=500
318
+</IfModule>
319
+
320
+LimitRequestBody 104857600
321
+```
322
+
323
+> **Note:** Some shared hosts disable `mod_proxy`. If `.htaccess` proxy doesn't work, ask your host to enable it, OR use the Node.js Selector method below.
324
+
325
+### 6.2 Using cPanel Node.js Selector (CloudLinux)
326
+
327
+If your host has CloudLinux with Node.js Selector:
328
+
329
+1. In cPanel, go to **Software** → **Setup Node.js App**
330
+2. Click **Create Application**
331
+3. Configuration:
332
+ ```
333
+ Node.js Version: 20.x
334
+ Application Mode: Production
335
+ Application Root: /home/cpaneluser/OpenCodeHub
336
+ Application URL: git.yourdomain.com
337
+ Application Startup File: dist/server/entry.mjs
338
+ ```
339
+4. Click **Create**
340
+5. In **Environment Variables**, add all variables from your `.env`
341
+6. Click **Save**
342
+7. Click **Restart**
343
+
344
+### 6.3 Using Nginx Reverse Proxy (VPS with cPanel + Nginx)
345
+
346
+If your cPanel server uses Nginx:
347
+
348
+```nginx
349
+# In cPanel → Nginx Manager → Custom Configuration
350
+# OR via SSH in /etc/nginx/conf.d/opencodehub.conf
351
+
352
+server {
353
+ listen 80;
354
+ server_name git.yourdomain.com;
355
+ return 301 https://$server_name$request_uri;
356
+}
357
+
358
+server {
359
+ listen 443 ssl http2;
360
+ server_name git.yourdomain.com;
361
+
362
+ ssl_certificate /path/to/ssl.crt;
363
+ ssl_certificate_key /path/to/ssl.key;
364
+
365
+ location / {
366
+ proxy_pass http://127.0.0.1:3000;
367
+ proxy_http_version 1.1;
368
+ proxy_set_header Upgrade $http_upgrade;
369
+ proxy_set_header Connection 'upgrade';
370
+ proxy_set_header Host $host;
371
+ proxy_set_header X-Real-IP $remote_addr;
372
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
373
+ proxy_set_header X-Forwarded-Proto $scheme;
374
+ proxy_cache_bypass $http_upgrade;
375
+ }
376
+
377
+ location ~ ^/[^/]+/[^/]+\.git/ {
378
+ proxy_pass http://127.0.0.1:3000;
379
+ proxy_read_timeout 600s;
380
+ proxy_send_timeout 600s;
381
+ client_max_body_size 100M;
382
+ }
383
+}
384
+```
171
385
172
386
---
173
387
174
-## Troubleshooting
388
+## Step 7: Verify Deployment
389
+
390
+### 7.1 Check App is Running
391
+
392
+```bash
393
+pm2 status
394
+pm2 logs opencodehub
395
+```
396
+
397
+### 7.2 Test Health Endpoint
398
+
399
+```bash
400
+curl http://127.0.0.1:3000/api/health
401
+```
402
+
403
+### 7.3 Test from Browser
175
404
176
-### Application Won't Start
405
+Visit `https://git.yourdomain.com` and log in.
177
406
178
-1. Check error logs in cPanel → **Errors**
179
-2. Verify Node.js version compatibility
180
-3. Check if all dependencies installed
181
-4. Verify startup file path is correct
407
+---
408
+
409
+## Step 8: Git SSH Access (Advanced)
410
+
411
+cPanel shared hosting typically doesn't allow custom SSH ports. For Git over SSH, you have options:
412
+
413
+### Option A: Use Git over HTTPS (Recommended for cPanel)
414
+
415
+OpenCodeHub supports Git over HTTP(S) out of the box. Users can:
416
+```bash
417
+git clone https://git.yourdomain.com/username/repo.git
418
+```
419
+
420
+### Option B: Use a Different Port for SSH Git
182
421
183
-### Database Connection Errors
422
+If your host allows additional ports:
184
423
185
424
```bash
186
-# Test connection via SSH
187
-psql "postgresql://user:pass@localhost/dbname"
425
+# In .env
426
+GIT_SSH_PORT=2222
427
+
428
+# Start SSH git server
429
+bun run git:start
188
430
```
189
431
190
-### 503 Service Unavailable
432
+Add to PM2 config:
433
+```javascript
434
+apps: [
435
+ {
436
+ name: 'opencodehub',
437
+ script: './dist/server/entry.mjs',
438
+ // ... main app config
439
+ },
440
+ {
441
+ name: 'opencodehub-ssh',
442
+ script: './scripts/ssh-server.ts',
443
+ cwd: '/home/cpaneluser/OpenCodeHub',
444
+ interpreter: 'bun'
445
+ }
446
+]
447
+```
191
448
192
-- Application may have crashed
193
-- Check logs and restart via cPanel
449
+> **Note:** Most shared hosts block non-standard ports. HTTPS Git is the safest option.
194
450
195
451
---
196
452
197
-## Limitations Summary
453
+## Maintenance
454
+
455
+### Update OpenCodeHub
456
+
457
+```bash
458
+cd ~/OpenCodeHub
459
+git pull origin main
460
+
461
+# Rebuild
462
+export SKIP_REDIS_CHECK=1
463
+bun install
464
+bun run build
465
+bun run db:push
466
+
467
+# Restart
468
+pm2 restart opencodehub
469
+```
198
470
199
-| Feature | cPanel Support |
200
-| --------------- | ----------------------------- |
201
-| Web UI | ✅ Works |
202
-| Git clone/push | ⚠️ May timeout on large repos |
203
-| WebSockets | ❌ Usually not supported |
204
-| Background jobs | ❌ Limited |
205
-| Custom domains | ✅ Works |
206
-| SSL | ✅ Via AutoSSL |
471
+### Backup
472
+
473
+```bash
474
+# Database backup (PostgreSQL)
475
+pg_dump $DATABASE_URL > ~/backups/opencodehub-$(date +%Y%m%d).sql
476
+
477
+# File backup
478
+cd ~
479
+tar czf backups/opencodehub-files-$(date +%Y%m%d).tar.gz OpenCodeHub/data
480
+```
481
+
482
+Set up a cron job in cPanel → **Cron Jobs**:
483
+```bash
484
+# Daily at 2 AM
485
+0 2 * * * /home/cpaneluser/.nvm/versions/node/v20.x.x/bin/node /home/cpaneluser/scripts/backup.js
486
+```
207
487
208
488
---
209
489
210
-## Recommended Alternative
490
+## Troubleshooting
211
491
212
-For a Git server, we strongly recommend:
492
+| Problem | Solution |
493
+|---------|----------|
494
+| **"Forbidden 403" error** | Check file permissions. Directories should be 755, files 644. |
495
+| **Node.js app not starting** | Check logs: `pm2 logs`. Verify Node.js version is 20+. |
496
+| **Database connection failed** | Verify PostgreSQL is running and credentials are correct. Check if `localhost` is the right host (some cPanel uses `127.0.0.1`). |
497
+| **Build fails with memory error** | cPanel shared hosting often limits memory. Try `NODE_OPTIONS="--max-old-space-size=1024" bun run build`. |
498
+| **Git push fails** | Use HTTPS Git instead of SSH. cPanel shared hosting rarely allows custom SSH ports. |
499
+| **Static assets not loading** | Ensure `dist/` folder is built and the reverse proxy is forwarding all requests correctly. |
500
+| **Session lost on restart** | Without Redis, sessions are in-memory. For persistence, ask host to enable Redis, or use PostgreSQL session store (requires code change). |
501
+
502
+---
503
+
504
+## Limitations on cPanel Shared Hosting
505
+
506
+| Feature | Shared Hosting | VPS/Dedicated |
507
+|---------|---------------|---------------|
508
+| Docker | Not available | Available |
509
+| Redis | Rarely available | Available |
510
+| Custom SSH ports | Blocked | Available |
511
+| CI/CD Runner | Not possible (needs Docker) | Available |
512
+| Resource limits | Low (1-2GB RAM) | Configurable |
513
+| Storage adapters | Local only | All adapters |
514
+
515
+For full functionality, consider upgrading to a VPS or using Coolify/Docker deployment instead.
516
+
517
+---
213
518
214
-1. **VPS** (DigitalOcean, Linode, Vultr) - Full control
215
-2. **Docker** on any cloud provider - Easy deployment
216
-3. **Vercel/Cloudflare** - For serverless approach
519
+## Next Steps
217
520
218
-See [Docker Deployment Guide](/administration/deploy-docker/) for production setups.
521
+- [Configure Email (SMTP)](/administration/configuration/#email)
522
+- [Enable Branch Protection](/guides/branch-protection/)
523
+- [Troubleshooting Common Issues](/support/troubleshooting/)
219
524
▼src/content/docs/administration/deploy-cyberpanel.md
+468-191
1
1
---
2
-title: "Deploy with CyberPanel"
3
-description: "Deploy OpenCodeHub using CyberPanel with OpenLiteSpeed web server"
2
+title: "Deploy on CyberPanel"
3
+description: "Deploy OpenCodeHub using CyberPanel with OpenLiteSpeed web server or Docker"
4
4
---
5
5
6
-CyberPanel is a hosting control panel that uses OpenLiteSpeed (OLS) as its web server. This guide covers deploying OpenCodeHub on a CyberPanel server.
6
+> **Difficulty:** Easy-Intermediate | **Time:** 25-35 minutes | **Method:** Docker Compose (recommended) or LiteSpeed Node.js
7
+
8
+**CyberPanel** is a modern, free, open-source hosting control panel powered by OpenLiteSpeed. It offers better performance than cPanel for modern applications and has native Docker support in the Enterprise version.
9
+
10
+---
7
11
8
12
## Prerequisites
9
13
10
-- CyberPanel installed on a VPS
11
-- Root SSH access
12
-- Domain pointed to your server
13
-- PostgreSQL or MySQL available
14
+- VPS with Ubuntu 22.04/24.04, AlmaLinux 8/9, or Rocky Linux 8/9
15
+- Minimum **2 CPU cores, 4GB RAM, 40GB SSD**
16
+- Root or sudo access
17
+- A domain/subdomain pointed to your server (e.g., `git.yourdomain.com`)
14
18
15
19
---
16
20
17
-## Step 1: Create Website in CyberPanel
21
+## Step 1: Install CyberPanel
22
+
23
+If you haven't installed CyberPanel yet:
18
24
19
-1. Login to CyberPanel admin panel
20
-2. Go to **Websites → Create Website**
21
-3. Configure:
22
- - Domain: `git.yourdomain.com`
23
- - Email: your email
24
- - PHP: None (we'll use Node.js)
25
- - SSL: Issue SSL via Let's Encrypt
25
+```bash
26
+# Run the installer
27
+sh <(curl https://cyberpanel.net/install.sh || wget -O - https://cyberpanel.net/install.sh)
28
+```
29
+
30
+During installation:
31
+1. Select **1** for CyberPanel + OpenLiteSpeed
32
+2. Select **1** for Full installation
33
+3. Set MySQL password
34
+4. Choose whether to install PowerDNS, Postfix, Pure-FTPd (optional)
35
+5. Install Memcached/Redis (select **Y** for Redis - we'll use it)
36
+6. Install Watchdog (recommended)
37
+
38
+After installation, access CyberPanel at:
39
+```
40
+https://your-server-ip:8090
41
+```
26
42
27
43
---
28
44
29
-## Step 2: Install Node.js
45
+## Deployment Method A: Docker Compose (Recommended)
46
+
47
+CyberPanel Enterprise and recent versions support Docker. This is the easiest and most complete method.
48
+
49
+### Step A.1: Enable Docker in CyberPanel
30
50
31
-CyberPanel doesn't include Node.js by default. Install via SSH:
51
+1. Log into CyberPanel
52
+2. Go to **Docker** → **Install Docker**
53
+3. Wait for installation to complete
54
+4. Go to **Docker** → **Images** → **Pull Image**
55
+5. Pull these images:
56
+ - `postgres:16-alpine`
57
+ - `redis:7-alpine`
58
+
59
+### Step A.2: Create Docker Network
32
60
33
61
```bash
34
-# Connect via SSH as root
62
+# SSH into your server
35
63
ssh root@your-server-ip
36
64
37
-# Install Node.js 20.x
38
-curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
39
-apt install -y nodejs
65
+docker network create opencodehub-network
66
+```
67
+
68
+### Step A.3: Create Persistent Volumes
40
69
41
-# Verify
42
-node --version # Should be 20.x
43
-npm --version
70
+```bash
71
+mkdir -p /var/lib/opencodehub/{repos,storage,ssh,cache}
44
72
```
45
73
74
+### Step A.4: Start PostgreSQL Container
46
75
47
-## Step 3: Install PostgreSQL
76
+In CyberPanel:
77
+1. Go to **Docker** → **Containers** → **Create Container**
78
+2. Or use CLI:
48
79
49
80
```bash
50
-# Install PostgreSQL
51
-apt install -y postgresql postgresql-contrib
52
-
53
-# Create database and user
54
-sudo -u postgres psql << EOF
55
-CREATE DATABASE opencodehub;
56
-CREATE USER opencodehub WITH ENCRYPTED PASSWORD 'your-secure-password';
57
-GRANT ALL PRIVILEGES ON DATABASE opencodehub TO opencodehub;
58
-\c opencodehub
59
-GRANT ALL ON SCHEMA public TO opencodehub;
60
-EOF
81
+docker run -d \
82
+ --name opencodehub-postgres \
83
+ --network opencodehub-network \
84
+ -e POSTGRES_USER=opencodehub \
85
+ -e POSTGRES_PASSWORD=$(openssl rand -hex 16) \
86
+ -e POSTGRES_DB=opencodehub \
87
+ -v opencodehub-postgres:/var/lib/postgresql/data \
88
+ -p 127.0.0.1:5432:5432 \
89
+ --restart unless-stopped \
90
+ postgres:16-alpine
61
91
```
62
92
93
+Note the password you set.
63
94
64
-## Step 4: Clone and Setup Application
95
+### Step A.5: Start Redis Container
65
96
66
97
```bash
67
-# Create app directory
68
-mkdir -p /home/git.yourdomain.com/app
69
-cd /home/git.yourdomain.com/app
98
+docker run -d \
99
+ --name opencodehub-redis \
100
+ --network opencodehub-network \
101
+ -v opencodehub-redis:/data \
102
+ -p 127.0.0.1:6379:6379 \
103
+ --restart unless-stopped \
104
+ redis:7-alpine \
105
+ redis-server --appendonly yes --requirepass $(openssl rand -hex 16)
106
+```
70
107
71
-# Clone repository
72
-git clone https://github.com/swadhinbiswas/OpencodeHub.git .
108
+Note the Redis password.
73
109
74
-# Install dependencies
75
-npm install
110
+### Step A.6: Deploy OpenCodeHub
111
+
112
+#### Clone and Build
113
+
114
+```bash
115
+cd /var/lib/opencodehub
116
+git clone https://github.com/swadhinbiswas/OpencodeHub.git
117
+cd OpenCodeHub
76
118
77
119
# Create environment file
78
-cat > .env << 'EOF'
79
-NODE_ENV=production
80
-PORT=3000
81
-SITE_URL=https://git.yourdomain.com
120
+cp .env.example .env
121
+nano .env
122
+```
82
123
124
+Configure `.env`:
125
+```bash
83
126
# Database
84
127
DATABASE_DRIVER=postgres
85
-DATABASE_URL=postgresql://opencodehub:your-secure-password@localhost:5432/opencodehub
128
+DATABASE_URL=postgresql://opencodehub:[email protected]:5432/opencodehub
129
+
130
+# Redis
131
+REDIS_URL=redis://:[email protected]:6379
86
132
87
-# Security (generate with: openssl rand -hex 32)
88
-JWT_SECRET=your-64-char-jwt-secret
89
-SESSION_SECRET=your-64-char-session-secret
90
-INTERNAL_HOOK_SECRET=your-64-char-hook-secret
133
+# Secrets (generate each with: openssl rand -hex 32)
134
+JWT_SECRET=
135
+SESSION_SECRET=
136
+INTERNAL_HOOK_SECRET=
137
+CRON_SECRET=
138
+RUNNER_SECRET=
139
+WORKFLOW_SECRET_ENCRYPTION_KEY=
140
+
141
+# Site
142
+SITE_URL=https://git.yourdomain.com
143
+NODE_ENV=production
91
144
92
145
# Storage
93
146
STORAGE_TYPE=local
94
-STORAGE_PATH=./data/repos
95
-EOF
147
+STORAGE_PATH=/data/storage
148
+REPOS_PATH=/data/repos
149
+SSH_HOST_KEY_PATH=/data/ssh/host_key
96
150
97
-# Build
98
-npm run build
151
+# Skip Redis check during build
152
+SKIP_REDIS_CHECK=1
153
+```
99
154
100
-# Initialize database
101
-npm run db:push
155
+#### Build and Run
102
156
103
-# Create admin user
104
-npm run scripts/seed-admin.ts
157
+```bash
158
+# Build the Docker image
159
+docker build -t opencodehub:prod .
160
+
161
+# Run the container
162
+docker run -d \
163
+ --name opencodehub \
164
+ --network opencodehub-network \
165
+ -p 127.0.0.1:4321:4321 \
166
+ -p 2222:2222 \
167
+ -v /var/lib/opencodehub/repos:/data/repos \
168
+ -v /var/lib/opencodehub/storage:/data/storage \
169
+ -v /var/lib/opencodehub/ssh:/data/ssh \
170
+ -v /var/lib/opencodehub/cache:/data/cache \
171
+ --env-file .env \
172
+ --restart unless-stopped \
173
+ opencodehub:prod
105
174
```
106
175
176
+### Step A.7: Configure Reverse Proxy in CyberPanel
107
177
108
-## Step 5: Configure OpenLiteSpeed
178
+1. In CyberPanel, go to **Websites** → **Create Website**
179
+2. Domain: `git.yourdomain.com`
180
+3. Package: Default
181
+4. Owner: admin
182
+5. PHP: Any (we'll use proxy, not PHP)
183
+6. SSL: Select **Issue SSL**
184
+7. Click **Create Website**
109
185
110
-CyberPanel uses OpenLiteSpeed. We need to set up reverse proxy.
186
+Now configure the reverse proxy:
111
187
112
-### Create Proxy Configuration
188
+```bash
189
+# SSH into server
190
+nano /usr/local/lsws/conf/vhosts/git.yourdomain.com/vhost.conf
191
+```
113
192
114
-1. SSH into server
115
-2. Edit the vhost config:
193
+Add or modify the virtual host configuration:
116
194
195
+```apache
196
+<virtualHost>
197
+ <name>git.yourdomain.com</name>
198
+ <address>*</address>
199
+ <port>80</port>
200
+ <docRoot>/var/www/html</docRoot>
201
+
202
+ <rewrite>
203
+ <enable>1</enable>
204
+ <rules>
205
+RewriteEngine On
206
+RewriteCond %{HTTPS} off
207
+RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
208
+ </rules>
209
+ </rewrite>
210
+</virtualHost>
211
+
212
+<virtualHost>
213
+ <name>git.yourdomain.com</name>
214
+ <address>*</address>
215
+ <port>443</port>
216
+ <docRoot>/var/www/html</docRoot>
217
+
218
+ <ssl>
219
+ <enable>1</enable>
220
+ <certFile>/etc/letsencrypt/live/git.yourdomain.com/fullchain.pem</certFile>
221
+ <keyFile>/etc/letsencrypt/live/git.yourdomain.com/privkey.pem</keyFile>
222
+ </ssl>
223
+
224
+ <extProcessor>
225
+ <name>opencodehub</name>
226
+ <type>proxy</type>
227
+ <address>127.0.0.1:4321</address>
228
+ <maxConns>100</maxConns>
229
+ <initTimeout>30</initTimeout>
230
+ <retryTimeout>10</retryTimeout>
231
+ <pcKeepAliveTimeout>5</pcKeepAliveTimeout>
232
+ </extProcessor>
233
+
234
+ <context>
235
+ <type>proxy</type>
236
+ <uri>/</uri>
237
+ <handler>opencodehub</handler>
238
+ <addDefaultCharset>off</addDefaultCharset>
239
+ </context>
240
+
241
+ <context>
242
+ <type>proxy</type>
243
+ <uri>/*.git/</uri>
244
+ <handler>opencodehub</handler>
245
+ <addDefaultCharset>off</addDefaultCharset>
246
+ </context>
247
+</virtualHost>
248
+```
249
+
250
+Restart OpenLiteSpeed:
117
251
```bash
118
-nano /usr/local/lsws/conf/vhosts/git.yourdomain.com/vhconf.conf
252
+systemctl restart lsws
119
253
```
120
254
121
-3. Add or modify the config:
255
+---
122
256
123
-```apache
124
-docRoot $VH_ROOT/public_html
125
-enableGzip 1
126
-
127
-context / {
128
- type proxy
129
- handler localhost:3000
130
- addDefaultCharset off
131
-}
132
-
133
-rewrite {
134
- enable 1
135
- autoLoadHtaccess 1
136
-}
257
+## Deployment Method B: LiteSpeed Node.js (No Docker)
258
+
259
+If you prefer not to use Docker, CyberPanel supports Node.js apps natively via LiteSpeed.
260
+
261
+### Step B.1: Install Node.js
262
+
263
+```bash
264
+# SSH as root
265
+source /etc/profile
266
+yum install -y nodejs npm # AlmaLinux/Rocky
267
+# OR
268
+apt install -y nodejs npm # Ubuntu
269
+
270
+# Install Bun
271
+curl -fsSL https://bun.sh/install | bash
137
272
```
138
273
139
-### Alternative: Via CyberPanel UI
274
+### Step B.2: Create Website in CyberPanel
140
275
141
-1. Go to **Websites → List Websites**
142
-2. Click on your website → **vHost Conf**
143
-3. Add the proxy context as shown above
144
-4. Click **Save**
276
+1. **Websites** → **Create Website**
277
+2. Domain: `git.yourdomain.com`
278
+3. SSL: Issue Let's Encrypt
279
+4. Click **Create**
145
280
146
-### Restart LiteSpeed
281
+### Step B.3: Set Up PostgreSQL
282
+
283
+CyberPanel uses MariaDB by default. Install PostgreSQL:
147
284
148
285
```bash
149
-systemctl restart lsws
286
+# AlmaLinux/Rocky 9
287
+sudo dnf install -y postgresql16-server postgresql16-contrib
288
+sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
289
+sudo systemctl enable --now postgresql-16
290
+
291
+# Create database
292
+sudo -u postgres psql -c "CREATE USER opencodehub WITH PASSWORD 'strongpassword';"
293
+sudo -u postgres psql -c "CREATE DATABASE opencodehub OWNER opencodehub;"
150
294
```
151
295
296
+### Step B.4: Deploy OpenCodeHub Code
297
+
298
+```bash
299
+cd /home/git.yourdomain.com/public_html
300
+git clone https://github.com/swadhinbiswas/OpencodeHub.git .
301
+```
302
+
303
+### Step B.5: Configure Node.js App in CyberPanel
304
+
305
+1. Go to **Websites** → **List Websites**
306
+2. Click **Manage** for `git.yourdomain.com`
307
+3. Go to **Node.js** → **Setup Node.js App**
308
+4. Configuration:
309
+ ```
310
+ Application Name: opencodehub
311
+ Application Startup File: dist/server/entry.mjs
312
+ Application Path: /home/git.yourdomain.com/public_html
313
+ Application URL: git.yourdomain.com
314
+ ```
315
+5. In **Environment Variables**, add all values from `.env`
316
+6. Click **Create**
152
317
153
-## Step 6: Setup Process Manager (PM2)
318
+### Step B.6: Build and Start
154
319
155
320
```bash
156
-# Install PM2
157
-npm install -g pm2
321
+cd /home/git.yourdomain.com/public_html
322
+cp .env.example .env
323
+# Edit .env with your values
324
+nano .env
158
325
159
-# Start OpenCodeHub
160
-cd /home/git.yourdomain.com/app
161
-pm2 start dist/server/entry.mjs --name opencodehub
326
+# Install dependencies
327
+bun install
328
+
329
+# Build
330
+export SKIP_REDIS_CHECK=1
331
+bun run build
162
332
163
-# Save process list
164
-pm2 save
333
+# Initialize database
334
+bun run db:push
165
335
166
-# Setup startup script
167
-pm2 startup systemd
168
-# Run the command it outputs
336
+# Create admin user
337
+bun run scripts/seed-admin.ts
169
338
```
170
339
340
+Back in CyberPanel:
341
+1. Go to **Node.js** → **Manage Node.js Apps**
342
+2. Click **Start** for your app
171
343
172
-## Step 7: Configure Firewall
344
+---
173
345
174
-CyberPanel uses firewalld:
346
+## Step 2: Create Admin User (Docker Method)
175
347
176
348
```bash
177
-# Allow necessary ports (if not already open)
178
-firewall-cmd --permanent --add-port=3000/tcp
179
-firewall-cmd --reload
349
+# If using Docker
350
+docker exec -it opencodehub bun run scripts/seed-admin.ts
180
351
```
181
352
182
-:::note
183
-Port 3000 only needs to be open if accessing directly. With the reverse proxy, only 80/443 need to be open.
184
-:::
353
+Enter username, email, and password.
185
354
186
355
---
187
356
188
-## SSL Configuration
357
+## Step 3: Verify Installation
189
358
190
-CyberPanel can automatically issue SSL via Let's Encrypt:
359
+```bash
360
+# Check container is running
361
+docker ps
191
362
192
-1. Go to **SSL → Manage SSL**
193
-2. Select your website
194
-3. Click **Issue SSL**
363
+# Check logs
364
+docker logs opencodehub
195
365
196
-The SSL will be automatically configured for OpenLiteSpeed.
366
+# Test health
367
+curl http://127.0.0.1:4321/api/health
368
+```
369
+
370
+Visit `https://git.yourdomain.com` in your browser.
197
371
198
372
---
199
373
200
-## OpenLiteSpeed Optimizations
374
+## Step 4: Configure Firewall
201
375
202
-### Increase Timeouts for Git Operations
376
+CyberPanel uses firewalld/ufw. Open necessary ports:
203
377
204
-Edit `/usr/local/lsws/conf/vhosts/git.yourdomain.com/vhconf.conf`:
378
+```bash
379
+# For SSH Git access
380
+firewall-cmd --permanent --add-port=2222/tcp
381
+firewall-cmd --reload
205
382
206
-```apache
207
-context / {
208
- type proxy
209
- handler localhost:3000
210
- addDefaultCharset off
211
-
212
- # Extended timeouts for git operations
213
- extraparam {
214
- ProxyTimeout 600
215
- }
216
-}
383
+# For OpenCodeHub web (if not using reverse proxy)
384
+# Port 4321 should only be accessible locally (127.0.0.1) when behind proxy
217
385
```
218
386
219
-### Enable WebSocket Support
387
+---
220
388
221
-```apache
222
-context /ws {
223
- type proxy
224
- handler localhost:3000
225
- addDefaultCharset off
226
-
227
- extraparam {
228
- WebSocket 1
229
- }
230
-}
389
+## Step 5: Set Up CI/CD Runner (Docker Method)
390
+
391
+If you deployed via Docker:
392
+
393
+```bash
394
+# Build runner image
395
+docker build -t opencodehub-runner -f Dockerfile.runner .
396
+
397
+# Run runner
398
+docker run -d \
399
+ --name opencodehub-runner \
400
+ --network opencodehub-network \
401
+ --privileged \
402
+ -e SERVER_URL=https://git.yourdomain.com \
403
+ -e RUNNER_TOKEN=<get-from-admin-panel> \
404
+ -v /var/run/docker.sock:/var/run/docker.sock \
405
+ -v /var/lib/opencodehub/runner-work:/work \
406
+ -v /var/lib/opencodehub/runner-cache:/cache \
407
+ --restart unless-stopped \
408
+ opencodehub-runner
231
409
```
232
410
411
+Get the runner token from OpenCodeHub admin panel → **Runners** → **Register Runner**.
412
+
233
413
---
234
414
235
-## Monitoring with CyberPanel
415
+## Step 6: SSL with Let's Encrypt
236
416
237
-### View Logs
417
+### In CyberPanel Dashboard:
238
418
239
-1. Go to **Logs → Access Logs** or **Error Logs**
240
-2. Select your website
419
+1. Go to **SSL** → **Manage SSL**
420
+2. Select `git.yourdomain.com`
421
+3. Click **Issue SSL**
422
+4. CyberPanel will automatically configure OpenLiteSpeed with the certificate
241
423
242
-### PM2 Monitoring
424
+### Auto-Renewal:
243
425
244
-```bash
245
-# View status
246
-pm2 status
426
+CyberPanel handles Let's Encrypt auto-renewal automatically.
247
427
248
-# View logs
249
-pm2 logs opencodehub
428
+---
250
429
251
-# Monitor resources
252
-pm2 monit
253
-```
430
+## Maintenance
254
431
432
+### Update OpenCodeHub
255
433
256
-## Troubleshooting
434
+```bash
435
+cd /var/lib/opencodehub/OpenCodeHub
436
+git pull origin main
257
437
258
-### 503 Bad Gateway
438
+# Rebuild
439
+docker build -t opencodehub:prod .
440
+
441
+# Restart container
442
+docker stop opencodehub
443
+docker rm opencodehub
259
444
260
-1. Check if Node.js app is running: `pm2 status`
261
-2. Verify port 3000 is listening: `netstat -tlnp | grep 3000`
262
-3. Check LiteSpeed error logs: `/usr/local/lsws/logs/error.log`
445
+# Re-run with same docker run command from Step A.6
446
+```
263
447
264
-### Application Crashes on Restart
448
+Or use Docker Compose for easier management:
265
449
266
450
```bash
267
-# Check PM2 logs
268
-pm2 logs opencodehub --lines 100
451
+# Create docker-compose.yml in /var/lib/opencodehub
452
+cat > docker-compose.yml << 'EOF'
453
+version: '3.8'
454
+
455
+services:
456
+ app:
457
+ build:
458
+ context: ./OpenCodeHub
459
+ dockerfile: Dockerfile
460
+ container_name: opencodehub
461
+ restart: unless-stopped
462
+ ports:
463
+ - "127.0.0.1:4321:4321"
464
+ - "2222:2222"
465
+ env_file: ./OpenCodeHub/.env
466
+ volumes:
467
+ - ./repos:/data/repos
468
+ - ./storage:/data/storage
469
+ - ./ssh:/data/ssh
470
+ - ./cache:/data/cache
471
+ depends_on:
472
+ - postgres
473
+ - redis
474
+ networks:
475
+ - och-net
476
+
477
+ postgres:
478
+ image: postgres:16-alpine
479
+ restart: unless-stopped
480
+ environment:
481
+ POSTGRES_USER: opencodehub
482
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
483
+ POSTGRES_DB: opencodehub
484
+ volumes:
485
+ - ./postgres-data:/var/lib/postgresql/data
486
+ networks:
487
+ - och-net
488
+
489
+ redis:
490
+ image: redis:7-alpine
491
+ restart: unless-stopped
492
+ command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
493
+ volumes:
494
+ - ./redis-data:/data
495
+ networks:
496
+ - och-net
497
+
498
+ runner:
499
+ build:
500
+ context: ./OpenCodeHub
501
+ dockerfile: Dockerfile.runner
502
+ container_name: opencodehub-runner
503
+ restart: unless-stopped
504
+ privileged: true
505
+ environment:
506
+ - SERVER_URL=https://git.yourdomain.com
507
+ - RUNNER_TOKEN=${RUNNER_TOKEN}
508
+ - DOCKER_HOST=unix:///var/run/docker.sock
509
+ volumes:
510
+ - /var/run/docker.sock:/var/run/docker.sock
511
+ - ./runner-work:/work
512
+ - ./runner-cache:/cache
513
+ networks:
514
+ - och-net
515
+
516
+networks:
517
+ och-net:
518
+ driver: bridge
519
+EOF
269
520
270
-# Restart application
271
-pm2 restart opencodehub
521
+# Create .env for compose
522
+cat > .env << 'EOF'
523
+POSTGRES_PASSWORD=your-postgres-password
524
+REDIS_PASSWORD=your-redis-password
525
+RUNNER_TOKEN=your-runner-token
526
+EOF
527
+
528
+# Deploy
529
+docker-compose up -d --build
530
+
531
+# Update
532
+cd /var/lib/opencodehub
533
+docker-compose pull
534
+docker-compose up -d --build
272
535
```
273
536
274
-### Database Connection Issues
537
+### Backup
275
538
276
539
```bash
277
-# Test PostgreSQL connection
278
-psql -U opencodehub -h localhost -d opencodehub
540
+# Database
541
+docker exec opencodehub-postgres pg_dump -U opencodehub opencodehub > backup-$(date +%Y%m%d).sql
542
+
543
+# Files
544
+tar czf och-backup-$(date +%Y%m%d).tar.gz /var/lib/opencodehub/repos /var/lib/opencodehub/storage
545
+```
546
+
547
+Set up a cron job in CyberPanel → **Cron Jobs**:
548
+```
549
+0 2 * * * cd /var/lib/opencodehub && docker exec opencodehub-postgres pg_dump -U opencodehub opencodehub > backups/backup-$(date +\%Y\%m\%d).sql
279
550
```
280
551
281
552
---
282
553
283
-## Updating OpenCodeHub
554
+## Troubleshooting
284
555
285
-```bash
286
-cd /home/git.yourdomain.com/app
556
+| Problem | Solution |
557
+|---------|----------|
558
+| **502 Bad Gateway** | Check if OpenCodeHub container is running: `docker ps`. Check logs: `docker logs opencodehub`. |
559
+| **SSL not working** | Re-issue SSL in CyberPanel → SSL → Manage SSL. Ensure DNS points to server. |
560
+| **Database connection error** | Verify PostgreSQL container is running. Check `.env` DATABASE_URL uses correct password. |
561
+| **Git SSH not working** | Ensure port 2222 is open in firewall. Verify SSH host key is generated in `/data/ssh`. |
562
+| **Build fails** | Check Docker has enough disk space: `docker system df`. Free space with `docker system prune`. |
563
+| **Node.js app won't start (Method B)** | Check LiteSpeed error logs in CyberPanel → Logs. Verify `dist/server/entry.mjs` exists after build. |
564
+| **Permission denied on files** | Fix ownership: `chown -R 1000:1000 /var/lib/opencodehub/*` (Docker runs as user 1000/bun). |
287
565
288
-# Pull latest changes
289
-git pull origin main
566
+---
290
567
291
-# Install dependencies
292
-npm install
568
+## Performance Tuning
293
569
294
-# Rebuild
295
-npm run build
570
+CyberPanel + OpenLiteSpeed is already optimized, but you can tune further:
296
571
297
-# Run migrations
298
-npm run db:push
572
+### Enable LSCache
299
573
300
-# Restart
301
-pm2 restart opencodehub
302
-```
574
+1. Go to **Websites** → **List Websites** → **Manage**
575
+2. **LiteSpeed Cache** → **Enable**
576
+3. This caches static assets and improves load times
303
577
578
+### Database Optimization
304
579
305
-## Comparison: OpenLiteSpeed vs Nginx
580
+```bash
581
+# In PostgreSQL container
582
+docker exec -it opencodehub-postgres psql -U opencodehub -d opencodehub
306
583
307
-| Feature | OpenLiteSpeed | Nginx |
308
-|---------|---------------|-------|
309
-| Performance | Excellent | Excellent |
310
-| .htaccess support | ✅ | ❌ |
311
-| WebSocket | ✅ | ✅ |
312
-| Configuration | GUI + files | Files only |
313
-| Resource usage | Low | Very low |
584
+# Run VACUUM
585
+VACUUM ANALYZE;
586
+```
314
587
315
-Both work well for OpenCodeHub.
588
+Set up a weekly cron:
589
+```
590
+0 3 * * 0 docker exec opencodehub-postgres psql -U opencodehub -d opencodehub -c "VACUUM ANALYZE;"
591
+```
316
592
317
593
---
318
594
319
595
## Next Steps
320
596
321
-- [Set up monitoring](/administration/monitoring/)
322
-- [Configure backups](/administration/deploy-docker/#backup--restore)
323
-- [Enable AI code review](/features/ai-review/)
597
+- [Configure Email (SMTP)](/administration/configuration/#email)
598
+- [Set up Storage Adapter (S3/R2)](/guides/storage-adapters/)
599
+- [Enable Branch Protection](/guides/branch-protection/)
600
+- [Set up your First Stack](/tutorials/your-first-stack/)
324
601
▼src/content/docs/administration/deploy-nas.md
+728-0
1
+---
2
+title: "Deploy on NAS (Synology, TrueNAS, QNAP)"
3
+description: "Deploy OpenCodeHub on your Network Attached Storage device using Docker"
4
+---
5
+
6
+> **Difficulty:** Intermediate | **Time:** 30-45 minutes | **Method:** Docker/Container Station
7
+
8
+Deploy OpenCodeHub on your **Network Attached Storage (NAS)** device. This is perfect for small teams, personal use, or as a private Git server at home. Works on Synology DSM, TrueNAS SCALE, QNAP QTS, and any NAS supporting Docker.
9
+
10
+---
11
+
12
+## Prerequisites
13
+
14
+| NAS Type | Minimum Requirements |
15
+|----------|---------------------|
16
+| **Synology** | DSM 7.0+, 4GB RAM (8GB recommended), x86_64 or ARM64 |
17
+| **TrueNAS SCALE** | 8GB RAM, 2 CPU cores, 40GB free space |
18
+| **QNAP** | QTS 5.0+, 4GB RAM, Container Station installed |
19
+| **Generic** | Docker/Podman support, 4GB RAM, 2 CPU cores |
20
+
21
+- A domain with DDNS configured (e.g., `git.yourddns.net`) OR local network access only
22
+- Port forwarding on your router (if accessing externally):
23
+ - `80` → NAS:80
24
+ - `443` → NAS:443
25
+ - `2222` → NAS:2222 (for SSH Git, optional)
26
+
27
+---
28
+
29
+## Part 1: Synology DSM Deployment
30
+
31
+### Step 1.1: Install Container Manager
32
+
33
+1. Open **Package Center**
34
+2. Search for **Container Manager** (DSM 7.2+) or **Docker** (older DSM)
35
+3. Click **Install**
36
+
37
+### Step 1.2: Create Shared Folders
38
+
39
+1. Open **Control Panel** → **Shared Folder** → **Create**
40
+2. Create these folders:
41
+ - `opencodehub/repos` — Git repositories
42
+ - `opencodehub/storage` — File uploads
43
+ - `opencodehub/ssh` — SSH host keys
44
+ - `opencodehub/cache` — Application cache
45
+ - `opencodehub/postgres` — PostgreSQL data
46
+ - `opencodehub/redis` — Redis data
47
+
48
+3. Set permissions:
49
+ - Right-click each folder → **Edit** → **Permissions**
50
+ - Grant **Read/Write** to your admin user and the `Docker` system group
51
+
52
+### Step 1.3: Set Up PostgreSQL
53
+
54
+#### Using Container Manager GUI:
55
+
56
+1. Open **Container Manager** → **Image** → **Add** → **Add from URL**
57
+2. Image name: `postgres`
58
+3. Tag: `16-alpine`
59
+4. Click **Add**
60
+
61
+5. Go to **Container** → **Create**
62
+6. Select `postgres:16-alpine`
63
+7. Configuration:
64
+ - **Container name:** `opencodehub-postgres`
65
+ - **Enable auto-restart:** Yes
66
+ - **Network:** Use the same bridge network as other containers
67
+ - **Environment variables:**
68
+ ```
69
+ POSTGRES_USER=opencodehub
70
+ POSTGRES_PASSWORD=<generate-strong-password>
71
+ POSTGRES_DB=opencodehub
72
+ ```
73
+ - **Volume settings:**
74
+ ```
75
+ /volume1/opencodehub/postgres → /var/lib/postgresql/data
76
+ ```
77
+ - **Port settings:**
78
+ ```
79
+ Local port: 5432 → Container port: 5432
80
+ ```
81
+8. Click **Done**
82
+
83
+#### Using SSH (Alternative):
84
+
85
+```bash
86
+ssh admin@your-synology-ip
87
+sudo -i
88
+
89
+docker run -d \
90
+ --name opencodehub-postgres \
91
+ --restart unless-stopped \
92
+ -e POSTGRES_USER=opencodehub \
93
+ -e POSTGRES_PASSWORD=YOUR_PASSWORD \
94
+ -e POSTGRES_DB=opencodehub \
95
+ -v /volume1/opencodehub/postgres:/var/lib/postgresql/data \
96
+ -p 5432:5432 \
97
+ postgres:16-alpine
98
+```
99
+
100
+### Step 1.4: Set Up Redis
101
+
102
+Using Container Manager:
103
+1. Pull `redis:7-alpine`
104
+2. Create container:
105
+ - **Name:** `opencodehub-redis`
106
+ - **Environment:**
107
+ ```
108
+ REDIS_PASSWORD=<strong-password>
109
+ ```
110
+ - **Command:** `redis-server --appendonly yes --requirepass YOUR_PASSWORD`
111
+ - **Volume:**
112
+ ```
113
+ /volume1/opencodehub/redis → /data
114
+ ```
115
+ - **Port:** `6379` → `6379`
116
+
117
+Or via SSH:
118
+```bash
119
+docker run -d \
120
+ --name opencodehub-redis \
121
+ --restart unless-stopped \
122
+ -v /volume1/opencodehub/redis:/data \
123
+ -p 6379:6379 \
124
+ redis:7-alpine \
125
+ redis-server --appendonly yes --requirepass YOUR_PASSWORD
126
+```
127
+
128
+### Step 1.5: Deploy OpenCodeHub
129
+
130
+#### Option A: Pre-built Image (Fastest)
131
+
132
+If using the published Docker image:
133
+
134
+```bash
135
+docker run -d \
136
+ --name opencodehub \
137
+ --restart unless-stopped \
138
+ --link opencodehub-postgres:postgres \
139
+ --link opencodehub-redis:redis \
140
+ -p 4321:4321 \
141
+ -p 2222:2222 \
142
+ -e NODE_ENV=production \
143
+ -e DATABASE_URL=postgresql://opencodehub:[email protected]:5432/opencodehub \
144
+ -e REDIS_URL=redis://:[email protected]:6379 \
145
+ -e JWT_SECRET=$(openssl rand -hex 32) \
146
+ -e SESSION_SECRET=$(openssl rand -hex 32) \
147
+ -e INTERNAL_HOOK_SECRET=$(openssl rand -hex 32) \
148
+ -e CRON_SECRET=$(openssl rand -hex 32) \
149
+ -e RUNNER_SECRET=$(openssl rand -hex 32) \
150
+ -e WORKFLOW_SECRET_ENCRYPTION_KEY=$(openssl rand -hex 32) \
151
+ -e SITE_URL=https://git.yourddns.net \
152
+ -e STORAGE_TYPE=local \
153
+ -e STORAGE_PATH=/data/storage \
154
+ -e REPOS_PATH=/data/repos \
155
+ -e SSH_HOST_KEY_PATH=/data/ssh/host_key \
156
+ -v /volume1/opencodehub/repos:/data/repos \
157
+ -v /volume1/opencodehub/storage:/data/storage \
158
+ -v /volume1/opencodehub/ssh:/data/ssh \
159
+ -v /volume1/opencodehub/cache:/data/cache \
160
+ swadhinbiswas/opencodehub:latest
161
+```
162
+
163
+> **Note:** On Synology, `host.docker.internal` may not work. Use your NAS IP address instead (e.g., `192.168.1.100`).
164
+
165
+#### Option B: Build from Source
166
+
167
+1. In Container Manager → **Project** (Docker Compose):
168
+
169
+```yaml
170
+version: '3.8'
171
+
172
+services:
173
+ app:
174
+ build:
175
+ context: /volume1/docker/OpenCodeHub
176
+ dockerfile: Dockerfile
177
+ container_name: opencodehub
178
+ restart: unless-stopped
179
+ ports:
180
+ - "4321:4321"
181
+ - "2222:2222"
182
+ environment:
183
+ - NODE_ENV=production
184
+ - DATABASE_URL=postgresql://opencodehub:YOUR_PASS@postgres:5432/opencodehub
185
+ - REDIS_URL=redis://:YOUR_PASS@redis:6379
186
+ - JWT_SECRET=YOUR_SECRET
187
+ - SESSION_SECRET=YOUR_SECRET
188
+ - INTERNAL_HOOK_SECRET=YOUR_SECRET
189
+ - CRON_SECRET=YOUR_SECRET
190
+ - RUNNER_SECRET=YOUR_SECRET
191
+ - WORKFLOW_SECRET_ENCRYPTION_KEY=YOUR_SECRET
192
+ - SITE_URL=https://git.yourddns.net
193
+ - STORAGE_TYPE=local
194
+ - STORAGE_PATH=/data/storage
195
+ - REPOS_PATH=/data/repos
196
+ - SSH_HOST_KEY_PATH=/data/ssh/host_key
197
+ volumes:
198
+ - /volume1/opencodehub/repos:/data/repos
199
+ - /volume1/opencodehub/storage:/data/storage
200
+ - /volume1/opencodehub/ssh:/data/ssh
201
+ - /volume1/opencodehub/cache:/data/cache
202
+ depends_on:
203
+ - postgres
204
+ - redis
205
+ networks:
206
+ - och-net
207
+
208
+ postgres:
209
+ image: postgres:16-alpine
210
+ container_name: opencodehub-postgres
211
+ restart: unless-stopped
212
+ environment:
213
+ - POSTGRES_USER=opencodehub
214
+ - POSTGRES_PASSWORD=YOUR_PASS
215
+ - POSTGRES_DB=opencodehub
216
+ volumes:
217
+ - /volume1/opencodehub/postgres:/var/lib/postgresql/data
218
+ networks:
219
+ - och-net
220
+
221
+ redis:
222
+ image: redis:7-alpine
223
+ container_name: opencodehub-redis
224
+ restart: unless-stopped
225
+ command: redis-server --appendonly yes --requirepass YOUR_PASS
226
+ volumes:
227
+ - /volume1/opencodehub/redis:/data
228
+ networks:
229
+ - och-net
230
+
231
+networks:
232
+ och-net:
233
+ driver: bridge
234
+```
235
+
236
+2. Save this as `docker-compose.yml` in `/volume1/docker/OpenCodeHub/`
237
+3. Clone the repo to that folder first:
238
+ ```bash
239
+ cd /volume1/docker
240
+ git clone https://github.com/swadhinbiswas/OpencodeHub.git
241
+ ```
242
+4. In Container Manager → **Project** → **Create**
243
+5. Select the path `/volume1/docker/OpenCodeHub`
244
+6. Click **Create**
245
+
246
+### Step 1.6: Configure Reverse Proxy (Synology)
247
+
248
+1. **Control Panel** → **Login Portal** → **Advanced** → **Reverse Proxy**
249
+2. Click **Create**
250
+3. **General:**
251
+ - Source:
252
+ - Protocol: HTTPS
253
+ - Hostname: `git.yourddns.net`
254
+ - Port: 443
255
+ - Destination:
256
+ - Protocol: HTTP
257
+ - Hostname: `localhost`
258
+ - Port: 4321
259
+4. **Custom Header** → **Create** → **WebSocket**
260
+ - Header name: `Upgrade`
261
+ - Value: `$http_upgrade`
262
+ - Header name: `Connection`
263
+ - Value: `upgrade`
264
+5. Click **Save**
265
+
266
+### Step 1.7: SSL Certificate (Let's Encrypt)
267
+
268
+1. **Control Panel** → **Security** → **Certificate**
269
+2. Click **Add** → **Add a new certificate**
270
+3. Select **Get a certificate from Let's Encrypt**
271
+4. Domain name: `git.yourddns.net`
272
273
+6. Click **Apply**
274
+
275
+7. After issuance, go to **Configure** and assign the certificate to:
276
+ - `git.yourddns.net:443` (your reverse proxy)
277
+
278
+---
279
+
280
+## Part 2: TrueNAS SCALE Deployment
281
+
282
+TrueNAS SCALE has native Kubernetes support with Helm charts, but Docker is easier via **Apps** (Docker Compose).
283
+
284
+### Step 2.1: Create Datasets
285
+
286
+1. Go to **Storage** → **Pools** → Your pool → **Add Dataset**
287
+2. Create a parent dataset: `opencodehub`
288
+3. Under it, create:
289
+ - `repos`
290
+ - `storage`
291
+ - `ssh`
292
+ - `cache`
293
+ - `postgres`
294
+ - `redis`
295
+
296
+### Step 2.2: Deploy via Custom App (Docker Compose)
297
+
298
+1. Go to **Apps** → **Discover Apps** → **Custom App**
299
+2. Enable **Advanced Mode**
300
+3. Enter this Docker Compose:
301
+
302
+```yaml
303
+version: '3.8'
304
+
305
+services:
306
+ app:
307
+ image: swadhinbiswas/opencodehub:latest
308
+ container_name: opencodehub
309
+ restart: unless-stopped
310
+ ports:
311
+ - "4321:4321"
312
+ - "2222:2222"
313
+ environment:
314
+ - NODE_ENV=production
315
+ - DATABASE_URL=postgresql://opencodehub:YOUR_PASS@postgres:5432/opencodehub
316
+ - REDIS_URL=redis://:YOUR_PASS@redis:6379
317
+ - JWT_SECRET=YOUR_SECRET
318
+ - SESSION_SECRET=YOUR_SECRET
319
+ - INTERNAL_HOOK_SECRET=YOUR_SECRET
320
+ - CRON_SECRET=YOUR_SECRET
321
+ - RUNNER_SECRET=YOUR_SECRET
322
+ - WORKFLOW_SECRET_ENCRYPTION_KEY=YOUR_SECRET
323
+ - SITE_URL=https://git.yourdomain.com
324
+ - STORAGE_TYPE=local
325
+ - STORAGE_PATH=/data/storage
326
+ - REPOS_PATH=/data/repos
327
+ - SSH_HOST_KEY_PATH=/data/ssh/host_key
328
+ volumes:
329
+ - /mnt/YOURPOOL/opencodehub/repos:/data/repos
330
+ - /mnt/YOURPOOL/opencodehub/storage:/data/storage
331
+ - /mnt/YOURPOOL/opencodehub/ssh:/data/ssh
332
+ - /mnt/YOURPOOL/opencodehub/cache:/data/cache
333
+ depends_on:
334
+ - postgres
335
+ - redis
336
+ networks:
337
+ - och-net
338
+
339
+ postgres:
340
+ image: postgres:16-alpine
341
+ container_name: opencodehub-postgres
342
+ restart: unless-stopped
343
+ environment:
344
+ - POSTGRES_USER=opencodehub
345
+ - POSTGRES_PASSWORD=YOUR_PASS
346
+ - POSTGRES_DB=opencodehub
347
+ volumes:
348
+ - /mnt/YOURPOOL/opencodehub/postgres:/var/lib/postgresql/data
349
+ networks:
350
+ - och-net
351
+
352
+ redis:
353
+ image: redis:7-alpine
354
+ container_name: opencodehub-redis
355
+ restart: unless-stopped
356
+ command: redis-server --appendonly yes --requirepass YOUR_PASS
357
+ volumes:
358
+ - /mnt/YOURPOOL/opencodehub/redis:/data
359
+ networks:
360
+ - och-net
361
+
362
+networks:
363
+ och-net:
364
+ driver: bridge
365
+```
366
+
367
+> Replace `YOURPOOL` with your actual pool name and `YOUR_PASS`/`YOUR_SECRET` with your values.
368
+
369
+4. Click **Save**
370
+5. TrueNAS will deploy all containers
371
+
372
+### Step 2.3: Configure TrueNAS Certificate
373
+
374
+1. **System** → **General** → **GUI SSL Certificate**
375
+2. Or use **Apps** → **Certificates** for app-specific SSL
376
+3. For external access, use TrueNAS's built-in ACME (Let's Encrypt) or upload your own certificate
377
+
378
+### Step 2.4: Reverse Proxy with Nginx Proxy Manager (Recommended)
379
+
380
+Install Nginx Proxy Manager from the TrueNAS Apps catalog:
381
+
382
+1. **Apps** → **Discover Apps** → Search "Nginx Proxy Manager"
383
+2. Install with default settings
384
+3. Access Nginx Proxy Manager at `your-nas-ip:81`
385
+4. Add Proxy Host:
386
+ - Domain Names: `git.yourdomain.com`
387
+ - Forward Hostname/IP: `opencodehub`
388
+ - Forward Port: `4321`
389
+ - Enable **Block Common Exploits**
390
+ - SSL: Request a new SSL certificate from Let's Encrypt
391
+ - Enable **Force SSL** and **HTTP/2 Support**
392
+
393
+---
394
+
395
+## Part 3: QNAP QTS Deployment
396
+
397
+### Step 3.1: Install Container Station
398
+
399
+1. Open **App Center**
400
+2. Search for **Container Station**
401
+3. Click **Install**
402
+
403
+### Step 3.2: Create Folders
404
+
405
+1. Open **File Station**
406
+2. Create folder: `opencodehub`
407
+3. Inside it create: `repos`, `storage`, `ssh`, `cache`, `postgres`, `redis`
408
+
409
+### Step 3.3: Deploy via Container Station
410
+
411
+#### Create Network:
412
+
413
+1. Container Station → **Networks** → **Create**
414
+2. Name: `opencodehub-network`
415
+3. Driver: Bridge
416
+
417
+#### Create PostgreSQL:
418
+
419
+1. **Create** → **Search Docker Hub** → `postgres:16-alpine`
420
+2. Click **Install**
421
+3. Configuration:
422
+ - Name: `opencodehub-postgres`
423
+ - Network: `opencodehub-network`
424
+ - Environment:
425
+ ```
426
+ POSTGRES_USER=opencodehub
427
+ POSTGRES_PASSWORD=<password>
428
+ POSTGRES_DB=opencodehub
429
+ ```
430
+ - Shared Folders:
431
+ ```
432
+ /share/Container/opencodehub/postgres → /var/lib/postgresql/data
433
+ ```
434
+ - Port: `5432`
435
+
436
+#### Create Redis:
437
+
438
+1. Search and install `redis:7-alpine`
439
+2. Name: `opencodehub-redis`
440
+3. Network: `opencodehub-network`
441
+4. Command: `redis-server --appendonly yes --requirepass YOUR_PASS`
442
+5. Shared Folders:
443
+ ```
444
+ /share/Container/opencodehub/redis → /data
445
+ ```
446
+
447
+#### Create OpenCodeHub:
448
+
449
+1. Search and install `swadhinbiswas/opencodehub:latest`
450
+2. Name: `opencodehub`
451
+3. Network: `opencodehub-network`
452
+4. Environment variables (same as Synology example)
453
+5. Shared Folders:
454
+ ```
455
+ /share/Container/opencodehub/repos → /data/repos
456
+ /share/Container/opencodehub/storage → /data/storage
457
+ /share/Container/opencodehub/ssh → /data/ssh
458
+ /share/Container/opencodehub/cache → /data/cache
459
+ ```
460
+6. Ports: `4321`, `2222`
461
+
462
+### Step 3.4: QNAP Reverse Proxy
463
+
464
+1. **Control Panel** → **System** → **Reverse Proxy**
465
+2. Click **Create**
466
+3. Rule:
467
+ - Name: `OpenCodeHub`
468
+ - Source Protocol: HTTPS
469
+ - Source URL: `git.yourdomain.com`
470
+ - Port: 443
471
+ - Destination Protocol: HTTP
472
+ - Destination URL: `localhost`
473
+ - Port: 4321
474
+4. Enable **HSTS**
475
+
476
+### Step 3.5: SSL Certificate
477
+
478
+1. **Control Panel** → **Security** → **Certificate & Private Key**
479
+2. Click **Replace Certificate**
480
+3. Choose **Get from Let's Encrypt**
481
+4. Enter your domain and email
482
+5. Click **Apply**
483
+
484
+---
485
+
486
+## Part 4: Generic NAS / Any Docker Host
487
+
488
+If your NAS supports Docker (via Portainer, Podman, or CLI) and you have SSH access, the absolute easiest way to deploy is using the 1-click install script:
489
+
490
+```bash
491
+# Connect to your NAS via SSH, then run:
492
+curl -sSL https://raw.githubusercontent.com/swadhinbiswas/OpencodeHub/main/install.sh | bash
493
+```
494
+
495
+### Using Docker Compose (Manual Setup)
496
+
497
+If you prefer to deploy manually via Portainer or `docker-compose.yml`:
498
+
499
+```bash
500
+# Create unified data directory
501
+mkdir -p ~/opencodehub-data
502
+
503
+# Create docker-compose.yml
504
+cat > ~/opencodehub/docker-compose.yml << 'EOF'
505
+version: '3.8'
506
+
507
+services:
508
+ app:
509
+ image: swadhinbiswas/opencodehub:latest
510
+ container_name: opencodehub
511
+ restart: unless-stopped
512
+ ports:
513
+ - "4321:4321"
514
+ - "2222:2222"
515
+ environment:
516
+ - NODE_ENV=production
517
+ - DATABASE_URL=postgresql://opencodehub:YOUR_PASS@postgres:5432/opencodehub
518
+ - REDIS_URL=redis://:YOUR_PASS@redis:6379
519
+ - JWT_SECRET=YOUR_SECRET
520
+ - SESSION_SECRET=YOUR_SECRET
521
+ - INTERNAL_HOOK_SECRET=YOUR_SECRET
522
+ - CRON_SECRET=YOUR_SECRET
523
+ - RUNNER_SECRET=YOUR_SECRET
524
+ - WORKFLOW_SECRET_ENCRYPTION_KEY=YOUR_SECRET
525
+ - SITE_URL=https://git.yourdomain.com
526
+ - DATA_DIR=/data
527
+ volumes:
528
+ - ~/opencodehub-data:/data
529
+ depends_on:
530
+ - postgres
531
+ - redis
532
+ networks:
533
+ - och-net
534
+
535
+ postgres:
536
+ image: postgres:16-alpine
537
+ container_name: opencodehub-postgres
538
+ restart: unless-stopped
539
+ environment:
540
+ - POSTGRES_USER=opencodehub
541
+ - POSTGRES_PASSWORD=YOUR_PASS
542
+ - POSTGRES_DB=opencodehub
543
+ volumes:
544
+ - ~/opencodehub-data/postgres:/var/lib/postgresql/data
545
+ networks:
546
+ - och-net
547
+
548
+ redis:
549
+ image: redis:7-alpine
550
+ container_name: opencodehub-redis
551
+ restart: unless-stopped
552
+ command: redis-server --appendonly yes --requirepass YOUR_PASS
553
+ volumes:
554
+ - ~/opencodehub-data/redis:/data
555
+ networks:
556
+ - och-net
557
+
558
+networks:
559
+ och-net:
560
+ driver: bridge
561
+EOF
562
+
563
+# Deploy
564
+cd ~/opencodehub
565
+docker-compose up -d
566
+```
567
+
568
+---
569
+
570
+## Step 5: Router Port Forwarding
571
+
572
+For external access, forward these ports on your router:
573
+
574
+| External Port | Internal IP | Internal Port | Purpose |
575
+|--------------|-------------|---------------|---------|
576
+| 80 | Your NAS IP | 80 | HTTP (for Let's Encrypt/redirect) |
577
+| 443 | Your NAS IP | 443 | HTTPS (OpenCodeHub web) |
578
+| 2222 | Your NAS IP | 2222 | SSH Git (optional) |
579
+
580
+> **Security Note:** If using a reverse proxy, you only need to forward 80 and 443. Port 4321 should NOT be exposed externally.
581
+
582
+---
583
+
584
+## Step 6: Dynamic DNS (DDNS)
585
+
586
+If you don't have a static IP:
587
+
588
+### Synology:
589
+1. **Control Panel** → **External Access** → **DDNS**
590
+2. Click **Add**
591
+3. Service Provider: Synology, No-IP, DuckDNS, etc.
592
+4. Enter hostname: `git.yourddns.net`
593
+5. Click **Test Connection** → **OK**
594
+
595
+### TrueNAS:
596
+1. **Network** → **Global Configuration** → **Nameservers**
597
+2. Use Cloudflare or your DNS provider's API for dynamic updates
598
+3. Or install a DDNS client as a custom app
599
+
600
+### QNAP:
601
+1. **Control Panel** → **Network & File Services** → **DDNS**
602
+2. Click **Add**
603
+3. Select provider and configure
604
+
605
+### Router DDNS:
606
+Most routers (UniFi, ASUS, TP-Link) have built-in DDNS. Configure it to update `git.yourddns.net` automatically.
607
+
608
+---
609
+
610
+## Step 7: Create Admin User
611
+
612
+```bash
613
+# Synology/QNAP/Generic
614
+ssh admin@your-nas-ip
615
+docker exec -it opencodehub bun run scripts/seed-admin.ts
616
+
617
+# TrueNAS
618
+kubectl exec -it deployment/opencodehub -- bun run scripts/seed-admin.ts
619
+```
620
+
621
+Enter username, email, and password.
622
+
623
+---
624
+
625
+## Step 8: Initial Setup & Verification
626
+
627
+1. Visit `https://git.yourddns.net` (or your domain)
628
+2. Log in with admin credentials
629
+3. Create your first organization
630
+4. Test Git over HTTPS:
631
+ ```bash
632
+ git clone https://git.yourddns.net/admin/test-repo.git
633
+ ```
634
+
635
+---
636
+
637
+## Maintenance
638
+
639
+### Update OpenCodeHub
640
+
641
+```bash
642
+cd ~/opencodehub # or /volume1/docker/OpenCodeHub, etc.
643
+docker-compose pull
644
+docker-compose up -d
645
+```
646
+
647
+### Backup Strategy
648
+
649
+#### Automated Backup (Synology):
650
+
651
+1. **Hyper Backup** → **Create** → **Local/Remote**
652
+2. Select `opencodehub` shared folder
653
+3. Schedule: Daily at 2 AM
654
+4. Retention: Keep last 7 versions
655
+
656
+#### Manual Backup:
657
+
658
+```bash
659
+# Backup script
660
+#!/bin/bash
661
+DATE=$(date +%Y%m%d_%H%M%S)
662
+BACKUP_DIR="/path/to/backups"
663
+
664
+# Database
665
+docker exec opencodehub-postgres pg_dump -U opencodehub opencodehub | gzip > $BACKUP_DIR/och-db-$DATE.sql.gz
666
+
667
+# Files
668
+tar czf $BACKUP_DIR/och-files-$DATE.tar.gz /path/to/opencodehub/repos /path/to/opencodehub/storage
669
+
670
+# Keep only last 7 days
671
+find $BACKUP_DIR -name "och-*" -mtime +7 -delete
672
+```
673
+
674
+### Monitor Resources
675
+
676
+| NAS | Monitoring Tool |
677
+|-----|----------------|
678
+| Synology | **Resource Monitor** widget |
679
+| TrueNAS | **Reporting** → CPU/Memory/Disk |
680
+| QNAP | **Resource Monitor** in Dashboard |
681
+
682
+OpenCodeHub on NAS typically uses:
683
+- **RAM:** 1-2GB idle, 2-4GB under load
684
+- **CPU:** 10-30% during normal use
685
+- **Disk:** Grows with repos and uploads
686
+
687
+---
688
+
689
+## Troubleshooting
690
+
691
+| Problem | Solution |
692
+|---------|----------|
693
+| **Container won't start** | Check logs: `docker logs opencodehub`. Often a database connection issue. |
694
+| **"host.docker.internal" not found** | Use your NAS's LAN IP (e.g., `192.168.1.100`) instead of `host.docker.internal`. |
695
+| **Permission denied on volumes** | Ensure the Docker user has read/write access to the shared folders. On Synology, set permissions for the `Docker` group. |
696
+| **Slow performance** | NAS devices often have slow CPUs. Ensure you have at least 4GB RAM. Consider using SSD for the `postgres` volume. |
697
+| **SSL certificate errors** | Ensure your domain resolves correctly. Check DDNS is updating your IP. |
698
+| **Git SSH not connecting** | Port 2222 must be forwarded on router. Some ISPs block port 22/2222. Try a different high port (e.g., 8022). |
699
+| **Database corruption after power loss** | PostgreSQL with default settings can corrupt on unclean shutdown. Use a UPS. For extra safety, add `fsync=on` to PostgreSQL config. |
700
+| **Out of memory** | Synology/QNAP with 2GB RAM will struggle. Close unused packages. Add a swap file if needed. |
701
+
702
+---
703
+
704
+## NAS-Specific Tips
705
+
706
+### Synology
707
+- Enable **Snapshot Replication** for instant recovery
708
+- Use **SSO Client** if you want to integrate with existing domain auth
709
+- Consider **Virtual Machine Manager** if you need more isolation
710
+
711
+### TrueNAS SCALE
712
+- Use **Apps** instead of VMs for better resource efficiency
713
+- Enable **Automatic container updates** in TrueNAS settings
714
+- Consider **TrueCharts** catalog for additional apps
715
+
716
+### QNAP
717
+- Use **QuTS hero** (ZFS) for better data integrity
718
+- Enable **snapshots** for the opencodehub dataset
719
+- **QVPN** can secure remote access without exposing ports
720
+
721
+---
722
+
723
+## Next Steps
724
+
725
+- [Configure Email (SMTP)](/administration/configuration/#email)
726
+- [Set up Offsite Storage (S3/R2)](/guides/storage-adapters/) — highly recommended for NAS
727
+- [Enable Branch Protection](/guides/branch-protection/)
728
+- [Set up your First Stack](/tutorials/your-first-stack/)
0
729