Skip to content

Commit 6555fbb

Browse files
author
Lasim
committed
feat: enhance documentation structure and metadata extraction for improved navigation and title accuracy
1 parent f8ce085 commit 6555fbb

9 files changed

Lines changed: 200 additions & 15 deletions

File tree

.source/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// @ts-nocheck -- skip type checking
2-
import * as docs_2 from "../docs/docker-to-iac/index.mdx?collection=docs&hash=1749400994400"
3-
import * as docs_1 from "../docs/deploystack/index.mdx?collection=docs&hash=1749400994400"
4-
import * as docs_0 from "../docs/index.mdx?collection=docs&hash=1749400994400"
2+
import * as docs_3 from "../docs/docker-to-iac/limitations.mdx?collection=docs&hash=1749491540000"
3+
import * as docs_2 from "../docs/docker-to-iac/index.mdx?collection=docs&hash=1749491540000"
4+
import * as docs_1 from "../docs/deploystack/index.mdx?collection=docs&hash=1749491540000"
5+
import * as docs_0 from "../docs/index.mdx?collection=docs&hash=1749491540000"
56
import { _runtime } from "fumadocs-mdx"
67
import * as _source from "../source.config"
7-
export const docs = _runtime.docs<typeof _source.docs>([{ info: {"path":"index.mdx","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/index.mdx"}, data: docs_0 }, { info: {"path":"deploystack/index.mdx","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/deploystack/index.mdx"}, data: docs_1 }, { info: {"path":"docker-to-iac/index.mdx","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/docker-to-iac/index.mdx"}, data: docs_2 }], [{"info":{"path":"deploystack/meta.json","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/deploystack/meta.json"},"data":{"title":"DeployStack","description":"Documentation for DeployStack","root":true,"icon":"DeployStackLogo"}}, {"info":{"path":"docker-to-iac/meta.json","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/docker-to-iac/meta.json"},"data":{"title":"docker-to-iac","description":"docker-to-iac module","root":true,"icon":"Container"}}])
8+
export const docs = _runtime.docs<typeof _source.docs>([{ info: {"path":"index.mdx","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/index.mdx"}, data: docs_0 }, { info: {"path":"deploystack/index.mdx","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/deploystack/index.mdx"}, data: docs_1 }, { info: {"path":"docker-to-iac/index.mdx","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/docker-to-iac/index.mdx"}, data: docs_2 }, { info: {"path":"docker-to-iac/limitations.mdx","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/docker-to-iac/limitations.mdx"}, data: docs_3 }], [{"info":{"path":"deploystack/meta.json","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/deploystack/meta.json"},"data":{"title":"DeployStack","description":"Documentation for DeployStack","root":true,"icon":"DeployStackLogo"}}, {"info":{"path":"docker-to-iac/meta.json","absolutePath":"/Volumes/T9_1/Git/deploy.my/documentation/docs/docker-to-iac/meta.json"},"data":{"title":"docker-to-iac","description":"docker-to-iac module","root":true,"icon":"Container"}}])

