create-thally-docs 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -9,17 +9,31 @@ import { Readable, pipeline } from "stream";
|
|
|
9
9
|
import { promisify } from "util";
|
|
10
10
|
import tar from "tar";
|
|
11
11
|
var pipelineAsync = promisify(pipeline);
|
|
12
|
-
var
|
|
12
|
+
var TEMPLATE_REPOSITORY = "thallylabs/docs";
|
|
13
|
+
var TARBALL_URL = `https://codeload.github.com/${TEMPLATE_REPOSITORY}/tar.gz/main`;
|
|
13
14
|
var EXCLUDE_PATHS = [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"/node_modules
|
|
15
|
+
// Match both the directory entry itself and every nested file. Tar invokes
|
|
16
|
+
// the filter for `.../node_modules` before descendants, without a trailing `/`.
|
|
17
|
+
"/node_modules",
|
|
18
|
+
// The canonical docs repository may temporarily retain package sources while
|
|
19
|
+
// runtime work is being upstreamed. A scaffold consumes the published
|
|
20
|
+
// packages declared in package.json; it must never inherit those sources.
|
|
21
|
+
"/packages",
|
|
17
22
|
"/.git/",
|
|
23
|
+
"/.next/",
|
|
24
|
+
"/.data/",
|
|
25
|
+
"/.thally/",
|
|
18
26
|
"/thally-agent.yml",
|
|
19
27
|
"/thally-track.yml",
|
|
20
28
|
"/CODEOWNERS",
|
|
21
29
|
"/CLAUDE.md",
|
|
22
|
-
"/notes/"
|
|
30
|
+
"/notes/",
|
|
31
|
+
"/public/images/",
|
|
32
|
+
"/src/public/",
|
|
33
|
+
"/snippets/",
|
|
34
|
+
"/.github/ISSUE_TEMPLATE/",
|
|
35
|
+
"/.github/PULL_REQUEST_TEMPLATE.md",
|
|
36
|
+
"/README.md"
|
|
23
37
|
];
|
|
24
38
|
function shouldInclude(path) {
|
|
25
39
|
for (const excluded of EXCLUDE_PATHS) {
|
|
@@ -75,11 +89,11 @@ function writeTrackingConfig(projectDir, repos) {
|
|
|
75
89
|
// src/customize.ts
|
|
76
90
|
import { existsSync, mkdirSync, writeFileSync as writeFileSync2, readFileSync as readFileSync2, readdirSync, cpSync, rmSync } from "fs";
|
|
77
91
|
import { join as join2 } from "path";
|
|
78
|
-
import { execSync } from "child_process";
|
|
79
92
|
var STARTER_PAGES = {
|
|
80
93
|
"introduction.mdx": `---
|
|
81
94
|
title: Introduction
|
|
82
|
-
description: Welcome to {NAME}
|
|
95
|
+
description: Welcome to {NAME}.
|
|
96
|
+
mode: home
|
|
83
97
|
keywords:
|
|
84
98
|
- {NAME}
|
|
85
99
|
- documentation
|
|
@@ -87,29 +101,44 @@ keywords:
|
|
|
87
101
|
- getting started
|
|
88
102
|
---
|
|
89
103
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
## What you'll find here
|
|
104
|
+
<Hero
|
|
105
|
+
title="Welcome to {NAME}"
|
|
106
|
+
subtitle="Use this starter to introduce your product, guide readers to their first successful outcome, and publish a clear API reference."
|
|
107
|
+
primaryLabel="Start the quickstart"
|
|
108
|
+
primaryHref="/quickstart"
|
|
109
|
+
secondaryLabel="See components"
|
|
110
|
+
secondaryHref="/components"
|
|
111
|
+
/>
|
|
99
112
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
113
|
+
<CardGroup cols={3}>
|
|
114
|
+
<Card title="Quickstart" icon="party-horn" href="/quickstart">
|
|
115
|
+
Show readers the fastest path to a useful first result.
|
|
116
|
+
</Card>
|
|
117
|
+
<Card title="Components" icon="grid-round" href="/components">
|
|
118
|
+
Structure guides with steps, tabs, cards, callouts, accordions, and more.
|
|
119
|
+
</Card>
|
|
120
|
+
<Card title="API reference" icon="code-simple" href="/api">
|
|
121
|
+
Replace \`openapi.yaml\` with your specification to publish interactive endpoints.
|
|
122
|
+
</Card>
|
|
123
|
+
<Card title="Customize" icon="wrench" href="/customization">
|
|
124
|
+
Make the navigation, brand, typography, and links your own.
|
|
125
|
+
</Card>
|
|
126
|
+
<Card title="Multi-language" icon="message" href="/es">
|
|
127
|
+
Switch to the included Spanish example from the language menu.
|
|
128
|
+
</Card>
|
|
129
|
+
<Card title="Agent-ready docs" icon="link-simple" href="/llms.txt">
|
|
130
|
+
Give coding agents a clean, structured version of your documentation.
|
|
131
|
+
</Card>
|
|
132
|
+
</CardGroup>
|
|
103
133
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
\`docs.json\`. Every change you save is instantly reflected for both readers and agents.
|
|
134
|
+
<Note type="info" title="Make it yours">
|
|
135
|
+
Start by editing \`src/content/introduction.mdx\`. Then update \`docs.json\` to
|
|
136
|
+
organize navigation and \`src/data/site.ts\` to set your product name and links.
|
|
137
|
+
</Note>
|
|
109
138
|
`,
|
|
110
139
|
"quickstart.mdx": `---
|
|
111
140
|
title: Quickstart
|
|
112
|
-
description:
|
|
141
|
+
description: Give readers the fastest path to a successful first result with {NAME}.
|
|
113
142
|
keywords:
|
|
114
143
|
- {NAME}
|
|
115
144
|
- quickstart
|
|
@@ -117,32 +146,121 @@ keywords:
|
|
|
117
146
|
- getting started
|
|
118
147
|
---
|
|
119
148
|
|
|
120
|
-
|
|
149
|
+
Describe the prerequisites and the shortest useful workflow. A good quickstart
|
|
150
|
+
takes someone from zero to a visible result without explaining every option.
|
|
121
151
|
|
|
122
|
-
|
|
123
|
-
version in your project so builds stay reproducible across machines and CI:
|
|
152
|
+
## Prerequisites
|
|
124
153
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
\`\`\`
|
|
154
|
+
- Requirement one, such as an account, API key, or supported runtime
|
|
155
|
+
- Requirement two, such as a compatible device, browser, or operating system
|
|
128
156
|
|
|
129
|
-
|
|
157
|
+
<Steps>
|
|
158
|
+
<Step title="Install">
|
|
159
|
+
Explain how to install {NAME} or create an account.
|
|
130
160
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
161
|
+
\`\`\`bash
|
|
162
|
+
npm install your-package
|
|
163
|
+
\`\`\`
|
|
164
|
+
</Step>
|
|
165
|
+
<Step title="Configure">
|
|
166
|
+
Show only the configuration required for the first successful run.
|
|
134
167
|
|
|
135
|
-
\`\`\`
|
|
136
|
-
|
|
168
|
+
\`\`\`bash
|
|
169
|
+
your-cli init
|
|
170
|
+
\`\`\`
|
|
171
|
+
</Step>
|
|
172
|
+
<Step title="Run it">
|
|
173
|
+
Give readers a command or action with an observable result.
|
|
137
174
|
|
|
138
|
-
|
|
139
|
-
|
|
175
|
+
\`\`\`bash
|
|
176
|
+
your-cli start
|
|
177
|
+
\`\`\`
|
|
178
|
+
</Step>
|
|
179
|
+
</Steps>
|
|
180
|
+
|
|
181
|
+
<Tip>
|
|
182
|
+
Tell readers where to get help, then link to the next guide they should read.
|
|
183
|
+
</Tip>
|
|
184
|
+
`,
|
|
185
|
+
"components.mdx": `---
|
|
186
|
+
title: Components
|
|
187
|
+
description: A compact tour of the rich MDX components available in {NAME}.
|
|
188
|
+
keywords:
|
|
189
|
+
- {NAME}
|
|
190
|
+
- components
|
|
191
|
+
- MDX
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
Use components to keep complex instructions clear without turning every page
|
|
195
|
+
into a wall of text.
|
|
196
|
+
|
|
197
|
+
## Show equivalent paths
|
|
198
|
+
|
|
199
|
+
<Tabs>
|
|
200
|
+
<Tab title="npm">
|
|
201
|
+
\`\`\`bash
|
|
202
|
+
npm install your-package
|
|
203
|
+
\`\`\`
|
|
204
|
+
</Tab>
|
|
205
|
+
<Tab title="pnpm">
|
|
206
|
+
\`\`\`bash
|
|
207
|
+
pnpm add your-package
|
|
208
|
+
\`\`\`
|
|
209
|
+
</Tab>
|
|
210
|
+
<Tab title="yarn">
|
|
211
|
+
\`\`\`bash
|
|
212
|
+
yarn add your-package
|
|
213
|
+
\`\`\`
|
|
214
|
+
</Tab>
|
|
215
|
+
</Tabs>
|
|
216
|
+
|
|
217
|
+
## Reveal detail when it matters
|
|
218
|
+
|
|
219
|
+
<Accordion title="Where should advanced configuration live?">
|
|
220
|
+
Keep the default path visible and move optional detail into an accordion. This
|
|
221
|
+
lets new readers move quickly without hiding information from experts.
|
|
222
|
+
</Accordion>
|
|
223
|
+
|
|
224
|
+
## Communicate status
|
|
225
|
+
|
|
226
|
+
<Badge variant="success">Stable</Badge>{" "}
|
|
227
|
+
<Badge variant="warning">Beta</Badge>{" "}
|
|
228
|
+
<Badge variant="info">New</Badge>
|
|
229
|
+
|
|
230
|
+
<Tip>
|
|
231
|
+
Browse the complete component library at [docs.thally.io](https://docs.thally.io/components/card).
|
|
232
|
+
</Tip>
|
|
233
|
+
`,
|
|
234
|
+
"customization.mdx": `---
|
|
235
|
+
title: Customization
|
|
236
|
+
description: Make {NAME} feel unmistakably like your product.
|
|
237
|
+
keywords:
|
|
238
|
+
- {NAME}
|
|
239
|
+
- branding
|
|
240
|
+
- navigation
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
Your documentation should feel like part of the product\u2014not a separate website.
|
|
140
244
|
|
|
141
|
-
|
|
245
|
+
<CardGroup cols={2}>
|
|
246
|
+
<Card title="Brand and theme" icon="party-horn" href="https://docs.thally.io/guides/branding-and-theming">
|
|
247
|
+
Configure colors, logos, favicons, typography, and light or dark presentation.
|
|
248
|
+
</Card>
|
|
249
|
+
<Card title="Navigation" icon="book-open" href="https://docs.thally.io/guides/configuring-navigation">
|
|
250
|
+
Organize tabs, icon-labelled groups, pages, and external destinations in \`docs.json\`.
|
|
251
|
+
</Card>
|
|
252
|
+
<Card title="Domains" icon="link-simple" href="https://app.thally.io">
|
|
253
|
+
Connect a custom domain from your site settings in Thally Cloud.
|
|
254
|
+
</Card>
|
|
255
|
+
<Card title="Analytics and feedback" icon="message" href="https://app.thally.io">
|
|
256
|
+
Learn what readers need and collect feedback without third-party widgets.
|
|
257
|
+
</Card>
|
|
258
|
+
</CardGroup>
|
|
142
259
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
260
|
+
<Note type="info" title="Start with docs.json">
|
|
261
|
+
Navigation and portable presentation settings live in \`docs.json\`. Site
|
|
262
|
+
identity and fallback brand values live in \`src/data/site.ts\`.
|
|
263
|
+
</Note>
|
|
146
264
|
`,
|
|
147
265
|
"changelog.mdx": `---
|
|
148
266
|
title: Changelog
|
|
@@ -165,17 +283,121 @@ The first release of your **{NAME}** documentation.
|
|
|
165
283
|
Edit this page at \`src/content/changelog.mdx\` to announce your own releases as you ship.
|
|
166
284
|
`
|
|
167
285
|
};
|
|
286
|
+
var STARTER_SPANISH_PAGES = {
|
|
287
|
+
"introduction.mdx": `---
|
|
288
|
+
title: Introducci\xF3n
|
|
289
|
+
description: Te damos la bienvenida a {NAME}.
|
|
290
|
+
mode: home
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
<Hero
|
|
294
|
+
title="Te damos la bienvenida a {NAME}"
|
|
295
|
+
subtitle="Usa este sitio inicial para presentar tu producto, guiar a tus lectores hasta su primer resultado y publicar una referencia de API clara."
|
|
296
|
+
primaryLabel="Abrir inicio r\xE1pido"
|
|
297
|
+
primaryHref="/es/quickstart"
|
|
298
|
+
secondaryLabel="Ver componentes"
|
|
299
|
+
secondaryHref="/es/components"
|
|
300
|
+
/>
|
|
301
|
+
|
|
302
|
+
<CardGroup cols={3}>
|
|
303
|
+
<Card title="Inicio r\xE1pido" icon="party-horn" href="/es/quickstart">
|
|
304
|
+
Ayuda a tus lectores a lograr su primer resultado en minutos.
|
|
305
|
+
</Card>
|
|
306
|
+
<Card title="Componentes" icon="grid-round" href="/es/components">
|
|
307
|
+
Usa pesta\xF1as, pasos, tarjetas, avisos y acordeones.
|
|
308
|
+
</Card>
|
|
309
|
+
<Card title="Referencia de API" icon="code-simple" href="/es/api">
|
|
310
|
+
Convierte \`openapi.yaml\` en documentaci\xF3n interactiva.
|
|
311
|
+
</Card>
|
|
312
|
+
<Card title="Personalizaci\xF3n" icon="wrench" href="/es/customization">
|
|
313
|
+
Adapta la navegaci\xF3n, marca, tipograf\xEDa y enlaces.
|
|
314
|
+
</Card>
|
|
315
|
+
<Card title="Varios idiomas" icon="message" href="/">
|
|
316
|
+
Cambia entre ingl\xE9s y espa\xF1ol desde el selector de idioma.
|
|
317
|
+
</Card>
|
|
318
|
+
<Card title="Preparado para IA" icon="link-simple" href="/llms.txt">
|
|
319
|
+
Publica contenido legible por agentes desde el primer d\xEDa.
|
|
320
|
+
</Card>
|
|
321
|
+
</CardGroup>
|
|
322
|
+
`,
|
|
323
|
+
"quickstart.mdx": `---
|
|
324
|
+
title: Inicio r\xE1pido
|
|
325
|
+
description: Gu\xEDa a tus lectores hasta su primer resultado con {NAME}.
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
Un buen inicio r\xE1pido lleva al lector de cero a un resultado visible sin explicar
|
|
329
|
+
todas las opciones.
|
|
330
|
+
|
|
331
|
+
<Steps>
|
|
332
|
+
<Step title="Instala">
|
|
333
|
+
Explica c\xF3mo instalar {NAME} o crear una cuenta.
|
|
334
|
+
|
|
335
|
+
\`\`\`bash
|
|
336
|
+
npm install your-package
|
|
337
|
+
\`\`\`
|
|
338
|
+
</Step>
|
|
339
|
+
<Step title="Configura">
|
|
340
|
+
Muestra \xFAnicamente la configuraci\xF3n necesaria para comenzar.
|
|
341
|
+
</Step>
|
|
342
|
+
<Step title="Ejecuta">
|
|
343
|
+
Termina con una acci\xF3n y un resultado que el lector pueda comprobar.
|
|
344
|
+
</Step>
|
|
345
|
+
</Steps>
|
|
346
|
+
|
|
347
|
+
<Tip>Enlaza la siguiente gu\xEDa que deber\xEDa leer una vez completado este flujo.</Tip>
|
|
348
|
+
`,
|
|
349
|
+
"components.mdx": `---
|
|
350
|
+
title: Componentes
|
|
351
|
+
description: Una muestra de los componentes MDX disponibles en {NAME}.
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
<Tabs>
|
|
355
|
+
<Tab title="npm">\`npm install your-package\`</Tab>
|
|
356
|
+
<Tab title="pnpm">\`pnpm add your-package\`</Tab>
|
|
357
|
+
<Tab title="yarn">\`yarn add your-package\`</Tab>
|
|
358
|
+
</Tabs>
|
|
359
|
+
|
|
360
|
+
<Accordion title="\xBFD\xF3nde debe ir la configuraci\xF3n avanzada?">
|
|
361
|
+
Mant\xE9n visible el camino principal y coloca los detalles opcionales aqu\xED.
|
|
362
|
+
</Accordion>
|
|
363
|
+
|
|
364
|
+
<Badge variant="success">Estable</Badge>{" "}
|
|
365
|
+
<Badge variant="warning">Beta</Badge>{" "}
|
|
366
|
+
<Badge variant="info">Nuevo</Badge>
|
|
367
|
+
`,
|
|
368
|
+
"customization.mdx": `---
|
|
369
|
+
title: Personalizaci\xF3n
|
|
370
|
+
description: Haz que {NAME} se sienta como una parte natural de tu producto.
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
<CardGroup cols={2}>
|
|
374
|
+
<Card title="Marca y tema" icon="party-horn">Configura colores, logotipos, tipograf\xEDa y apariencia.</Card>
|
|
375
|
+
<Card title="Navegaci\xF3n" icon="book-open">Organiza pesta\xF1as, grupos con iconos y p\xE1ginas en \`docs.json\`.</Card>
|
|
376
|
+
<Card title="Dominios" icon="link-simple">Conecta un dominio personalizado desde Thally Cloud.</Card>
|
|
377
|
+
<Card title="Anal\xEDtica y feedback" icon="message">Comprende qu\xE9 necesitan tus lectores.</Card>
|
|
378
|
+
</CardGroup>
|
|
379
|
+
`,
|
|
380
|
+
"changelog.mdx": `---
|
|
381
|
+
title: Novedades
|
|
382
|
+
description: Cambios, versiones y mejoras destacadas de {NAME}.
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## v0.1.0
|
|
386
|
+
|
|
387
|
+
La primera versi\xF3n de la documentaci\xF3n de **{NAME}**.
|
|
388
|
+
|
|
389
|
+
- Sitio creado con [Thally](https://github.com/thallylabs/thally)
|
|
390
|
+
- Referencia de API y contenido preparado para agentes
|
|
391
|
+
- Ejemplo biling\xFCe en ingl\xE9s y espa\xF1ol
|
|
392
|
+
`
|
|
393
|
+
};
|
|
168
394
|
function buildStarterDocsJson({
|
|
169
395
|
enableAiChat,
|
|
170
396
|
repoUrl,
|
|
171
397
|
i18nLocales
|
|
172
398
|
}) {
|
|
173
399
|
const config = {};
|
|
174
|
-
config.theme = "
|
|
175
|
-
config.fonts = {
|
|
176
|
-
body: { family: "Plus Jakarta Sans", weight: ["400", "500", "600", "700"] },
|
|
177
|
-
heading: { family: "Outfit", weight: ["600", "700"] }
|
|
178
|
-
};
|
|
400
|
+
config.theme = "default";
|
|
179
401
|
if (enableAiChat) {
|
|
180
402
|
config.ai = { chat: true };
|
|
181
403
|
}
|
|
@@ -185,43 +407,118 @@ function buildStarterDocsJson({
|
|
|
185
407
|
primary: { label: "Get started", href: "/quickstart" }
|
|
186
408
|
};
|
|
187
409
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
410
|
+
const locales = [
|
|
411
|
+
{ code: "en", label: "English" },
|
|
412
|
+
{ code: "es", label: "Espa\xF1ol" },
|
|
413
|
+
...(i18nLocales ?? []).filter(({ code }) => code !== "en" && code !== "es")
|
|
414
|
+
];
|
|
415
|
+
config.i18n = { defaultLocale: "en", locales };
|
|
194
416
|
config.tabs = [
|
|
195
417
|
{
|
|
196
418
|
tab: "Overview",
|
|
197
|
-
groups: [
|
|
419
|
+
groups: [
|
|
420
|
+
{ group: "Getting Started", icon: "book-open", pages: ["introduction", "quickstart"] },
|
|
421
|
+
{ group: "Explore", icon: "grid-round", pages: ["components"] },
|
|
422
|
+
{ group: "Project", icon: "wrench", pages: ["customization"] }
|
|
423
|
+
]
|
|
198
424
|
},
|
|
199
425
|
{ tab: "API Reference", api: { source: "openapi.yaml" } },
|
|
200
426
|
{ tab: "Changelog", href: "/changelog" }
|
|
201
427
|
];
|
|
202
428
|
return JSON.stringify(config, null, 2) + "\n";
|
|
203
429
|
}
|
|
204
|
-
function writeStarterContent(targetDir, projectName,
|
|
430
|
+
function writeStarterContent(targetDir, projectName, enableAiChat = true, repoUrl = "", i18nLocales) {
|
|
205
431
|
const contentDir = join2(targetDir, "src", "content");
|
|
206
432
|
if (existsSync(contentDir)) {
|
|
207
433
|
const entries = readdirSync(contentDir);
|
|
208
434
|
for (const entry of entries) {
|
|
209
435
|
const fullPath = join2(contentDir, entry);
|
|
210
|
-
|
|
436
|
+
rmSync(fullPath, { recursive: true, force: true });
|
|
211
437
|
}
|
|
212
438
|
} else {
|
|
213
439
|
mkdirSync(contentDir, { recursive: true });
|
|
214
440
|
}
|
|
215
441
|
for (const [filename, template] of Object.entries(STARTER_PAGES)) {
|
|
216
|
-
const content = template.replace(/\{NAME\}/g, projectName)
|
|
442
|
+
const content = template.replace(/\{NAME\}/g, projectName);
|
|
217
443
|
writeFileSync2(join2(contentDir, filename), content, "utf8");
|
|
218
444
|
}
|
|
445
|
+
const spanishDir = join2(contentDir, "es");
|
|
446
|
+
mkdirSync(spanishDir, { recursive: true });
|
|
447
|
+
for (const [filename, template] of Object.entries(STARTER_SPANISH_PAGES)) {
|
|
448
|
+
const content = template.replace(/\{NAME\}/g, projectName);
|
|
449
|
+
writeFileSync2(join2(spanishDir, filename), content, "utf8");
|
|
450
|
+
}
|
|
219
451
|
writeFileSync2(
|
|
220
452
|
join2(targetDir, "docs.json"),
|
|
221
453
|
buildStarterDocsJson({ enableAiChat, repoUrl: repoUrl || void 0, i18nLocales }),
|
|
222
454
|
"utf8"
|
|
223
455
|
);
|
|
224
456
|
}
|
|
457
|
+
function writeStarterAgentGuide(targetDir, projectName) {
|
|
458
|
+
const guide = `# ${projectName} documentation instructions
|
|
459
|
+
|
|
460
|
+
## About this project
|
|
461
|
+
|
|
462
|
+
- This is a documentation site built with [Thally](https://github.com/thallylabs/thally).
|
|
463
|
+
- Pages are MDX files with YAML frontmatter in \`src/content/\`.
|
|
464
|
+
- Navigation and product features are configured in \`docs.json\`.
|
|
465
|
+
- Site identity and fallback brand values live in \`src/data/site.ts\`.
|
|
466
|
+
- Use \`/llms.txt\`, \`/llms-full.txt\`, and \`/skill.md\` on the deployed site for agent-readable context.
|
|
467
|
+
|
|
468
|
+
## Terminology
|
|
469
|
+
|
|
470
|
+
<!-- Add product-specific terms and preferred usage. -->
|
|
471
|
+
|
|
472
|
+
## Writing style
|
|
473
|
+
|
|
474
|
+
- Use active voice and address the reader as \u201Cyou.\u201D
|
|
475
|
+
- Keep sentences concise and headings in sentence case.
|
|
476
|
+
- Bold interface labels and format commands, files, and code with backticks.
|
|
477
|
+
- Lead with the outcome, then explain prerequisites and steps.
|
|
478
|
+
|
|
479
|
+
## Content boundaries
|
|
480
|
+
|
|
481
|
+
<!-- Define what belongs in public docs and what must remain internal. -->
|
|
482
|
+
`;
|
|
483
|
+
writeFileSync2(join2(targetDir, "AGENTS.md"), guide, "utf8");
|
|
484
|
+
}
|
|
485
|
+
function writeStarterReadme(targetDir, projectName) {
|
|
486
|
+
const readme = `# ${projectName}
|
|
487
|
+
|
|
488
|
+
Documentation powered by [Thally](https://github.com/thallylabs/thally).
|
|
489
|
+
|
|
490
|
+
## Local development
|
|
491
|
+
|
|
492
|
+
\`\`\`bash
|
|
493
|
+
npm install
|
|
494
|
+
npm run dev
|
|
495
|
+
\`\`\`
|
|
496
|
+
|
|
497
|
+
Open [http://localhost:3040](http://localhost:3040).
|
|
498
|
+
|
|
499
|
+
## Write your docs
|
|
500
|
+
|
|
501
|
+
- Add MDX pages in \`src/content/\`.
|
|
502
|
+
- Organize navigation and product features in \`docs.json\`.
|
|
503
|
+
- Update the site name, links, and brand defaults in \`src/data/site.ts\`.
|
|
504
|
+
- Copy \`.env.example\` to \`.env.local\` for local secrets.
|
|
505
|
+
|
|
506
|
+
The starter includes a home hero, icon-grouped navigation, English and Spanish
|
|
507
|
+
examples, a guided quickstart, component showcase, changelog, OpenAPI reference,
|
|
508
|
+
and \`AGENTS.md\` writing instructions for coding agents.
|
|
509
|
+
|
|
510
|
+
## Publishing changes
|
|
511
|
+
|
|
512
|
+
Push changes to the default branch to trigger your connected deployment. If the
|
|
513
|
+
site is not connected yet, add the repository in
|
|
514
|
+
[Thally Cloud](https://app.thally.io) or deploy it to any Next.js host.
|
|
515
|
+
|
|
516
|
+
Run \`npx create-thally-docs check --ci .\` before publishing. Deploy the site
|
|
517
|
+
anywhere Next.js is supported, or connect the repository to
|
|
518
|
+
[Thally Cloud](https://app.thally.io) for managed hosting and services.
|
|
519
|
+
`;
|
|
520
|
+
writeFileSync2(join2(targetDir, "README.md"), readme, "utf8");
|
|
521
|
+
}
|
|
225
522
|
function updateSiteConfig(targetDir, projectName, description, brandPreset, repoUrl) {
|
|
226
523
|
const siteFile = join2(targetDir, "src", "data", "site.ts");
|
|
227
524
|
if (!existsSync(siteFile)) {
|
|
@@ -251,6 +548,12 @@ function updateSiteConfig(targetDir, projectName, description, brandPreset, repo
|
|
|
251
548
|
/\{\s*label:\s*'Support',\s*href:\s*'[^']*'\s*\}/,
|
|
252
549
|
`{ label: 'Support', href: '${repoUrl ? `${repoUrl}/issues/new` : ""}' }`
|
|
253
550
|
);
|
|
551
|
+
if (!repoUrl) {
|
|
552
|
+
source = source.replace(
|
|
553
|
+
/\n\s*\{\s*label:\s*'(?:GitHub|Support)',\s*href:\s*''\s*\},?/g,
|
|
554
|
+
""
|
|
555
|
+
);
|
|
556
|
+
}
|
|
254
557
|
writeFileSync2(siteFile, source, "utf8");
|
|
255
558
|
}
|
|
256
559
|
function patchApiReferenceGuard(targetDir) {
|
|
@@ -324,6 +627,7 @@ function patchPackageJson(targetDir, slug) {
|
|
|
324
627
|
const pkgPath = join2(targetDir, "package.json");
|
|
325
628
|
if (!existsSync(pkgPath)) return;
|
|
326
629
|
const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
|
|
630
|
+
const hadWorkspaces = Array.isArray(pkg.workspaces) && pkg.workspaces.length > 0;
|
|
327
631
|
pkg.name = slug;
|
|
328
632
|
delete pkg.workspaces;
|
|
329
633
|
if (pkg.scripts) {
|
|
@@ -331,20 +635,44 @@ function patchPackageJson(targetDir, slug) {
|
|
|
331
635
|
delete pkg.scripts["pretest"];
|
|
332
636
|
delete pkg.scripts["packages:build"];
|
|
333
637
|
}
|
|
638
|
+
if (pkg.dependencies?.["@thallylabs/mcp"] === "*") {
|
|
639
|
+
pkg.dependencies["@thallylabs/mcp"] = "0.7.0";
|
|
640
|
+
}
|
|
334
641
|
writeFileSync2(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
335
642
|
`, "utf8");
|
|
336
643
|
const lockPath = join2(targetDir, "package-lock.json");
|
|
337
|
-
if (existsSync(lockPath))
|
|
644
|
+
if (!existsSync(lockPath)) return;
|
|
645
|
+
const lock = JSON.parse(readFileSync2(lockPath, "utf8"));
|
|
646
|
+
const hasWorkspaceEntries = Object.keys(lock.packages ?? {}).some(
|
|
647
|
+
(key) => key === "packages" || key.startsWith("packages/")
|
|
648
|
+
);
|
|
649
|
+
if (hadWorkspaces || hasWorkspaceEntries) {
|
|
650
|
+
rmSync(lockPath);
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
lock.name = slug;
|
|
654
|
+
if (lock.packages?.[""]) lock.packages[""].name = slug;
|
|
655
|
+
writeFileSync2(lockPath, `${JSON.stringify(lock, null, 2)}
|
|
656
|
+
`, "utf8");
|
|
657
|
+
}
|
|
658
|
+
function patchGitignore(targetDir) {
|
|
659
|
+
const gitignorePath = join2(targetDir, ".gitignore");
|
|
660
|
+
const existing = existsSync(gitignorePath) ? readFileSync2(gitignorePath, "utf8") : "";
|
|
661
|
+
const lines = existing.split(/\r?\n/);
|
|
662
|
+
if (lines.includes("node_modules/")) return;
|
|
663
|
+
const separator = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
664
|
+
writeFileSync2(gitignorePath, `${existing}${separator}node_modules/
|
|
665
|
+
`, "utf8");
|
|
338
666
|
}
|
|
339
667
|
|
|
340
668
|
// src/utils.ts
|
|
341
|
-
import { execSync
|
|
669
|
+
import { execSync } from "child_process";
|
|
342
670
|
import { basename } from "path";
|
|
343
671
|
function slugify(name) {
|
|
344
672
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
345
673
|
}
|
|
346
674
|
function run(cmd, cwd) {
|
|
347
|
-
|
|
675
|
+
execSync(cmd, { cwd, stdio: "inherit" });
|
|
348
676
|
}
|
|
349
677
|
function initGit(targetDir) {
|
|
350
678
|
try {
|
|
@@ -428,12 +756,15 @@ async function scaffold(options) {
|
|
|
428
756
|
console.log(" To finish wiring it: `thally track setup` (pick a trigger) + `thally agent init`,");
|
|
429
757
|
console.log(" then add your ANTHROPIC_API_KEY. See /guides/thally-track.");
|
|
430
758
|
}
|
|
431
|
-
writeStarterContent(targetDir, projectName,
|
|
759
|
+
writeStarterContent(targetDir, projectName, enableAiChat, repoUrl, i18nLocales);
|
|
760
|
+
writeStarterReadme(targetDir, projectName);
|
|
761
|
+
writeStarterAgentGuide(targetDir, projectName);
|
|
432
762
|
updateSiteConfig(targetDir, projectName, description, brandPreset, repoUrl);
|
|
433
763
|
patchApiReferenceGuard(targetDir);
|
|
434
764
|
patchTopBarNavigation(targetDir);
|
|
435
765
|
patchOpenApiFetch(targetDir);
|
|
436
766
|
patchPackageJson(targetDir, slug);
|
|
767
|
+
patchGitignore(targetDir);
|
|
437
768
|
updateEnvExample(targetDir);
|
|
438
769
|
if (doInstall) {
|
|
439
770
|
installDeps(targetDir);
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
initGit,
|
|
4
4
|
installDeps,
|
|
5
5
|
scaffold
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KN6QUPKR.js";
|
|
7
7
|
|
|
8
8
|
// src/migrate/index.ts
|
|
9
9
|
import { mkdirSync as mkdirSync2, copyFileSync as copyFileSync2, readFileSync as readFileSync3, writeFileSync, existsSync as existsSync3, mkdtempSync, rmSync } from "fs";
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
migrateDocs,
|
|
4
4
|
parseGitHubUrl
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QGRDDS5V.js";
|
|
6
6
|
import {
|
|
7
7
|
logo,
|
|
8
8
|
readDocsJson,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
slugify,
|
|
11
11
|
success,
|
|
12
12
|
writeDocsJson
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-KN6QUPKR.js";
|
|
14
14
|
|
|
15
15
|
// src/index.ts
|
|
16
16
|
import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
|
|
@@ -240,8 +240,17 @@ function extractLinks(content) {
|
|
|
240
240
|
}
|
|
241
241
|
return links;
|
|
242
242
|
}
|
|
243
|
-
function
|
|
244
|
-
|
|
243
|
+
function localizedPage(pageId, secondaryLocales) {
|
|
244
|
+
const [first, ...rest] = pageId.split("/");
|
|
245
|
+
if (secondaryLocales.has(first) && rest.length > 0) {
|
|
246
|
+
return { navPageId: rest.join("/"), locale: first };
|
|
247
|
+
}
|
|
248
|
+
return { navPageId: pageId };
|
|
249
|
+
}
|
|
250
|
+
function pageIdToPath(pageId, secondaryLocales) {
|
|
251
|
+
const { navPageId, locale } = localizedPage(pageId, secondaryLocales);
|
|
252
|
+
const basePath = navPageId === "introduction" ? "/" : `/${navPageId}`;
|
|
253
|
+
return locale ? `/${locale}${basePath === "/" ? "" : basePath}` : basePath;
|
|
245
254
|
}
|
|
246
255
|
function validateOpenApi(projectDir, source, issues) {
|
|
247
256
|
const specPath = join(projectDir, source);
|
|
@@ -292,6 +301,13 @@ async function runCheck(projectDir, options) {
|
|
|
292
301
|
const contentDir = join(projectDir, "src", "content");
|
|
293
302
|
const issues = [];
|
|
294
303
|
const config = readDocsJson(projectDir);
|
|
304
|
+
const secondaryLocales = new Set(
|
|
305
|
+
(config.i18n?.locales ?? []).map((locale) => locale.code).filter((code) => code !== config.i18n?.defaultLocale)
|
|
306
|
+
);
|
|
307
|
+
const generatedApiPaths = /* @__PURE__ */ new Set([
|
|
308
|
+
"/api",
|
|
309
|
+
...Array.from(secondaryLocales, (locale) => `/${locale}/api`)
|
|
310
|
+
]);
|
|
295
311
|
const navPageIds = /* @__PURE__ */ new Set();
|
|
296
312
|
const duplicates = /* @__PURE__ */ new Set();
|
|
297
313
|
for (const tab of config.tabs) {
|
|
@@ -324,7 +340,8 @@ async function runCheck(projectDir, options) {
|
|
|
324
340
|
for (const filePath of allFiles) {
|
|
325
341
|
const rel = filePath.slice(contentDir.length + 1).replace(/\.mdx$/, "").replace(/\\/g, "/");
|
|
326
342
|
const pageId = rel.endsWith("/index") ? rel.slice(0, -6) : rel;
|
|
327
|
-
|
|
343
|
+
const { navPageId } = localizedPage(pageId, secondaryLocales);
|
|
344
|
+
if (!navPageIds.has(navPageId)) {
|
|
328
345
|
if (fix) {
|
|
329
346
|
addOrphanToNav(projectDir, pageId);
|
|
330
347
|
fixedOrphans.push(pageId);
|
|
@@ -350,7 +367,7 @@ async function runCheck(projectDir, options) {
|
|
|
350
367
|
if (!data.description) issues.push({ severity: "warning", message: `Missing "description" in frontmatter`, file: rel2 });
|
|
351
368
|
if (content.trim().length < 50) issues.push({ severity: "warning", message: `Very short body (${content.trim().length} chars) \u2014 page may be empty`, file: rel2 });
|
|
352
369
|
if (options.drift) checkDrift(projectDir, rel2, data, issues);
|
|
353
|
-
const path = pageIdToPath(pageId);
|
|
370
|
+
const path = pageIdToPath(pageId, secondaryLocales);
|
|
354
371
|
const anchors = extractHeadingAnchors(content);
|
|
355
372
|
validPaths.add(path);
|
|
356
373
|
anchorsByPath.set(path, anchors);
|
|
@@ -371,7 +388,10 @@ async function runCheck(projectDir, options) {
|
|
|
371
388
|
const [beforeHash, anchor] = target.split("#");
|
|
372
389
|
let path = beforeHash.split("?")[0];
|
|
373
390
|
if (path.length > 1) path = path.replace(/\/$/, "");
|
|
374
|
-
|
|
391
|
+
const isGeneratedApiPath = Array.from(generatedApiPaths).some(
|
|
392
|
+
(prefix) => path === prefix || path.startsWith(`${prefix}/`)
|
|
393
|
+
);
|
|
394
|
+
if (isGeneratedApiPath || path.startsWith("/_next") || /\.[a-z0-9]+$/i.test(path)) continue;
|
|
375
395
|
if (!validPaths.has(path)) {
|
|
376
396
|
issues.push({ severity: "error", message: `Broken link: "${target}" \u2014 no page at "${path}"`, file, line });
|
|
377
397
|
} else if (anchor && !anchorsByPath.get(path)?.has(anchor)) {
|
package/dist/migrate/index.js
CHANGED
package/dist/scaffold.js
CHANGED