create-boltdocs 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
2
+ //#region \0rolldown/runtime.js
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -7,65 +7,66 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
9
  var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
16
18
  };
17
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
- // If the importer is in node compatibility mode or this is not an ESM
19
- // file that has been converted to a CommonJS file using a Babel-
20
- // compatible transform (i.e. "__esModule" has not been set), then set
21
- // "default" to the CommonJS "module.exports" for node compatibility.
22
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
- mod
24
- ));
25
-
26
- // src/index.ts
27
- var import_node_fs4 = __toESM(require("fs"), 1);
28
- var import_node_path4 = __toESM(require("path"), 1);
29
- var import_node_child_process = require("child_process");
30
- var import_prompts = __toESM(require("prompts"), 1);
31
- var import_picocolors = __toESM(require("picocolors"), 1);
32
-
33
- // src/templates/shared.ts
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let node_fs = require("node:fs");
25
+ node_fs = __toESM(node_fs);
26
+ let node_path = require("node:path");
27
+ node_path = __toESM(node_path);
28
+ let node_child_process = require("node:child_process");
29
+ let prompts = require("prompts");
30
+ prompts = __toESM(prompts);
31
+ let picocolors = require("picocolors");
32
+ picocolors = __toESM(picocolors);
33
+ //#region src/templates/shared.ts
34
34
  function getPackageJson(projectName) {
35
- return {
36
- name: projectName,
37
- version: "1.0.0",
38
- private: true,
39
- type: "module",
40
- scripts: {
41
- dev: "boltdocs",
42
- build: "boltdocs build",
43
- preview: "boltdocs preview",
44
- "lint:md": 'markdownlint-cli2 "**/*.{md,mdx}"',
45
- "lint:md:fix": 'markdownlint-cli2 --fix "**/*.{md,mdx}"'
46
- },
47
- dependencies: {
48
- react: "^19.0.0",
49
- "react-dom": "^19.0.0",
50
- boltdocs: "latest"
51
- },
52
- devDependencies: {
53
- typescript: "^5.7.0",
54
- "@types/react": "^19.0.0",
55
- "@types/react-dom": "^19.0.0",
56
- "markdownlint-cli2": "^0.22.0",
57
- vite: "^7.0.0",
58
- tailwindcss: "^4.0.0",
59
- "@tailwindcss/vite": "^4.2.2"
60
- }
61
- };
35
+ return {
36
+ name: projectName,
37
+ version: "1.0.0",
38
+ private: true,
39
+ type: "module",
40
+ scripts: {
41
+ dev: "boltdocs",
42
+ build: "boltdocs build",
43
+ preview: "boltdocs preview",
44
+ doctor: "boltdocs doctor",
45
+ "lint:md": "markdownlint-cli2 \"docs/**/*.{md,mdx}\"",
46
+ "lint:md:fix": "markdownlint-cli2 --fix \"docs/**/*.{md,mdx}\""
47
+ },
48
+ dependencies: {
49
+ react: "19.2.5",
50
+ "react-dom": "19.2.5",
51
+ boltdocs: "latest"
52
+ },
53
+ devDependencies: {
54
+ typescript: "^5.7.0",
55
+ "@types/react": "^19.2.14",
56
+ "@types/react-dom": "^19.2.3",
57
+ "markdownlint-cli2": "^0.22.0",
58
+ vite: "^7.0.0",
59
+ tailwindcss: "^4.0.0",
60
+ "@tailwindcss/vite": "^4.2.2"
61
+ }
62
+ };
62
63
  }
63
- var gitignoreContent = `node_modules
64
+ const gitignoreContent = `node_modules
64
65
  dist
65
66
  .DS_Store
66
67
  .boltdocs
67
68
  `;
68
- var markdownlintContent = `# Default state for all rules
69
+ const markdownlintContent = `# Default state for all rules
69
70
  default: true
70
71
 
71
72
  # MD013/line-length - Line length
@@ -87,37 +88,40 @@ MD025: false
87
88
  # MD051/link-fragments
88
89
  MD051: false # Sometimes fragments aren't fully resolved locally by the linter
89
90
  `;
90
- var markdownlintignoreContent = `.git
91
+ const markdownlintignoreContent = `.git
91
92
  **/node_modules
92
93
  node_modules
93
94
  dist
94
95
  `;
95
96
  function getLogoLight() {
96
- return `<svg width="60" height="51" viewBox="0 0 60 51" fill="none" xmlns="http://www.w3.org/2000/svg">
97
+ return `<svg width="60" height="51" viewBox="0 0 60 51" fill="none" xmlns="http://www.w3.org/2000/svg">
97
98
  <path d="M29.4449 0H19.4449V16.5L29.4449 6.5V0Z" fill="white"/>
98
99
  <path d="M26.9449 22.7265C26.9449 22.5077 21.2201 27.0658 16.9449 28.5C13.7491 29.5721 12.3156 29.5038 8.94486 29.5C5.59532 29.4963 0 28.5 0 28.5C0 28.5 5.57953 28.5146 8.94486 27.5C12.5409 26.4158 14.8203 25.5843 17.9449 23.5C23.3445 19.898 29.4449 11.5 29.4449 11.5L29.9449 18C29.9449 18 33.5825 15.8308 36.4449 15C39.4452 14.1291 44.4449 14 44.4449 14C44.4449 14 36.9449 19 34.4449 21.5C31.5322 24.4126 29.8582 26.9017 29.4449 31C29.1217 34.2041 29.4771 36.4508 31.4449 39C33.5792 41.765 35.952 43.0183 39.4449 43C42.677 42.9831 45.3003 42.4182 47.4449 40C49.7406 37.4113 50.2495 34.4466 49.9449 31C49.6603 27.7804 48.4876 25.4953 45.9449 23.5C43.2931 21.4191 36.4449 24 36.4449 24L47.9449 15C47.9449 15 51.5761 16.771 53.4449 18.5C55.711 20.5967 56.7467 22.1546 57.9449 25C59.1784 27.9295 59.4832 29.8216 59.4449 33C59.4089 35.9867 59.179 37.78 57.9449 40.5C56.8475 42.9185 55.8511 44.6507 53.9449 46.5C51.9236 48.4609 50.5803 49.0076 47.9449 50C45.5414 50.9051 44.0131 51 41.4449 51C38.8766 51 37.3235 50.9685 34.9449 50C32.4851 48.9985 29.4449 46 29.4449 46V51H19.4449V37.9904L22.9449 31.4226L26.9449 22.7265Z" fill="white"/>
99
100
  </svg>`;