.source/source.config.mjs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
// source.config.ts
2-
import { defineDocs } from "fumadocs-mdx/config";
2+
import { defineDocs, frontmatterSchema } from "fumadocs-mdx/config";
3+
import { z } from "zod";
34
var docs = defineDocs({
45
// Directory of documents, relative to the project root.
56
// We are using the existing 'docs' folder.
6-
dir: "docs"
7+
dir: "docs",
8+
docs: {
9+
schema: frontmatterSchema.extend({
10+
sidebar: z.string().optional()
11+
})
12+
}
713
});
814
export {
915
docs

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { notFound } from 'next/navigation';
44
import { source } from '@/lib/source';
55
import { generatePageMetadata, getCanonicalUrl } from '@/lib/seo-utils';
66
import { CustomNavbar } from '@/lib/components/CustomNavbar';
7+
import { getFinalPageTitle } from '@/lib/h1-extractor';
8+
import { readFile } from 'fs/promises';
79

810
export default async function Page({
911
params,
@@ -23,7 +25,6 @@ export default async function Page({
2325
<DocsPage toc={page.data.toc} full={page.data.full}>
2426
<CustomNavbar />
2527
<DocsBody>
26-
<h1>{page.data.title}</h1>
2728
<MDX />
2829
</DocsBody>
2930
</DocsPage>
@@ -49,8 +50,22 @@ export async function generateMetadata({
4950
const slugString = slug ? slug.join('/') : '';
5051
const url = getCanonicalUrl(slugString);
5152

53+
// Read the raw MDX file to extract H1 heading
54+
let finalTitle = page.data.title;
55+
try {
56+
// Get the absolute path from the page info
57+
const filePath = page.file.path;
58+
const absolutePath = `/Volumes/T9_1/Git/deploy.my/documentation/docs/${filePath}`;
59+
const rawContent = await readFile(absolutePath, 'utf-8');
60+
finalTitle = getFinalPageTitle(rawContent, page.data.title);
61+
} catch (error) {
62+
// Fallback to frontmatter title if file reading fails
63+
console.warn('Failed to read MDX file for H1 extraction:', error);
64+
finalTitle = page.data.title;
65+
}
66+
5267
return generatePageMetadata({
53-
title: page.data.title,
68+
title: finalTitle,
5469
description: page.data.description || 'DeployStack Documentation and API Reference',
5570
slug: slugString,
5671
url,

docs/docker-to-iac/index.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
title: Docker to IaC
2+
title: Docker to Infrastructure 2
33
description: Introduction to the node module docker-to-iac which allows you to transfer docker-compose into IaC templates
4-
menuTitle: Docker-to-IaC
4+
sidebar: lol text
55
---
66

77
# Docker to Infrastructure as Code Module

docs/docker-to-iac/limitations.mdx

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
title: Limitations
3+
description: Current limitations and constraints of the docker-to-iac module
4+
---
5+
6+
# Limitations for docker-to-iac module
7+
8+
## Registry Support
9+
10+
The module currently supports Docker images from -> please check [Supported Registries for docker-to-iac module](/docs/docker-to-iac/supported-registries.md)
11+
12+
## Docker Image Requirement
13+
14+
The `docker-to-iac` module is designed to work exclusively with pre-built Docker images. This means that each service in your `docker-compose.yml` file must specify an `image` property.
15+
16+
## Volume Support
17+
18+
When working with volume mappings in your Docker configuration, be aware that volume support varies among cloud providers:
19+
20+
- Some providers fully support multiple volume mappings
21+
- Some providers only support the first volume mapping defined in your configuration
22+
- Some providers support ephemeral files only, meaning no persistent volume storage is available
23+
- Volume mapping implementation details can differ between providers
24+
25+
Please check the specific provider's documentation to understand their volume mapping capabilities and limitations before deployment.
26+
27+
For example, if your Docker configuration includes multiple volumes:
28+
29+
```yaml
30+
services:
31+
app:
32+
image: nginx:latest
33+
volumes:
34+
- ./config:/etc/nginx/conf.d
35+
- ./logs:/var/log/nginx
36+
- ./data:/usr/share/nginx/html
37+
```
38+
39+
Depending on your chosen provider:
40+
41+
- All volume mappings might be supported
42+
- Only the first volume mapping (`./config:/etc/nginx/conf.d`) might be implemented
43+
- No volumes might be supported, with only ephemeral storage available
44+
45+
We recommend reviewing your target provider's documentation for detailed information about their volume support capabilities.
46+
47+
### Build Instructions Not Supported
48+
49+
The module does not support services that use the `build` directive. For example:
50+
51+
```yaml [docker-compose.yml]
52+
# ❌ Not Supported
53+
services:
54+
app:
55+
build:
56+
context: ./build/app
57+
dockerfile: Dockerfile
58+
```
59+
60+
Instead, you must use pre-built images:
61+
62+
```yaml [docker-compose.yml]
63+
# ✅ Supported
64+
services:
65+
app:
66+
image: nginx:latest
67+
```
68+
69+
#### Rationale
70+
71+
This limitation exists because Infrastructure as Code (IaC) templates require specific, immutable container images to ensure consistent deployments. The infrastructure and the selection of cloud providers for this docker-to-iac module only allow pre-build container images. It is technically not possible to create a build with the preconfigured infrastructure. This is why the pre-build check was built in. This happens also because the scope of this module is only pre-build container.
72+
73+
### Workaround
74+
75+
If you need to use custom Docker images:
76+
77+
Build your Docker images locally or in your CI/CD pipeline
78+
Push them to a container registry (like Docker Hub, GitHub Container Registry, or AWS ECR)
79+
Reference the pushed image in your docker-compose file using the image property
80+
81+
For example:
82+
83+
```yaml
84+
services:
85+
app:
86+
image: ghcr.io/your-org/your-app:1.0.0
87+
```
88+
89+
This ensures that your IaC templates will have access to the exact same container image across all deployments.

docs/index.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
title: DeployStack Documentation
33
description: Welcome to DeployStack documentation. Learn how to automate Docker Compose deployments across cloud providers with Infrastructure as Code templates and one-click deployments.
4-
menuTitle: DeployStack Documentation
54
---
65

76
# DeployStack Documentation

lib/h1-extractor.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Utility to extract H1 heading from MDX content for use in page titles
3+
*/
4+
5+
export interface H1ExtractionResult {
6+
h1Title: string | null;
7+
fallbackTitle: string;
8+
}
9+
10+
/**
11+
* Extracts the first H1 heading from MDX content
12+
* Supports both markdown syntax (# Heading) and JSX syntax (<h1>Heading</h1>)
13+
*/
14+
export function extractH1FromMDX(content: string): string | null {
15+
if (!content) return null;
16+
17+
// Remove frontmatter first
18+
const contentWithoutFrontmatter = content.replace(/^---[\s\S]*?---\n?/, '');
19+
20+
// Pattern for markdown H1: # Heading
21+
const markdownH1Match = contentWithoutFrontmatter.match(/^#\s+(.+)$/m);
22+
if (markdownH1Match) {
23+
return markdownH1Match[1].trim();
24+
}
25+
26+
// Pattern for JSX H1: <h1>Heading</h1> or <h1 ...>Heading</h1>
27+
const jsxH1Match = contentWithoutFrontmatter.match(/<h1[^>]*>([^<]+)<\/h1>/i);
28+
if (jsxH1Match) {
29+
return jsxH1Match[1].trim();
30+
}
31+
32+
return null;
33+
}
34+
35+
/**
36+
* Gets the best title for a page, preferring H1 over frontmatter title
37+
*/
38+
export function getBestPageTitle(
39+
mdxContent: string | undefined,
40+
frontmatterTitle: string | undefined
41+
): H1ExtractionResult {
42+
const h1Title = mdxContent ? extractH1FromMDX(mdxContent) : null;
43+
const fallbackTitle = frontmatterTitle || 'Untitled';
44+
45+
return {
46+
h1Title,
47+
fallbackTitle,
48+
};
49+
}
50+
51+
/**
52+
* Gets the final title to use, with H1 taking precedence
53+
*/
54+
export function getFinalPageTitle(
55+
mdxContent: string | undefined,
56+
frontmatterTitle: string | undefined
57+
): string {
58+
const { h1Title, fallbackTitle } = getBestPageTitle(mdxContent, frontmatterTitle);
59+
return h1Title || fallbackTitle;
60+
}

lib/source.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const source = loader({
1717
// The source of the documents, converted to Fumadocs format.
1818
source: docs.toFumadocsSource(),
1919

20+
2021
// Icon handler to support both lucide-react icons and custom icons
2122
icon(icon) {
2223
if (!icon) {
@@ -37,11 +38,19 @@ export const source = loader({
3738
return undefined;
3839
},
3940

41+
// Customize page tree to support custom sidebar titles
42+
pageTree: {
43+
attachFile(node, file) {
44+
// If the file has a custom sidebar title, use it instead of the title
45+
if (file?.data && 'sidebar' in file.data && file.data.sidebar) {
46+
node.name = file.data.sidebar as string;
47+
}
48+
return node;
49+
},
50+
},
51+
4052
// Optional: You can define global MDX components here if not done elsewhere
4153
// globalMdxComponents: getMDXComponents(),
42-
43-
// Optional: Configure how slugs are generated
44-
// getSlugs: (file) => { ... }
4554
});
4655

4756
// You might also want to export page tree and other utilities if needed directly

source.config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
import { defineDocs } from 'fumadocs-mdx/config';
1+
import { defineDocs, frontmatterSchema } from 'fumadocs-mdx/config';
2+
import { z } from 'zod';
23

34
export const docs = defineDocs({
45
// Directory of documents, relative to the project root.
56
// We are using the existing 'docs' folder.
67
dir: 'docs',
8+
docs: {
9+
schema: frontmatterSchema.extend({
10+
sidebar: z.string().optional(),
11+
}),
12+
},
713
});

0 commit comments

Comments
 (0)