Skip to content

Commit 4565ae1

Browse files
author
Lasim
committed
docs: enhance documentation structure by adding separate sources for development and self-hosted sections; remove root flags from meta.json files; introduce debug script for loading verification
1 parent 9a15afd commit 4565ae1

6 files changed

Lines changed: 157 additions & 49 deletions

File tree

app/[[...slug]]/page.tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { DocsLayout } from 'fumadocs-ui/layouts/docs';
33
import { HomeLayout } from 'fumadocs-ui/layouts/home';
44
import { DocsPage, DocsBody } from 'fumadocs-ui/page';
55
import { notFound } from 'next/navigation';
6-
import { source } from '@/lib/source';
6+
import { source, mainSource, developmentSource, selfHostedSource } from '@/lib/source';
77
import { generatePageMetadata, getCanonicalUrl } from '@/lib/seo-utils';
88
import { getFinalPageTitle } from '@/lib/h1-extractor';
99
import { readFile } from 'fs/promises';
@@ -41,12 +41,25 @@ export default async function Page({
4141
);
4242
}
4343

44+
// Determine which section we're in and get the appropriate page tree
45+
const firstSegment = slug[0];
46+
let pageTree = mainSource.pageTree;
47+
let navTitle = 'DeployStack Docs';
48+
49+
if (firstSegment === 'development') {
50+
pageTree = developmentSource.pageTree;
51+
navTitle = 'Development Docs';
52+
} else if (firstSegment === 'self-hosted') {
53+
pageTree = selfHostedSource.pageTree;
54+
navTitle = 'Self-Hosted Docs';
55+
}
56+
4457
return (
4558
<DocsLayout
4659
{...docsOptions}
47-
tree={source.pageTree}
60+
tree={pageTree}
4861
nav={{
49-
title: 'DeployStack Docs',
62+
title: navTitle,
5063
url: '/',
5164
}}
5265
sidebar={{
@@ -63,18 +76,8 @@ export default async function Page({
6376
}
6477

6578
export async function generateStaticParams() {
66-
const params = source.generateParams();
67-
68-
const result = [
69-
...params,
70-
...docs.docs
71-
.filter((page: any) => page._file.flattenedPath)
72-
.map((page: any) => ({
73-
slug: page._file.flattenedPath.split('/'),
74-
})),
75-
];
76-
77-
return result;
79+
// Simply use the unified source generateParams
80+
return source.generateParams();
7881
}
7982

8083
export async function generateMetadata({

docs/development/meta.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"title": "Development",
33
"description": "Development documentation for DeployStack",
44
"icon": "Code",
5-
"root": true,
65
"pages": [
76
"index",
87
"---Sections---",

docs/meta.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"title": "DeployStack",
33
"description": "Documentation for DeployStack",
44
"icon": "DeployStackLogo",
5-
"root": true,
65
"pages": [
76
"quick-start",
87
"---General---",
@@ -20,9 +19,6 @@
2019
"github-application",
2120
"github-oauth-setup",
2221
"troubleshooting",
23-
"local-setup",
24-
"---Developer Resources---",
25-
"development",
26-
"self-hosted"
22+
"local-setup"
2723
]
2824
}

docs/self-hosted/meta.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"title": "Self Hosted",
33
"description": "Self-hosted DeployStack",
44
"icon": "DeployStackLogo",
5-
"root": true,
65
"pages": [
76
"..."
87
]

lib/debug-source.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Debug script to see what's being loaded
2+
import { docs } from '../.source/index';
3+
4+
const allDocs = docs.docs;
5+
const allMeta = docs.meta;
6+
7+
console.log('=== ALL DOCS ===');
8+
allDocs.forEach((doc: any) => {
9+
console.log('Path:', doc._file.path, 'Flattened:', doc._file.flattenedPath);
10+
});
11+
12+
console.log('\n=== DEVELOPMENT DOCS ===');
13+
const developmentDocs = allDocs.filter((doc: any) =>
14+
doc._file.path.startsWith('development/')
15+
);
16+
developmentDocs.forEach((doc: any) => {
17+
console.log('Path:', doc._file.path, 'Flattened:', doc._file.flattenedPath);
18+
});
19+
20+
console.log('\n=== SELF-HOSTED DOCS ===');
21+
const selfHostedDocs = allDocs.filter((doc: any) =>
22+
doc._file.path.startsWith('self-hosted/')
23+
);
24+
selfHostedDocs.forEach((doc: any) => {
25+
console.log('Path:', doc._file.path, 'Flattened:', doc._file.flattenedPath);
26+
});

lib/source.ts

Lines changed: 112 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,128 @@ import { loader } from 'fumadocs-core/source';
77
import { icons } from 'lucide-react';
88
import { createElement } from 'react';
99
import { DeployStackLogo } from './components/DeployStackLogo';
10+
import { createMDXSource } from 'fumadocs-mdx';
11+
import type { PageTree } from 'fumadocs-core/server';
1012

11-
export const source = loader({
12-
// Base URL for the documentation pages.
13-
// Since we've moved docs to the root level, baseUrl should be '/'
14-
// This means docs/index.mdx will be at / and other docs at their direct paths
15-
baseUrl: '/',
16-
// The source of the documents, converted to Fumadocs format.
17-
source: docs.toFumadocsSource(),
18-
19-
// Icon handler to support both lucide-react icons and custom icons
20-
icon(icon) {
21-
if (!icon) {
22-
return; // No icon specified
23-
}
13+
// Helper function for icon handling
14+
function createIconHandler() {
15+
return (icon?: string) => {
16+
if (!icon) return;
2417

25-
// Handle custom icons
2618
if (icon === 'DeployStackLogo') {
2719
return createElement(DeployStackLogo);
2820
}
2921

30-
// Handle lucide-react icons
3122
if (icon in icons) {
3223
return createElement(icons[icon as keyof typeof icons]);
3324
}
3425

35-
// If icon not found, return undefined
3626
return undefined;
37-
},
27+
};
28+
}
3829

39-
// Customize page tree to support custom sidebar titles
40-
pageTree: {
41-
attachFile(node, file) {
42-
// If the file has a custom sidebar title, use it instead of the title
43-
if (file?.data && 'sidebar' in file.data && file.data.sidebar) {
44-
node.name = file.data.sidebar as string;
45-
}
46-
return node;
47-
},
48-
},
30+
// Filter docs into separate sections
31+
const allDocs = docs.docs;
32+
const allMeta = docs.meta;
33+
34+
// Main docs (root level - exclude development and self-hosted)
35+
const mainDocs = allDocs.filter((doc: any) => {
36+
const path = doc._file.path;
37+
return !path.startsWith('development/') && !path.startsWith('self-hosted/');
38+
});
39+
40+
const mainMeta = allMeta.filter((meta: any) => {
41+
const path = meta._file.path;
42+
return !path.startsWith('development/') && !path.startsWith('self-hosted/');
43+
});
44+
45+
// Development docs - keep the full path
46+
const developmentDocs = allDocs.filter((doc: any) =>
47+
doc._file.path.startsWith('development/')
48+
);
49+
50+
const developmentMeta = allMeta.filter((meta: any) =>
51+
meta._file.path.startsWith('development/')
52+
);
53+
54+
// Self-hosted docs - keep the full path
55+
const selfHostedDocs = allDocs.filter((doc: any) =>
56+
doc._file.path.startsWith('self-hosted/')
57+
);
58+
59+
const selfHostedMeta = allMeta.filter((meta: any) =>
60+
meta._file.path.startsWith('self-hosted/')
61+
);
62+
63+
// Create separate sources for each section
64+
export const mainSource = loader({
65+
baseUrl: '/',
66+
source: createMDXSource(mainDocs, mainMeta),
67+
icon: createIconHandler(),
68+
});
69+
70+
// For development and self-hosted, we keep the full path structure
71+
export const developmentSource = loader({
72+
baseUrl: '/', // Changed from '/development' to '/'
73+
source: createMDXSource(developmentDocs, developmentMeta),
74+
icon: createIconHandler(),
4975
});
76+
77+
export const selfHostedSource = loader({
78+
baseUrl: '/', // Changed from '/self-hosted' to '/'
79+
source: createMDXSource(selfHostedDocs, selfHostedMeta),
80+
icon: createIconHandler(),
81+
});
82+
83+
// Unified source for backward compatibility and dynamic usage
84+
export const source = {
85+
getPage(slug?: string[], locale?: string) {
86+
if (!slug || slug.length === 0) return mainSource.getPage(slug, locale);
87+
88+
const firstSegment = slug[0];
89+
90+
// For development section, use the full slug path
91+
if (firstSegment === 'development') {
92+
return developmentSource.getPage(slug, locale);
93+
}
94+
95+
// For self-hosted section, use the full slug path
96+
if (firstSegment === 'self-hosted') {
97+
return selfHostedSource.getPage(slug, locale);
98+
}
99+
100+
// For main docs, use as-is
101+
return mainSource.getPage(slug, locale);
102+
},
103+
104+
getPages(locale?: string) {
105+
return [
106+
...mainSource.getPages(locale),
107+
...developmentSource.getPages(locale),
108+
...selfHostedSource.getPages(locale),
109+
];
110+
},
111+
112+
generateParams() {
113+
// Get params from all sources
114+
const mainParams = mainSource.generateParams();
115+
const devParams = developmentSource.generateParams();
116+
const selfParams = selfHostedSource.generateParams();
117+
118+
return [
119+
...mainParams,
120+
...devParams,
121+
...selfParams,
122+
];
123+
},
124+
125+
// Get appropriate page tree based on current path
126+
getPageTree(path?: string) {
127+
if (path?.startsWith('/development')) return developmentSource.pageTree;
128+
if (path?.startsWith('/self-hosted')) return selfHostedSource.pageTree;
129+
return mainSource.pageTree;
130+
},
131+
132+
// Default page tree for compatibility
133+
pageTree: mainSource.pageTree,
134+
};

0 commit comments

Comments
 (0)