@brainfish-ai/devdoc 0.1.25 → 0.1.27

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.
Files changed (44) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/commands/create.d.ts +3 -0
  3. package/dist/cli/commands/create.js +180 -15
  4. package/dist/cli/commands/dev.js +41 -77
  5. package/package.json +6 -6
  6. package/renderer/app/api/docs/route.ts +6 -2
  7. package/renderer/app/icon.svg +4 -0
  8. package/renderer/components/docs-viewer/content/doc-page.tsx +17 -2
  9. package/renderer/components/docs-viewer/content/not-found-page.tsx +330 -0
  10. package/renderer/components/docs-viewer/index.tsx +56 -4
  11. package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +20 -0
  12. package/renderer/app/favicon.ico +0 -0
  13. package/templates/basic/README.md +0 -139
  14. package/templates/basic/assets/favicon.svg +0 -4
  15. package/templates/basic/assets/logo.svg +0 -9
  16. package/templates/basic/docs.json +0 -47
  17. package/templates/basic/guides/configuration.mdx +0 -149
  18. package/templates/basic/guides/overview.mdx +0 -96
  19. package/templates/basic/index.mdx +0 -39
  20. package/templates/basic/package.json +0 -14
  21. package/templates/basic/quickstart.mdx +0 -92
  22. package/templates/basic/vercel.json +0 -6
  23. package/templates/graphql/README.md +0 -139
  24. package/templates/graphql/api-reference/schema.graphql +0 -305
  25. package/templates/graphql/assets/favicon.svg +0 -4
  26. package/templates/graphql/assets/logo.svg +0 -9
  27. package/templates/graphql/docs.json +0 -54
  28. package/templates/graphql/guides/configuration.mdx +0 -149
  29. package/templates/graphql/guides/overview.mdx +0 -96
  30. package/templates/graphql/index.mdx +0 -39
  31. package/templates/graphql/package.json +0 -14
  32. package/templates/graphql/quickstart.mdx +0 -92
  33. package/templates/graphql/vercel.json +0 -6
  34. package/templates/openapi/README.md +0 -139
  35. package/templates/openapi/api-reference/openapi.json +0 -419
  36. package/templates/openapi/assets/favicon.svg +0 -4
  37. package/templates/openapi/assets/logo.svg +0 -9
  38. package/templates/openapi/docs.json +0 -61
  39. package/templates/openapi/guides/configuration.mdx +0 -149
  40. package/templates/openapi/guides/overview.mdx +0 -96
  41. package/templates/openapi/index.mdx +0 -39
  42. package/templates/openapi/package.json +0 -14
  43. package/templates/openapi/quickstart.mdx +0 -92
  44. package/templates/openapi/vercel.json +0 -6
