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 TARBALL_URL = "https://codeload.github.com/thallylabs/thally/tar.gz/main";
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
- "/cli/",
15
- "/packages/",
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} \u2014 learn what it does, how the docs are organized, and where to start.
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
- ## Welcome
91
-
92
- Welcome to the **{NAME}** documentation. This is your home base for guides, API
93
- references, and everything you need to build with {NAME}. The site is powered by
94
- [Thally](https://github.com/thallylabs/thally), an agent-native docs platform \u2014 every page
95
- is served to humans as polished HTML and to AI agents as structured JSON, JSON-LD,
96
- and Markdown from the same URL, so assistants can read your docs accurately.
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
- - **Guides** \u2014 step-by-step walkthroughs of common tasks and workflows.
101
- - **API reference** \u2014 generated from your OpenAPI spec, with a live "Try It" console.
102
- - **Quickstart** \u2014 install {NAME} and make your first call in a few minutes.
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
- ## Next steps
105
-
106
- Start with the [Quickstart](/quickstart) to get {NAME} running, then make this site
107
- your own by editing \`src/content/introduction.mdx\` and updating the navigation in
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: Install {NAME}, configure your API key, and make your first call in under five minutes.
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
- ## Installation
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
- Install {NAME} with your package manager of choice. We recommend pinning the
123
- version in your project so builds stay reproducible across machines and CI:
152
+ ## Prerequisites
124
153
 
125
- \`\`\`bash
126
- npm install {SLUG}
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
- ## Basic usage
157
+ <Steps>
158
+ <Step title="Install">
159
+ Explain how to install {NAME} or create an account.
130
160
 
131
- Import the client and initialize it with your API key. Keep the key in an
132
- environment variable rather than committing it to source control, so it never
133
- leaks into your repository or build logs:
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
- \`\`\`ts
136
- import { create } from '{SLUG}'
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
- const client = create({ apiKey: process.env.API_KEY })
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
- ## What's next
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
- That's the basics \u2014 you're ready to build. Explore the guides for common workflows,
144
- open the API reference to try endpoints against a live "Try It" console, or edit this
145
- page at \`src/content/quickstart.mdx\` to document your own onboarding flow.
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 = "sharp";
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
- if (i18nLocales && i18nLocales.length > 0) {
189
- config.i18n = {
190
- defaultLocale: "en",
191
- locales: [{ code: "en", label: "English" }, ...i18nLocales]
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: [{ group: "Getting Started", pages: ["introduction", "quickstart"] }]
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, slug, enableAiChat = true, repoUrl = "", i18nLocales) {
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
- execSync(`rm -rf "${fullPath}"`);
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).replace(/\{SLUG\}/g, slug);
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)) rmSync(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 as execSync2 } from "child_process";
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
- execSync2(cmd, { cwd, stdio: "inherit" });
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, slug, enableAiChat, repoUrl, i18nLocales);
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-6HO6ECUE.js";
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-YAG5BZEM.js";
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-6HO6ECUE.js";
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 pageIdToPath(pageId) {
244
- return pageId === "introduction" ? "/" : `/${pageId}`;
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
- if (!navPageIds.has(pageId)) {
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
- if (path.startsWith("/api") || path.startsWith("/_next") || /\.[a-z0-9]+$/i.test(path)) continue;
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)) {
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  migrateDocs
4
- } from "../chunk-YAG5BZEM.js";
5
- import "../chunk-6HO6ECUE.js";
4
+ } from "../chunk-QGRDDS5V.js";
5
+ import "../chunk-KN6QUPKR.js";
6
6
  export {
7
7
  migrateDocs
8
8
  };
package/dist/scaffold.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  scaffold
4
- } from "./chunk-6HO6ECUE.js";
4
+ } from "./chunk-KN6QUPKR.js";
5
5
  export {
6
6
  scaffold
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-thally-docs",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "Scaffold a new Thally documentation project",
5
5
  "type": "module",
6
6
  "engines": {