100
101
  }
101
102
  function getLogoDark() {
102
- return `<svg width="60" height="52" viewBox="0 0 60 52" fill="none" xmlns="http://www.w3.org/2000/svg">
103
+ return `<svg width="60" height="52" viewBox="0 0 60 52" fill="none" xmlns="http://www.w3.org/2000/svg">
103
104
  <path d="M29.4449 0H19.4449V16.5L29.4449 6.5V0Z" fill="black"/>
104
105
  <path d="M26.9449 22.7265C26.9449 22.5077 21.2201 27.0658 16.9449 28.5C13.7491 29.5721 12.3156 29.5038 8.94486 29.5C5.59532 29.4963 0 28.5 0 28.5C0 28.5 5.57953 28.5146 8.94486 27.5C12.5409 26.4158 14.8203 25.5843 17.9449 23.5C23.3445 19.898 29.4449 11.5 29.4449 11.5L29.9449 18.5C29.9449 18.5 33.5124 15.5332 36.4449 15C41.9449 14 45.4449 15 45.4449 15C45.4449 15 36.9449 19 34.4449 21.5C31.5322 24.4126 29.8582 26.9017 29.4449 31C29.1217 34.2041 29.4771 36.4508 31.4449 39C33.5792 41.765 35.952 43.0183 39.4449 43C42.677 42.9831 45.3003 42.4182 47.4449 40C49.7406 37.4113 50.2495 34.4466 49.9449 31C49.6603 27.7804 48.4876 25.4953 45.9449 23.5C43.2931 21.4191 36.4449 24 36.4449 24L47.4449 15.5C47.4449 15.5 50.4449 16 53.4449 19C56.4449 22 57.4449 23.5 57.9449 24.5C58.4449 25.5 59.9449 28.5 59.9449 33.5C59.9449 36.4869 59.9449 37.5 57.9449 41.5C55.9449 45.5 52.9449 47.5 52.9449 47.5C52.9449 47.5 51.9449 48.5 49.9449 49.5C47.9449 50.5 45.9289 50.8863 44.9449 51.1121C43.2783 51.4944 42.7023 51.5 41.4449 51.5C40.6256 51.5 39.3731 51.3693 37.9449 51.0624C36.9972 50.8587 35.9722 50.5774 34.9449 50.2051C33.7409 49.7688 32.5339 49.2076 31.4449 48.5C30.6262 47.9681 29.4449 47 29.4449 47V51H19.4449V37.9904L22.9449 31.4226L26.9449 22.7265Z" fill="black"/>
105
106
  </svg>`;
106
107
  }
107
108
  function getBoltdocsConfig(projectName, options = {}) {
108
- const i18nConfig = options.i18n ? `
109
+ const i18nConfig = options.i18n ? `
109
110
  i18n: {
110
111
  defaultLocale: 'en',
111
112
  locales: {
112
113
  en: 'English',
113
- es: 'Espa\xF1ol'
114
+ es: 'Español'
115
+ },
116
+ localeConfigs: {
117
+ en: { label: 'English', direction: 'ltr' },
118
+ es: { label: 'Español', direction: 'ltr' }
114
119
  }
115
120
  },` : "";
116
- const homePageConfig = options.homePage ? `
117
- homePage: '${options.homePage}',` : "";
118
- return `import { defineConfig } from 'boltdocs';
121
+ return `import { defineConfig } from 'boltdocs';
119
122
 
120
- export default defineConfig({${homePageConfig}${i18nConfig}
123
+ export default defineConfig({${options.homePage ? `
124
+ homePage: '${options.homePage}',` : ""}${i18nConfig}
121
125
  theme: {
122
126
  title: '${projectName}',
123
127
  logo: {
@@ -136,7 +140,7 @@ export default defineConfig({${homePageConfig}${i18nConfig}
136
140
  });`;
137
141
  }
138
142
  function getIndexCss() {
139
- return `@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap");
143
+ return `
140
144
  @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
141
145
 
142
146
  @import "tailwindcss";
@@ -147,38 +151,10 @@ function getIndexCss() {
147
151
  inside node_modules for class usage and generate the necessary CSS.
148
152
  */
149
153
  @source "./node_modules/boltdocs/src/client";
150
-
151
- .hero-section {
152
- display: flex;
153
- flex-direction: column;
154
- align-items: center;
155
- justify-content: center;
156
- padding: 8rem 2rem;
157
- text-align: center;
158
- }
159
-
160
- .hero-title {
161
- font-size: 4.5rem;
162
- font-weight: 900;
163
- letter-spacing: -0.02em;
164
- line-height: 1.1;
165
- background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-primary-400) 100%);
166
- -webkit-background-clip: text;
167
- -webkit-text-fill-color: transparent;
168
- margin-bottom: 1.5rem;
169
- }
170
-
171
- .hero-subtitle {
172
- font-size: 1.5rem;
173
- color: var(--color-muted);
174
- max-width: 48rem;
175
- margin-bottom: 3rem;
176
- line-height: 1.6;
177
- }
178
154
  `;
179
155
  }
180
156
  function getLayoutPage() {
181
- return `import {
157
+ return `import {
182
158
  DocsLayout,
183
159
  Navbar,
184
160
  Sidebar,
@@ -186,60 +162,56 @@ function getLayoutPage() {
186
162
  Head,
187
163
  Breadcrumbs,
188
164
  PageNav,
189
- ProgressBar,
190
165
  ErrorBoundary,
191
166
  CopyMarkdown,
192
167
  useRoutes,
193
168
  useConfig,
194
- useMdxComponents,
169
+ useLocation
195
170
  } from 'boltdocs/client'
196
- import { useLocation} from 'boltdocs/hooks'
197
171
 
198
172
  export default function Layout({ children }: { children: React.ReactNode }) {
199
173
  const { routes: filteredRoutes, allRoutes, currentRoute } = useRoutes()
200
174
  const { pathname } = useLocation()
201
175
  const config = useConfig()
202
- const mdxComponents = useMdxComponents()
203
- const CopyMarkdownComp = (mdxComponents.CopyMarkdown as any) || CopyMarkdown
204
176
 
205
- const isHome = pathname === '/' || pathname === ''
177
+ const isDocs = pathname.startsWith('/docs')
206
178
 
207
179
  return (
208
180
  <DocsLayout>
209
- {/* Modern Spotlight Gradients */}
210
- <ProgressBar />
211
181
  <Head
212
- siteTitle={config.theme?.title || 'Boltdocs'}
213
- siteDescription={config.theme?.description || ''}
182
+ siteTitle={config.theme?.title}
183
+ siteDescription={config.theme?.description}
214
184
  routes={allRoutes}
215
185
  />
216
186
  <Navbar />
217
187
 
218
188
  <DocsLayout.Body>
219
- {!isHome && <Sidebar routes={filteredRoutes} config={config} />}
189
+ {isDocs && <Sidebar routes={filteredRoutes} config={config} />}
220
190
 
221
191
  <DocsLayout.Content>
222
- {!isHome && (
223
- <DocsLayout.ContentHeader>
224
- <Breadcrumbs />
225
- <CopyMarkdownComp
226
- mdxRaw={currentRoute?._rawContent}
227
- route={currentRoute}
228
- config={config.theme?.copyMarkdown}
229
- />
230
- </DocsLayout.ContentHeader>
231
- )}
232
-
233
- <ErrorBoundary>{children}</ErrorBoundary>
234
-
235
- {!isHome && (
236
- <DocsLayout.ContentFooter>
237
- <PageNav />
238
- </DocsLayout.ContentFooter>
239
- )}
192
+ <DocsLayout.ContentMdx>
193
+ {isDocs && (
194
+ <DocsLayout.ContentHeader>
195
+ <Breadcrumbs />
196
+ <CopyMarkdown
197
+ mdxRaw={currentRoute?._rawContent}
198
+ route={currentRoute}
199
+ config={config.theme?.copyMarkdown}
200
+ />
201
+ </DocsLayout.ContentHeader>
202
+ )}
203
+
204
+ <ErrorBoundary>{children}</ErrorBoundary>
205
+
206
+ {isDocs && (
207
+ <DocsLayout.ContentFooter>
208
+ <PageNav />
209
+ </DocsLayout.ContentFooter>
210
+ )}
211
+ </DocsLayout.ContentMdx>
240
212
  </DocsLayout.Content>
241
213
 
242
- {!isHome && (
214
+ {isDocs && (
243
215
  <OnThisPage
244
216
  headings={currentRoute?.headings}
245
217
  editLink={config.theme?.editLink}
@@ -251,40 +223,78 @@ export default function Layout({ children }: { children: React.ReactNode }) {
251
223
  </DocsLayout>
252
224
  )
253
225
  }
254
-
255
226
  `;
256
227
  }
257
-
258
- // src/templates/empty.ts
259
- var import_node_path = __toESM(require("path"), 1);
260
- var import_node_fs = __toESM(require("fs"), 1);
261
- function generateEmptyTemplate(projectDir, projectName) {
262
- const srcDir = import_node_path.default.join(projectDir, "src");
263
- import_node_fs.default.mkdirSync(srcDir, { recursive: true });
264
- const homePageContent = `import React from 'react';
228
+ function generateHomePage() {
229
+ return `
230
+ import { Button, Cards, Card } from 'boltdocs/client'
231
+ import { time } from 'node:console';
232
+
233
+ const features = [
234
+ {
235
+ title: 'Fast and Lightweight',
236
+ description: 'Boltdocs is built with performance in mind, ensuring your documentation loads quickly and efficiently.',
237
+ icon: '⚡',
238
+ href: "https://boltdocs.vercel.app/docs/guides/overview/introduction"
239
+ },
240
+ {
241
+ title: "I18n & Versioning Support",
242
+ description: "Easily manage multiple languages and versions of your documentation with built-in support.",
243
+ icon: '🌐',
244
+ href: 'https://boltdocs.vercel.app/docs/guides/core-concepts/i18n'
245
+ },
246
+ {
247
+ title: 'Customizable',
248
+ description: 'Tailor your documentation site to your needs with flexible customization options.',
249
+ icon: '🎨',
250
+ href: 'https://boltdocs.vercel.app/docs/guides/customization/theme'
251
+
252
+ },
253
+ {
254
+ title: "plugins",
255
+ description: "Extend Boltdocs' functionality with a growing ecosystem of plugins.",
256
+ icon: '🔌',
257
+ href: 'https://boltdocs.vercel.app/docs/plugins'
258
+ }
259
+ ]
265
260
 
266
261
  export default function HomePage() {
267
262
  return (
268
- <div className="hero-section">
269
- <h1 className="hero-title">${projectName}</h1>
270
- <p className="hero-subtitle">
271
- Your minimal documentation site is ready. Start building something amazing.
272
- </p>
273
- <div className="flex gap-4">
274
- <a href="/docs" className="bg-primary text-primary-foreground px-8 py-3 rounded-lg no-underline font-semibold text-lg hover:opacity-90 transition-opacity">
275
- Get Started
276
- </a>
277
- </div>
263
+ <div className="w-full h-screen flex flex-col items-center pt-10 gap-6">
264
+ <header className='flex flex-col items-center'>
265
+ <h1 className="text-4xl font-bold text-center">Powerful Documentation</h1>
266
+ <p className="text-center">
267
+ Your minimal documentation site is ready. Start building something amazing.
268
+ </p>
269
+ <div className="flex gap-4">
270
+ <Button href="/docs">
271
+ Get Started
272
+ </Button>
273
+ </div>
274
+ </header>
275
+ <Cards className='mx-auto w-[60%]' cols={2}>
276
+ {features.map((feature, index) => (
277
+ <Card href={feature.href} key={index} title={feature.title} icon={feature.icon}>
278
+ <p>{feature.description}</p>
279
+ </Card>
280
+ ))}
281
+ </Cards>
278
282
  </div>
279
283
  );
280
284
  }
281
285
  `;
282
- const docsDir = import_node_path.default.join(projectDir, "docs");
283
- import_node_fs.default.mkdirSync(docsDir, { recursive: true });
284
- import_node_fs.default.writeFileSync(import_node_path.default.join(srcDir, "HomePage.tsx"), homePageContent);
285
- import_node_fs.default.writeFileSync(import_node_path.default.join(projectDir, "index.css"), getIndexCss());
286
- import_node_fs.default.writeFileSync(import_node_path.default.join(docsDir, "layout.tsx"), getLayoutPage());
287
- const indexMdx = `---
286
+ }
287
+ //#endregion
288
+ //#region src/templates/empty.ts
289
+ function generateEmptyTemplate(projectDir, projectName) {
290
+ const srcDir = node_path.default.join(projectDir, "src");
291
+ node_fs.default.mkdirSync(srcDir, { recursive: true });
292
+ const docsDir = node_path.default.join(projectDir, "docs");
293
+ node_fs.default.mkdirSync(docsDir, { recursive: true });
294
+ node_fs.default.writeFileSync(node_path.default.join(srcDir, "home-page.tsx"), generateHomePage());
295
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, "index.css"), getIndexCss());
296
+ node_fs.default.writeFileSync(node_path.default.join(docsDir, "layout.tsx"), getLayoutPage());
297
+ const indexMdx = `---
288
298
  title: Welcome
289
299
  ---
290
300
 
@@ -292,18 +302,16 @@ title: Welcome
292
302
 
293
303
  This is a minimal documentation setup. You can start by editing \`docs/index.mdx\`.
294
304
  `;
295
- import_node_fs.default.writeFileSync(import_node_path.default.join(docsDir, "index.mdx"), indexMdx);
305
+ node_fs.default.writeFileSync(node_path.default.join(docsDir, "index.mdx"), indexMdx);
296
306
  }
297
-
298
- // src/templates/base.ts
299
- var import_node_path2 = __toESM(require("path"), 1);
300
- var import_node_fs2 = __toESM(require("fs"), 1);
301
- function generateBaseTemplate(projectDir) {
302
- const srcDir = import_node_path2.default.join(projectDir, "src");
303
- import_node_fs2.default.mkdirSync(srcDir, { recursive: true });
304
- const componentsDir = import_node_path2.default.join(srcDir, "components");
305
- import_node_fs2.default.mkdirSync(componentsDir, { recursive: true });
306
- const buttonContent = `import React from 'react';
307
+ //#endregion
308
+ //#region src/templates/base.ts
309
+ function generateBaseTemplate(projectDir, projectName) {
310
+ const srcDir = node_path.default.join(projectDir, "src");
311
+ node_fs.default.mkdirSync(srcDir, { recursive: true });
312
+ const componentsDir = node_path.default.join(srcDir, "components");
313
+ node_fs.default.mkdirSync(componentsDir, { recursive: true });
314
+ node_fs.default.writeFileSync(node_path.default.join(componentsDir, "Button.tsx"), `import React from 'react';
307
315
 
308
316
  export function Button({ children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement>) {
309
317
  return (
@@ -315,59 +323,13 @@ export function Button({ children, ...props }: React.ButtonHTMLAttributes<HTMLBu
315
323
  </button>
316
324
  );
317
325
  }
318
- `;
319
- import_node_fs2.default.writeFileSync(import_node_path2.default.join(componentsDir, "Button.tsx"), buttonContent);
320
- const homePageContent = `import { Button } from 'boltdocs/primitives';
321
- import { Cards, Card } from 'boltdocs/mdx'
322
-
323
- export default function HomePage() {
324
- return (
325
- <div className="hero-section">
326
- <h1 className="hero-title">my-boltdocs-app</h1>
327
- <p className="hero-subtitle">
328
- The modern documentation framework. Fast, efficient, and beautiful by default.
329
- </p>
330
-
331
- <div className="flex gap-4 mb-16">
332
- <Button href="/docs">
333
- Get Started
334
- </Button>
335
- <Button href="https://github.com/jesusalcaladev/boltdocs" variant={'ghost'}>
336
- GitHub
337
- </Button>
338
- </div>
339
-
340
- <Cards>
341
- {[
342
- {
343
- title: "Performance First",
344
- desc: "Ultra-fast load times and instant HMR with Vite-powered development."
345
- },
346
- {
347
- title: "MDX Support",
348
- desc: "Write documentation with React components directly in your markdown files."
349
- },
350
- {
351
- title: "Fully Customizable",
352
- desc: "Custom layouts, components, and themes tailored to your project needs."
353
- }
354
- ].map((feat, i) => (
355
- <Card key={i} title={feat.title}>
356
- {feat.desc}
357
- </Card>
358
- ))}
359
- </Cards>
360
- </div>
361
- );
362
- }
363
-
364
- `;
365
- const docsDir = import_node_path2.default.join(projectDir, "docs");
366
- import_node_fs2.default.mkdirSync(docsDir, { recursive: true });
367
- import_node_fs2.default.writeFileSync(import_node_path2.default.join(srcDir, "HomePage.tsx"), homePageContent);
368
- import_node_fs2.default.writeFileSync(import_node_path2.default.join(docsDir, "layout.tsx"), getLayoutPage());
369
- import_node_fs2.default.writeFileSync(import_node_path2.default.join(projectDir, "index.css"), getIndexCss());
370
- const indexMdx = `---
326
+ `);
327
+ const docsDir = node_path.default.join(projectDir, "docs");
328
+ node_fs.default.mkdirSync(docsDir, { recursive: true });
329
+ node_fs.default.writeFileSync(node_path.default.join(srcDir, "home-page.tsx"), generateHomePage());
330
+ node_fs.default.writeFileSync(node_path.default.join(docsDir, "layout.tsx"), getLayoutPage());
331
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, "index.css"), getIndexCss());
332
+ node_fs.default.writeFileSync(node_path.default.join(docsDir, "index.mdx"), `---
371
333
  title: Introduction
372
334
  ---
373
335
 
@@ -386,19 +348,16 @@ Welcome to your new documentation site!
386
348
  </Tip>
387
349
 
388
350
  <Button onClick={() => alert('Hello world!')}>Try me</Button>
389
- `;
390
- import_node_fs2.default.writeFileSync(import_node_path2.default.join(docsDir, "index.mdx"), indexMdx);
351
+ `);
391
352
  }
392
-
393
- // src/templates/i18n.ts
394
- var import_node_path3 = __toESM(require("path"), 1);
395
- var import_node_fs3 = __toESM(require("fs"), 1);
396
- function generateI18nTemplate(projectDir) {
397
- const srcDir = import_node_path3.default.join(projectDir, "src");
398
- import_node_fs3.default.mkdirSync(srcDir, { recursive: true });
399
- const componentsDir = import_node_path3.default.join(srcDir, "components");
400
- import_node_fs3.default.mkdirSync(componentsDir, { recursive: true });
401
- const buttonContent = `import React from 'react';
353
+ //#endregion
354
+ //#region src/templates/i18n.ts
355
+ function generateI18nTemplate(projectDir, projectName) {
356
+ const srcDir = node_path.default.join(projectDir, "src");
357
+ node_fs.default.mkdirSync(srcDir, { recursive: true });
358
+ const componentsDir = node_path.default.join(srcDir, "components");
359
+ node_fs.default.mkdirSync(componentsDir, { recursive: true });
360
+ node_fs.default.writeFileSync(node_path.default.join(componentsDir, "Button.tsx"), `import React from 'react';
402
361
 
403
362
  export function Button({ children, className = '', ...props }: React.ButtonHTMLAttributes<HTMLButtonElement>) {
404
363
  return (
@@ -410,54 +369,13 @@ export function Button({ children, className = '', ...props }: React.ButtonHTMLA
410
369
  </button>
411
370
  );
412
371
  }
413
- `;
414
- import_node_fs3.default.writeFileSync(import_node_path3.default.join(componentsDir, "Button.tsx"), buttonContent);
415
- const homePageContent = `import React from 'react';
416
- import { Button } from './components/Button';
417
- import { useI18n } from 'boltdocs/hooks';
418
-
419
- export default function HomePage() {
420
- const i18n = useI18n();
421
- const locale = (i18n as any)?.locale || 'en';
422
-
423
- const translations: any = {
424
- en: {
425
- title: "Global Documentation",
426
- subtitle: "Multi-language support built-in.",
427
- button: "Get Started"
428
- },
429
- es: {
430
- title: "Documentaci\xF3n Global",
431
- subtitle: "Soporte multi-idioma integrado.",
432
- button: "Comenzar"
433
- }
434
- };
435
-
436
- const content = translations[locale] || translations.en;
437
-
438
- return (
439
- <div className="hero-section">
440
- <h1 className="hero-title">{content.title}</h1>
441
- <p className="hero-subtitle">{content.subtitle}</p>
442
- <div className="flex gap-4">
443
- <a href="/docs" className="no-underline">
444
- <Button className="text-lg px-10 py-4">
445
- {content.button}
446
- </Button>
447
- </a>
448
- </div>
449
- </div>
450
- );
451
- }
452
- `;
453
- const docsDir = import_node_path3.default.join(projectDir, "docs");
454
- import_node_fs3.default.mkdirSync(docsDir, { recursive: true });
455
- import_node_fs3.default.writeFileSync(import_node_path3.default.join(srcDir, "HomePage.tsx"), homePageContent);
456
- import_node_fs3.default.writeFileSync(import_node_path3.default.join(projectDir, "index.css"), getIndexCss());
457
- import_node_fs3.default.writeFileSync(import_node_path3.default.join(docsDir, "layout.tsx"), getLayoutPage());
458
- import_node_fs3.default.writeFileSync(
459
- import_node_path3.default.join(docsDir, "index.mdx"),
460
- `---
372
+ `);
373
+ const docsDir = node_path.default.join(projectDir, "docs");
374
+ node_fs.default.mkdirSync(docsDir, { recursive: true });
375
+ node_fs.default.writeFileSync(node_path.default.join(srcDir, "home-page.tsx"), generateHomePage());
376
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, "index.css"), getIndexCss());
377
+ node_fs.default.writeFileSync(node_path.default.join(docsDir, "layout.tsx"), getLayoutPage());
378
+ node_fs.default.writeFileSync(node_path.default.join(docsDir, "index.mdx"), `---
461
379
  title: Introduction
462
380
  ---
463
381
 
@@ -466,158 +384,211 @@ title: Introduction
466
384
  This project is configured with English and Spanish support.
467
385
 
468
386
  Check the \`es/\` folder for Spanish content.
469
- `
470
- );
471
- const esDocsDir = import_node_path3.default.join(docsDir, "es");
472
- import_node_fs3.default.mkdirSync(esDocsDir, { recursive: true });
473
- import_node_fs3.default.writeFileSync(
474
- import_node_path3.default.join(esDocsDir, "index.mdx"),
475
- `---
476
- title: Introducci\xF3n
387
+ `);
388
+ const esDocsDir = node_path.default.join(docsDir, "es");
389
+ node_fs.default.mkdirSync(esDocsDir, { recursive: true });
390
+ node_fs.default.writeFileSync(node_path.default.join(esDocsDir, "index.mdx"), `---
391
+ title: Introducción
477
392
  ---
478
393
 
479
- # Internacionalizaci\xF3n
394
+ # Internacionalización
480
395
 
481
- Este proyecto est\xE1 configurado con soporte para Ingl\xE9s y Espa\xF1ol.
396
+ Este proyecto está configurado con soporte para Inglés y Español.
482
397
 
483
- Boltdocs detecta autom\xE1ticamente las carpetas de idiomas.
484
- `
485
- );
398
+ Boltdocs detecta automáticamente las carpetas de idiomas.
399
+ `);
486
400
  }
401
+ //#endregion
402
+ //#region src/templates/external.ts
403
+ function generateExternalTemplate(projectDir, projectName) {
404
+ const srcDir = node_path.default.join(projectDir, "src");
405
+ node_fs.default.mkdirSync(srcDir, { recursive: true });
406
+ const docsDir = node_path.default.join(projectDir, "docs");
407
+ node_fs.default.mkdirSync(docsDir, { recursive: true });
408
+ const externalPagesDir = node_path.default.join(docsDir, "pages-external");
409
+ node_fs.default.mkdirSync(externalPagesDir, { recursive: true });
410
+ node_fs.default.writeFileSync(node_path.default.join(externalPagesDir, "index.tsx"), `import React from 'react'
411
+ import { PrimitiveButton } from 'boltdocs/client'
412
+ import HomePage from '../../src/home-page'
413
+
414
+ export const homePage = HomePage
415
+
416
+ /**
417
+ * External pages are standalone React components mapped to specific routes.
418
+ * They are defined outside the standard docs/ hierarchy.
419
+ */
420
+ export const pages = {
421
+ '/contact': () => (
422
+ <div className="p-20 text-center">
423
+ <h1 className="text-6xl font-black mb-6 bg-linear-to-r from-primary-600 to-primary-400 bg-clip-text text-transparent">
424
+ Contact Us
425
+ </h1>
426
+ <p className="text-xl text-text-muted mb-12 max-w-2xl mx-auto leading-relaxed">
427
+ This is a custom page defined in pages-external/index.tsx.
428
+ It bypassing the standard markdown processing while still being part of your Boltdocs app.
429
+ </p>
430
+ <PrimitiveButton
431
+ onClick={() => window.location.href = '/'}
432
+ className="px-8 py-4 text-lg"
433
+ >
434
+ Return Home
435
+ </PrimitiveButton>
436
+ </div>
437
+ )
438
+ }
439
+
440
+ /**
441
+ * Custom layout specifically for external pages.
442
+ * If not provided, it will fallback to the default app layout.
443
+ */
444
+ export const layout = ({ children }: { children: React.ReactNode }) => (
445
+ <div className="min-h-screen bg-bg-main text-text-main flex flex-col">
446
+ <header className="p-6 border-b border-border-subtle bg-bg-surface/50 backdrop-blur-md sticky top-0 z-50">
447
+ <div className="max-w-7xl mx-auto flex justify-between items-center">
448
+ <div className="font-black text-2xl tracking-tight">BOLTDOCS <span className="text-primary-500 text-sm font-medium">EXTERNAL</span></div>
449
+ <nav className="flex gap-6 items-center">
450
+ <a href="/" className="text-sm font-medium hover:text-primary-500 transition-colors">Home</a>
451
+ <a href="/docs" className="text-sm font-medium hover:text-primary-500 transition-colors">Documentation</a>
452
+ </nav>
453
+ </div>
454
+ </header>
455
+ <main className="flex-1">
456
+ {children}
457
+ </main>
458
+ <footer className="p-12 border-t border-border-subtle bg-bg-muted/30">
459
+ <div className="max-w-7xl mx-auto text-center">
460
+ <p className="text-sm text-text-muted font-medium italic">
461
+ "The best way to predict the future is to documenting it."
462
+ </p>
463
+ </div>
464
+ </footer>
465
+ </div>
466
+ )
467
+ `);
468
+ node_fs.default.writeFileSync(node_path.default.join(srcDir, "home-page.tsx"), generateHomePage());
469
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, "index.css"), getIndexCss());
470
+ node_fs.default.writeFileSync(node_path.default.join(docsDir, "index.mdx"), `---
471
+ title: Introduction
472
+ ---
473
+
474
+ # External Pages Feature
475
+
476
+ This project demonstrates the \`pages-external\` feature of Boltdocs.
487
477
 
488
- // src/index.ts
489
- var { green, yellow, bold, cyan, magenta, blue, red, dim } = import_picocolors.default;
478
+ Check out [Contact Page](/contact) to see it in action.
479
+
480
+ The source code for that page is located in \`docs/pages-external/index.tsx\`.
481
+ `);
482
+ }
483
+ //#endregion
484
+ //#region src/index.ts
485
+ const { green, yellow, bold, cyan, magenta, blue, red, dim } = picocolors.default;
490
486
  function getPackageManager() {
491
- const userAgent = process.env.npm_config_user_agent;
492
- if (userAgent?.includes("pnpm")) return "pnpm";
493
- if (userAgent?.includes("yarn")) return "yarn";
494
- if (userAgent?.includes("bun")) return "bun";
495
- return "npm";
487
+ const userAgent = process.env.npm_config_user_agent;
488
+ if (userAgent?.includes("pnpm")) return "pnpm";
489
+ if (userAgent?.includes("yarn")) return "yarn";
490
+ if (userAgent?.includes("bun")) return "bun";
491
+ return "npm";
496
492
  }
497
493
  async function run() {
498
- const pkgManager = getPackageManager();
499
- console.log(
500
- blue(
501
- bold(`
494
+ const pkgManager = getPackageManager();
495
+ console.log(blue(bold(`
502
496
  ____ ___ _ _____ ____ ___ ____ ____
503
497
  | __ ) / _ \\| | |_ _| _ \\ / _ \\ / ___/ ___|
504
498
  | _ \\| | | | | | | | | | | | | | | \\___ \\
505
499
  | |_) | |_| | |___ | | | |_| | |_| | |___ ___) |
506
- |____/ \\___/|_____| |_| |____/ \\___/ \\____|____/`)
507
- )
508
- );
509
- console.log(dim(`
510
- v0.0.1 - The modern documentation framework
511
- `));
512
- const response = await (0, import_prompts.default)([
513
- {
514
- type: "text",
515
- name: "projectName",
516
- message: "Project name:",
517
- initial: "my-boltdocs-app"
518
- },
519
- {
520
- type: "select",
521
- name: "template",
522
- message: "Select a project preset:",
523
- choices: [
524
- {
525
- title: cyan("Empty"),
526
- description: "Minimal documentation setup.",
527
- value: "empty"
528
- },
529
- {
530
- title: magenta("Base"),
531
- description: "Hero and custom components.",
532
- value: "base"
533
- },
534
- {
535
- title: yellow("i18n"),
536
- description: "Multi-language support (EN/ES).",
537
- value: "i18n"
538
- }
539
- ],
540
- initial: 1
541
- },
542
- {
543
- type: "confirm",
544
- name: "install",
545
- message: `Install dependencies with ${bold(pkgManager)}?`,
546
- initial: true
547
- }
548
- ]);
549
- if (!response.projectName || !response.template) {
550
- console.log(yellow("\nOperation canceled."));
551
- return;
552
- }
553
- const projectDir = import_node_path4.default.join(process.cwd(), response.projectName);
554
- if (import_node_fs4.default.existsSync(projectDir)) {
555
- console.error(
556
- red(`
557
- Error: Directory "${response.projectName}" already exists.`)
558
- );
559
- process.exit(1);
560
- }
561
- console.log(dim(`
562
- Building your documentation site...
563
- `));
564
- import_node_fs4.default.mkdirSync(projectDir, { recursive: true });
565
- console.log(`${green("\u2714")} Created project directory`);
566
- const configOptions = { homePage: "./src/HomePage.tsx" };
567
- if (response.template === "empty") {
568
- generateEmptyTemplate(projectDir, response.projectName);
569
- } else if (response.template === "i18n") {
570
- configOptions.i18n = true;
571
- generateI18nTemplate(projectDir);
572
- } else {
573
- generateBaseTemplate(projectDir);
574
- }
575
- console.log(`${green("\u2714")} Applied "${response.template}" preset`);
576
- import_node_fs4.default.writeFileSync(
577
- import_node_path4.default.join(projectDir, "package.json"),
578
- JSON.stringify(getPackageJson(response.projectName), null, 2)
579
- );
580
- import_node_fs4.default.writeFileSync(import_node_path4.default.join(projectDir, ".gitignore"), gitignoreContent);
581
- import_node_fs4.default.writeFileSync(import_node_path4.default.join(projectDir, ".npmignore"), gitignoreContent);
582
- import_node_fs4.default.writeFileSync(
583
- import_node_path4.default.join(projectDir, ".markdownlint.yaml"),
584
- markdownlintContent
585
- );
586
- import_node_fs4.default.writeFileSync(
587
- import_node_path4.default.join(projectDir, ".markdownlintignore"),
588
- markdownlintignoreContent
589
- );
590
- import_node_fs4.default.writeFileSync(
591
- import_node_path4.default.join(projectDir, "boltdocs.config.ts"),
592
- getBoltdocsConfig(response.projectName, configOptions)
593
- );
594
- const publicDir = import_node_path4.default.join(projectDir, "public");
595
- import_node_fs4.default.mkdirSync(publicDir, { recursive: true });
596
- import_node_fs4.default.writeFileSync(import_node_path4.default.join(publicDir, "logo-light.svg"), getLogoLight());
597
- import_node_fs4.default.writeFileSync(import_node_path4.default.join(publicDir, "logo-dark.svg"), getLogoDark());
598
- console.log(`${green("\u2714")} Finalized configuration and assets`);
599
- if (response.install) {
600
- console.log(cyan(`
601
- Installing dependencies with ${pkgManager}...
602
- `));
603
- try {
604
- (0, import_node_child_process.execSync)(`${pkgManager} install`, { cwd: projectDir, stdio: "inherit" });
605
- console.log(`
606
- ${green("\u2714")} Dependencies installed successfully`);
607
- } catch (e) {
608
- console.log(
609
- yellow(
610
- `
611
- Could not install dependencies automatically. Please run "${pkgManager} install".`
612
- )
613
- );
614
- }
615
- }
616
- console.log(bold(green("\n\u2728 All set! Your documentation is ready. \u2728\n")));
617
- console.log(`To start developing:`);
618
- console.log(` cd ${response.projectName}`);
619
- if (!response.install) console.log(` ${pkgManager} install`);
620
- console.log(` ${pkgManager} run dev
621
- `);
500
+ |____/ \\___/|_____| |_| |____/ \\___/ \\____|____/`)));
501
+ console.log(dim(`\n v0.0.2 - The modern documentation framework\n`));
502
+ const response = await (0, prompts.default)([
503
+ {
504
+ type: "text",
505
+ name: "projectName",
506
+ message: "Project name:",
507
+ initial: "my-boltdocs-app"
508
+ },
509
+ {
510
+ type: "select",
511
+ name: "template",
512
+ message: "Select a project preset:",
513
+ choices: [
514
+ {
515
+ title: cyan("Empty"),
516
+ description: "Minimal documentation setup.",
517
+ value: "empty"
518
+ },
519
+ {
520
+ title: magenta("Base"),
521
+ description: "Hero and custom components.",
522
+ value: "base"
523
+ },
524
+ {
525
+ title: yellow("i18n"),
526
+ description: "Multi-language support (EN/ES).",
527
+ value: "i18n"
528
+ },
529
+ {
530
+ title: blue("External"),
531
+ description: "Custom routes and external layouts.",
532
+ value: "external"
533
+ }
534
+ ],
535
+ initial: 1
536
+ },
537
+ {
538
+ type: "confirm",
539
+ name: "install",
540
+ message: `Install dependencies with ${bold(pkgManager)}?`,
541
+ initial: true
542
+ }
543
+ ]);
544
+ if (!response.projectName || !response.template) {
545
+ console.log(yellow("\nOperation canceled."));
546
+ return;
547
+ }
548
+ const projectDir = node_path.default.join(process.cwd(), response.projectName);
549
+ if (node_fs.default.existsSync(projectDir)) {
550
+ console.error(red(`\nError: Directory "${response.projectName}" already exists.`));
551
+ process.exit(1);
552
+ }
553
+ console.log(dim(`\nBuilding your documentation site...\n`));
554
+ node_fs.default.mkdirSync(projectDir, { recursive: true });
555
+ console.log(`${green("✔")} Created project directory`);
556
+ const configOptions = { homePage: "./src/home-page.tsx" };
557
+ if (response.template === "empty") generateEmptyTemplate(projectDir, response.projectName);
558
+ else if (response.template === "i18n") {
559
+ configOptions.i18n = true;
560
+ generateI18nTemplate(projectDir, response.projectName);
561
+ } else if (response.template === "external") generateExternalTemplate(projectDir, response.projectName);
562
+ else generateBaseTemplate(projectDir, response.projectName);
563
+ console.log(`${green("✔")} Applied "${response.template}" preset`);
564
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, "package.json"), JSON.stringify(getPackageJson(response.projectName), null, 2));
565
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, ".gitignore"), gitignoreContent);
566
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, ".npmignore"), gitignoreContent);
567
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, ".markdownlint.yaml"), markdownlintContent);
568
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, ".markdownlintignore"), markdownlintignoreContent);
569
+ node_fs.default.writeFileSync(node_path.default.join(projectDir, "boltdocs.config.ts"), getBoltdocsConfig(response.projectName, configOptions));
570
+ const publicDir = node_path.default.join(projectDir, "public");
571
+ node_fs.default.mkdirSync(publicDir, { recursive: true });
572
+ node_fs.default.writeFileSync(node_path.default.join(publicDir, "logo-light.svg"), getLogoLight());
573
+ node_fs.default.writeFileSync(node_path.default.join(publicDir, "logo-dark.svg"), getLogoDark());
574
+ console.log(`${green("")} Finalized configuration and assets`);
575
+ if (response.install) {
576
+ console.log(cyan(`\nInstalling dependencies with ${pkgManager}...\n`));
577
+ try {
578
+ (0, node_child_process.execSync)(`${pkgManager} install`, {
579
+ cwd: projectDir,
580
+ stdio: "inherit"
581
+ });
582
+ console.log(`\n${green("✔")} Dependencies installed successfully`);
583
+ } catch (e) {
584
+ console.log(yellow(`\nCould not install dependencies automatically. Please run "${pkgManager} install".`));
585
+ }
586
+ }
587
+ console.log(bold(green("\n✨ All set! Your documentation is ready. ✨\n")));
588
+ console.log(`To start developing:`);
589
+ console.log(` cd ${response.projectName}`);
590
+ if (!response.install) console.log(` ${pkgManager} install`);
591
+ console.log(` ${pkgManager} run dev\n`);
622
592
  }
623
593
  run().catch(console.error);
594
+ //#endregion