@@ -0,0 +1,330 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useState, useCallback, useRef } from 'react'
4
+ import { FileX, House, ArrowLeft, MagnifyingGlass, Spinner } from '@phosphor-icons/react'
5
+ import { Button } from '@/components/ui/button'
6
+ import { useDocsNavigation } from '@/lib/docs-navigation-context'
7
+ import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'
8
+ import { useCodeCopy } from '@/hooks/use-code-copy'
9
+
10
+ // Import MDX components for custom 404 pages
11
+ import {
12
+ Note,
13
+ Warning,
14
+ Info,
15
+ Tip,
16
+ Check,
17
+ Error as ErrorCallout,
18
+ Callout,
19
+ Card,
20
+ CardGroup,
21
+ Accordion,
22
+ AccordionGroup,
23
+ Steps,
24
+ Step,
25
+ Tabs,
26
+ Tab,
27
+ CodeGroup,
28
+ Frame,
29
+ Columns,
30
+ Snippet,
31
+ Latex,
32
+ ParamField,
33
+ ResponseField,
34
+ Expandable,
35
+ Iframe,
36
+ Video,
37
+ Loom,
38
+ Image,
39
+ Screenshot,
40
+ Logo,
41
+ Icon,
42
+ Highlight,
43
+ Marker,
44
+ Underline,
45
+ Badge,
46
+ Mermaid,
47
+ PDF,
48
+ Audio,
49
+ Download,
50
+ Hero,
51
+ Pre,
52
+ Tagline,
53
+ Headline,
54
+ Description,
55
+ CommandBox,
56
+ Section,
57
+ Center,
58
+ FeatureGrid,
59
+ FeatureItem,
60
+ ButtonLink,
61
+ Spacer,
62
+ Divider,
63
+ } from '../../docs/mdx/index'
64
+
65
+ // MDX components mapping for custom 404 pages
66
+ const mdxComponents = {
67
+ Note,
68
+ Warning,
69
+ Info,
70
+ Tip,
71
+ Check,
72
+ Error: ErrorCallout,
73
+ Callout,
74
+ Card,
75
+ CardGroup,
76
+ Accordion,
77
+ AccordionGroup,
78
+ Steps,
79
+ Step,
80
+ Tabs,
81
+ Tab,
82
+ CodeGroup,
83
+ Frame,
84
+ Columns,
85
+ Snippet,
86
+ Latex,
87
+ ParamField,
88
+ ResponseField,
89
+ Expandable,
90
+ Iframe,
91
+ Video,
92
+ Loom,
93
+ Image,
94
+ Screenshot,
95
+ Logo,
96
+ Icon,
97
+ Highlight,
98
+ Marker,
99
+ Underline,
100
+ Badge,
101
+ Mermaid,
102
+ PDF,
103
+ Audio,
104
+ Download,
105
+ Hero,
106
+ Pre,
107
+ Tagline,
108
+ Headline,
109
+ Description,
110
+ CommandBox,
111
+ Section,
112
+ Center,
113
+ FeatureGrid,
114
+ FeatureItem,
115
+ ButtonLink,
116
+ Spacer,
117
+ Divider,
118
+ }
119
+
120
+ interface NotFoundPageProps {
121
+ slug?: string
122
+ onGoBack?: () => void
123
+ onSearch?: () => void
124
+ }
125
+
126
+ interface Custom404Data {
127
+ frontmatter: {
128
+ title?: string
129
+ description?: string
130
+ mode?: 'default' | 'wide' | 'custom'
131
+ hideHeader?: boolean
132
+ background?: string
133
+ }
134
+ mdxSource: MDXRemoteSerializeResult
135
+ }
136
+
137
+ export function NotFoundPage({ slug, onGoBack, onSearch }: NotFoundPageProps) {
138
+ const docsNav = useDocsNavigation()
139
+ const [customPage, setCustomPage] = useState<Custom404Data | null>(null)
140
+ const [loading, setLoading] = useState(true)
141
+ const contentRef = useRef<HTMLDivElement>(null)
142
+
143
+ // Add copy buttons to code blocks after content loads
144
+ useCodeCopy(contentRef, [customPage])
145
+
146
+ // Try to load custom 404.mdx page
147
+ useEffect(() => {
148
+ async function loadCustom404() {
149
+ try {
150
+ const response = await fetch('/api/docs?slug=404&is404=true')
151
+ if (response.ok) {
152
+ const data = await response.json()
153
+ setCustomPage(data)
154
+ }
155
+ } catch {
156
+ // No custom 404 page, use default
157
+ } finally {
158
+ setLoading(false)
159
+ }
160
+ }
161
+ loadCustom404()
162
+ }, [])
163
+
164
+ const handleGoHome = useCallback(() => {
165
+ // Navigate to the first page of the current tab or just switch to first tab
166
+ if (docsNav?.switchToTab) {
167
+ window.location.hash = ''
168
+ window.location.reload()
169
+ } else {
170
+ window.location.hash = ''
171
+ }
172
+ }, [docsNav])
173
+
174
+ const handleGoBack = useCallback(() => {
175
+ if (onGoBack) {
176
+ onGoBack()
177
+ } else {
178
+ window.history.back()
179
+ }
180
+ }, [onGoBack])
181
+
182
+ // Show loading state briefly while checking for custom 404
183
+ if (loading) {
184
+ return (
185
+ <div className="docs-page docs-page-not-found w-full min-h-[200px]">
186
+ <div className="flex items-center justify-center py-12">
187
+ <Spinner className="h-6 w-6 animate-spin text-muted-foreground" />
188
+ </div>
189
+ </div>
190
+ )
191
+ }
192
+
193
+ // Render custom 404 page if available
194
+ if (customPage) {
195
+ const { mode = 'default', hideHeader, background } = customPage.frontmatter
196
+ const isCustomMode = mode === 'custom'
197
+ const showHeader = !hideHeader && !isCustomMode
198
+
199
+ // Custom mode: Full-width layout
200
+ if (isCustomMode) {
201
+ return (
202
+ <div
203
+ ref={contentRef}
204
+ className="docs-page docs-page-not-found docs-content w-full min-h-full"
205
+ style={{ background: background || 'var(--background)' }}
206
+ >
207
+ <div className="docs-custom-content [&>*]:w-full">
208
+ <MDXRemote {...customPage.mdxSource} components={mdxComponents} />
209
+ </div>
210
+ </div>
211
+ )
212
+ }
213
+
214
+ // Default mode with optional header
215
+ const containerClass = mode === 'wide' ? 'max-w-6xl' : 'max-w-4xl'
216
+
217
+ return (
218
+ <div ref={contentRef} className={`docs-page docs-page-not-found docs-content ${containerClass} mx-auto px-4 py-6 sm:px-8 sm:py-8`}>
219
+ {showHeader && customPage.frontmatter.title && (
220
+ <div className="docs-page-header mb-6">
221
+ <h1 className="docs-content-title text-2xl sm:text-3xl font-bold mb-2 text-foreground">
222
+ {customPage.frontmatter.title}
223
+ </h1>
224
+ {customPage.frontmatter.description && (
225
+ <p className="docs-content-description text-lg text-muted-foreground">
226
+ {customPage.frontmatter.description}
227
+ </p>
228
+ )}
229
+ </div>
230
+ )}
231
+ <div className="docs-prose prose prose-sm max-w-none prose-headings:text-foreground prose-p:text-muted-foreground prose-strong:text-foreground">
232
+ <MDXRemote {...customPage.mdxSource} components={mdxComponents} />
233
+ </div>
234
+
235
+ {/* Always show navigation actions for custom 404 */}
236
+ <div className="mt-8 pt-6 border-t border-border">
237
+ <div className="flex flex-col sm:flex-row items-center justify-center gap-3">
238
+ <Button variant="outline" size="sm" onClick={handleGoBack} className="gap-2 min-w-[120px]">
239
+ <ArrowLeft className="w-4 h-4" />
240
+ Go back
241
+ </Button>
242
+ <Button variant="default" size="sm" onClick={handleGoHome} className="gap-2 min-w-[120px]">
243
+ <House className="w-4 h-4" />
244
+ Go home
245
+ </Button>
246
+ {onSearch && (
247
+ <Button variant="outline" size="sm" onClick={onSearch} className="gap-2 min-w-[120px]">
248
+ <MagnifyingGlass className="w-4 h-4" />
249
+ Search
250
+ </Button>
251
+ )}
252
+ </div>
253
+ </div>
254
+ </div>
255
+ )
256
+ }
257
+
258
+ // Default 404 page
259
+ return (
260
+ <div className="docs-page docs-page-not-found w-full min-h-[calc(100vh-200px)] flex items-center justify-center">
261
+ <div className="text-center px-4 py-12 max-w-md mx-auto">
262
+ {/* Icon */}
263
+ <div className="mb-6">
264
+ <div className="inline-flex items-center justify-center w-20 h-20 rounded-full bg-muted/50 text-muted-foreground">
265
+ <FileX className="w-10 h-10" weight="light" />
266
+ </div>
267
+ </div>
268
+
269
+ {/* Title */}
270
+ <h1 className="text-2xl font-semibold text-foreground mb-2">
271
+ Page not found
272
+ </h1>
273
+
274
+ {/* Description */}
275
+ <p className="text-muted-foreground mb-2">
276
+ The page you&apos;re looking for doesn&apos;t exist or has been moved.
277
+ </p>
278
+
279
+ {/* Show the slug that wasn't found */}
280
+ {slug && (
281
+ <p className="text-sm text-muted-foreground/70 mb-6 font-mono bg-muted/30 px-3 py-1.5 rounded-md inline-block">
282
+ /{slug}
283
+ </p>
284
+ )}
285
+
286
+ {!slug && <div className="mb-6" />}
287
+
288
+ {/* Actions */}
289
+ <div className="flex flex-col sm:flex-row items-center justify-center gap-3">
290
+ <Button
291
+ variant="outline"
292
+ size="sm"
293
+ onClick={handleGoBack}
294
+ className="gap-2 min-w-[120px]"
295
+ >
296
+ <ArrowLeft className="w-4 h-4" />
297
+ Go back
298
+ </Button>
299
+
300
+ <Button
301
+ variant="default"
302
+ size="sm"
303
+ onClick={handleGoHome}
304
+ className="gap-2 min-w-[120px]"
305
+ >
306
+ <House className="w-4 h-4" />
307
+ Go home
308
+ </Button>
309
+
310
+ {onSearch && (
311
+ <Button
312
+ variant="outline"
313
+ size="sm"
314
+ onClick={onSearch}
315
+ className="gap-2 min-w-[120px]"
316
+ >
317
+ <MagnifyingGlass className="w-4 h-4" />
318
+ Search
319
+ </Button>
320
+ )}
321
+ </div>
322
+
323
+ {/* Help text */}
324
+ <p className="text-xs text-muted-foreground/60 mt-8">
325
+ If you believe this is an error, please check the URL or contact the documentation maintainer.
326
+ </p>
327
+ </div>
328
+ </div>
329
+ )
330
+ }
@@ -4,6 +4,7 @@ import { useEffect, useState, useCallback, useRef } from 'react'
4
4
  import { Spinner } from '@phosphor-icons/react'
5
5
  import type { BrainfishCollection, BrainfishRESTRequest, BrainfishDocGroup } from '@/lib/api-docs/types'
6
6
  import { DocsSidebar } from './sidebar'
7
+ import { NotFoundPage } from './content/not-found-page'
7
8
  import { ApiPlayground } from './playground'
8
9
  import type { DebugContext } from './playground/response-viewer'
9
10
  import { RightSidebar } from './sidebar/right-sidebar'
@@ -391,6 +392,7 @@ function DocsContent() {
391
392
  const [isVersionLoading, setIsVersionLoading] = useState(false) // For version switch only
392
393
  const [error, setError] = useState<string | null>(null)
393
394
  const [showAuthModal, setShowAuthModal] = useState(false)
395
+ const [notFoundSlug, setNotFoundSlug] = useState<string | null>(null) // Track 404 for invalid URLs
394
396
 
395
397
  // Prefill context for agent
396
398
  const { setPrefill } = usePlaygroundPrefill()
@@ -481,13 +483,16 @@ function DocsContent() {
481
483
  setSelectedRequest(request)
482
484
  setSelectedDocSection(null)
483
485
  setSelectedDocPage(null)
486
+ setNotFoundSlug(null)
484
487
  } else {
485
- // Endpoint not found - clear selection
488
+ // Endpoint not found - show 404 page
486
489
  setSelectedRequest(null)
487
490
  setSelectedDocSection(null)
488
491
  setSelectedDocPage(null)
492
+ setNotFoundSlug(`endpoint/${actualId}`)
489
493
  }
490
494
  } else if (actualType === 'page' && actualId) {
495
+ setNotFoundSlug(null) // Clear not found state - DocPage handles its own 404
491
496
  setSelectedDocPage(actualId)
492
497
  setSelectedRequest(null)
493
498
  setSelectedDocSection(null)
@@ -515,6 +520,7 @@ function DocsContent() {
515
520
  setSelectedRequest(request)
516
521
  setSelectedDocSection(null)
517
522
  setSelectedDocPage(null)
523
+ setNotFoundSlug(null) // Clear 404 state when selecting an endpoint
518
524
  updateUrlHash(`endpoint/${request.id}`)
519
525
  // Reset tab navigation so the new endpoint can determine its default tab
520
526
  resetNavigation()
@@ -527,6 +533,7 @@ function DocsContent() {
527
533
  setSelectedDocSection(isIntro ? null : headingId)
528
534
  setSelectedRequest(null)
529
535
  setSelectedDocPage(null)
536
+ setNotFoundSlug(null) // Clear 404 state
530
537
 
531
538
  updateUrlHash(isIntro ? '' : `doc/${headingId}`)
532
539
 
@@ -599,6 +606,7 @@ function DocsContent() {
599
606
  setSelectedDocPage(pageSlug)
600
607
  setSelectedRequest(null)
601
608
  setSelectedDocSection(null)
609
+ setNotFoundSlug(null) // Clear 404 state
602
610
  updateUrlHash(`page/${pageSlug}`, targetTab)
603
611
  switchToDocs()
604
612
 
@@ -1162,6 +1170,7 @@ function DocsContent() {
1162
1170
  selectedApiVersion={selectedApiVersion}
1163
1171
  handleApiVersionChange={handleApiVersionChange}
1164
1172
  isVersionLoading={isVersionLoading}
1173
+ notFoundSlug={notFoundSlug}
1165
1174
  />
1166
1175
  </NavigationProvider>
1167
1176
  )
@@ -1193,6 +1202,7 @@ interface DocsWithModeProps {
1193
1202
  selectedApiVersion: string | null
1194
1203
  handleApiVersionChange: (version: string) => void
1195
1204
  isVersionLoading: boolean
1205
+ notFoundSlug: string | null
1196
1206
  }
1197
1207
 
1198
1208
  // Mode toggle tabs - switches between Docs, API Client, and Notes
@@ -1268,6 +1278,7 @@ function DocsWithMode({
1268
1278
  selectedApiVersion,
1269
1279
  handleApiVersionChange,
1270
1280
  isVersionLoading,
1281
+ notFoundSlug,
1271
1282
  }: DocsWithModeProps) {
1272
1283
  const { mode, switchToDocs } = useModeContext()
1273
1284
  const { setTheme } = useTheme()
@@ -1340,6 +1351,7 @@ function DocsWithMode({
1340
1351
  if (!showGraphQL || !schemaPath) {
1341
1352
  setGraphqlOperations([])
1342
1353
  setGraphqlCollection(null)
1354
+ setSelectedGraphQLOperation(null) // Clear selection when leaving GraphQL tab
1343
1355
  return
1344
1356
  }
1345
1357
 
@@ -1364,6 +1376,44 @@ function DocsWithMode({
1364
1376
  loadGraphQLSchema()
1365
1377
  }, [showGraphQL, schemaPath, schemaEndpoint])
1366
1378
 
1379
+ // Auto-select GraphQL operation from URL hash or default to first operation
1380
+ useEffect(() => {
1381
+ if (!showGraphQL || graphqlOperations.length === 0) {
1382
+ return
1383
+ }
1384
+
1385
+ // Check if there's a selection in the URL hash first
1386
+ const hash = window.location.hash.slice(1) // Remove #
1387
+ if (hash) {
1388
+ const parts = hash.split('/')
1389
+ const hashType = parts[1]
1390
+ const hashId = parts.slice(2).join('/')
1391
+
1392
+ if (hashType === 'endpoint' && hashId) {
1393
+ // Try to find and select the operation from the URL hash
1394
+ const operation = graphqlOperations.find(op => op.id === hashId)
1395
+ if (operation) {
1396
+ setSelectedGraphQLOperation(operation)
1397
+ return
1398
+ }
1399
+ }
1400
+ }
1401
+
1402
+ // If already have a selection, don't override it
1403
+ if (selectedGraphQLOperation) {
1404
+ return
1405
+ }
1406
+
1407
+ // Check if there are doc groups for this tab first
1408
+ const hasGroups = hasDocGroupsForTab(collection?.docGroups, activeTab)
1409
+ if (!hasGroups) {
1410
+ // No doc groups - auto-select first GraphQL operation
1411
+ const firstOperation = graphqlOperations[0]
1412
+ setSelectedGraphQLOperation(firstOperation)
1413
+ window.history.pushState(null, '', `#${activeTab}/endpoint/${firstOperation.id}`)
1414
+ }
1415
+ }, [showGraphQL, graphqlOperations, selectedGraphQLOperation, activeTab, collection?.docGroups])
1416
+
1367
1417
  // Handle GraphQL operation selection from sidebar
1368
1418
  const handleSelectGraphQLOperation = useCallback((request: BrainfishRESTRequest) => {
1369
1419
  // Find the matching GraphQL operation
@@ -1500,10 +1550,10 @@ function DocsWithMode({
1500
1550
  ref={contentRef}
1501
1551
  className={cn(
1502
1552
  "docs-content-area flex-1 bg-background min-w-0",
1503
- (showChangelog || showGraphQL) ? "overflow-hidden flex flex-col" : "overflow-y-auto scroll-smooth"
1553
+ (showChangelog || (showGraphQL && selectedGraphQLOperation)) ? "overflow-hidden flex flex-col" : "overflow-y-auto scroll-smooth"
1504
1554
  )}
1505
1555
  >
1506
- {showGraphQL ? (
1556
+ {showGraphQL && selectedGraphQLOperation ? (
1507
1557
  <div className="flex-1 flex flex-col h-full">
1508
1558
  <GraphQLPlayground
1509
1559
  endpoint={activeGraphQLSchemas[0]?.endpoint || ''}
@@ -1523,7 +1573,9 @@ function DocsWithMode({
1523
1573
  ) : selectedRequest ? (
1524
1574
  <RequestDetails request={selectedRequest} />
1525
1575
  ) : selectedDocPage ? (
1526
- <DocPage slug={selectedDocPage} />
1576
+ <DocPage slug={selectedDocPage} onSearch={openSearch} />
1577
+ ) : notFoundSlug ? (
1578
+ <NotFoundPage slug={notFoundSlug} onSearch={openSearch} />
1527
1579
  ) : (
1528
1580
  <div className="flex-1 flex items-center justify-center bg-background">
1529
1581
  <div className="text-center text-muted-foreground">
@@ -77,6 +77,26 @@ export function CollectionTree({
77
77
  }
78
78
  return expanded
79
79
  })
80
+
81
+ // Re-expand all folders when collection folders change (e.g., tab switch)
82
+ // This ensures folders are expanded when switching between tabs with different folder sets
83
+ const folderIds = useMemo(() =>
84
+ collection.folders.map(f => f.id).sort().join(','),
85
+ [collection.folders]
86
+ )
87
+
88
+ useEffect(() => {
89
+ if (level === 0 && collection.folders.length > 0) {
90
+ setExpandedFolders(prev => {
91
+ const newExpanded = new Set(prev)
92
+ // Add all current folder IDs to expanded set
93
+ collection.folders.forEach((folder) => {
94
+ newExpanded.add(folder.id)
95
+ })
96
+ return newExpanded
97
+ })
98
+ }
99
+ }, [folderIds, level, collection.folders])
80
100
 
81
101
  // Auto-expand folder when selectedRequest changes (e.g., via agent navigation)
82
102
  useEffect(() => {
Binary file
@@ -1,139 +0,0 @@
1
- # My Documentation
2
-
3
- Documentation site built with [DevDoc](https://github.com/brainfish-ai/devdoc).
4
-
5
- [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/brainfish-ai/devdoc-starter)
6
-
7
- ## Quick Start
8
-
9
- ### Prerequisites
10
-
11
- - [Node.js](https://nodejs.org/) 18.0 or later
12
- - npm, yarn, or pnpm
13
-
14
- ### Installation
15
-
16
- 1. **Clone this repository**
17
-
18
- ```bash
19
- git clone https://github.com/your-username/your-docs.git
20
- cd your-docs
21
- ```
22
-
23
- Or use the GitHub template button above.
24
-
25
- 2. **Install dependencies**
26
-
27
- ```bash
28
- npm install
29
- ```
30
-
31
- 3. **Start the development server**
32
-
33
- ```bash
34
- npm run dev
35
- ```
36
-
37
- 4. **Open your browser**
38
-
39
- Visit [http://localhost:3000](http://localhost:3000) to see your docs.
40
-
41
- ## Project Structure
42
-
43
- ```
44
- .
45
- ├── docs.json # Site configuration
46
- ├── index.mdx # Homepage
47
- ├── quickstart.mdx # Quickstart guide
48
- ├── guides/
49
- │ ├── overview.mdx # Overview page
50
- │ └── configuration.mdx # Configuration guide
51
- ├── public/
52
- │ ├── logo.svg # Site logo
53
- │ └── favicon.svg # Favicon
54
- ├── package.json
55
- ├── vercel.json # Vercel deployment config
56
- └── README.md
57
- ```
58
-
59
- ## Configuration
60
-
61
- Edit `docs.json` to customize your site:
62
-
63
- ```json
64
- {
65
- "name": "My Documentation",
66
- "logo": "/logo.svg",
67
- "navigation": {
68
- "tabs": [
69
- {
70
- "tab": "Documentation",
71
- "type": "docs",
72
- "groups": [
73
- {
74
- "group": "Getting Started",
75
- "pages": ["index", "quickstart"]
76
- }
77
- ]
78
- }
79
- ]
80
- }
81
- }
82
- ```
83
-
84
- ## Writing Content
85
-
86
- Create `.mdx` files with frontmatter:
87
-
88
- ```mdx
89
- ---
90
- title: Page Title
91
- description: Page description for SEO
92
- ---
93
-
94
- # Your Content Here
95
-
96
- Write Markdown with React components.
97
-
98
- <Note>
99
- Use components like Note, Card, Steps, and more.
100
- </Note>
101
- ```
102
-
103
- ## Available Commands
104
-
105
- | Command | Description |
106
- |---------|-------------|
107
- | `npm run dev` | Start development server |
108
- | `npm run build` | Build for production |
109
- | `npm run start` | Start production server |
110
- | `npm run check` | Validate configuration |
111
-
112
- ## Deployment
113
-
114
- ### Vercel (Recommended)
115
-
116
- Click the "Deploy with Vercel" button above, or:
117
-
118
- 1. Push your code to GitHub
119
- 2. Import the repository in [Vercel](https://vercel.com)
120
- 3. Deploy!
121
-
122
- ### Other Platforms
123
-
124
- ```bash
125
- # Build the site
126
- npm run build
127
-
128
- # Output is in the dist/ directory
129
- ```
130
-
131
- ## Learn More
132
-
133
- - [DevDoc Documentation](https://devdoc.sh/docs)
134
- - [MDX Documentation](https://mdxjs.com/)
135
- - [Vercel Documentation](https://vercel.com/docs)
136
-
137
- ## License
138
-
139
- MIT
@@ -1,4 +0,0 @@
1
- <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <rect width="32" height="32" rx="8" fill="#10b981"/>
3
- <path d="M8 16L14 22L24 10" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
4
- </svg>