diff --git a/src/generators/jsx-ast/utils/buildContent.mjs b/src/generators/jsx-ast/utils/buildContent.mjs
index 195e1220..3091e80d 100644
--- a/src/generators/jsx-ast/utils/buildContent.mjs
+++ b/src/generators/jsx-ast/utils/buildContent.mjs
@@ -293,25 +293,10 @@ export const createDocumentLayout = (
remark
) =>
createTree('root', [
- createJSXElement(JSX_IMPORTS.NavBar.name),
- createJSXElement(JSX_IMPORTS.Article.name, {
- children: [
- createJSXElement(JSX_IMPORTS.SideBar.name, sideBarProps),
- createElement('div', [
- createElement('div', [
- createJSXElement(JSX_IMPORTS.TableOfContents.name, {
- headings: metaBarProps.headings,
- summaryTitle: 'On this page',
- }),
- createElement('br'),
- createElement(
- 'main',
- entries.map(entry => processEntry(entry, remark))
- ),
- ]),
- createJSXElement(JSX_IMPORTS.MetaBar.name, metaBarProps),
- ]),
- ],
+ createJSXElement(JSX_IMPORTS.Layout.name, {
+ sideBarProps,
+ metaBarProps,
+ children: entries.map(entry => processEntry(entry, remark)),
}),
]);
diff --git a/src/generators/web/README.md b/src/generators/web/README.md
index 7a62ac5e..7a9361ec 100644
--- a/src/generators/web/README.md
+++ b/src/generators/web/README.md
@@ -6,8 +6,31 @@ The `web` generator transforms JSX AST entries into complete web bundles, produc
The `web` generator accepts the following configuration options:
-| Name | Type | Default | Description |
-| -------------- | -------- | ------------------------------------ | ------------------------------------------------------------------------ |
-| `output` | `string` | - | The directory where HTML, JavaScript, and CSS files will be written |
-| `templatePath` | `string` | `'template.html'` | Path to the HTML template file |
-| `imports` | `object` | `{ '#config/Logo': [Node.js Logo] }` | Object mapping import aliases to package names for external dependencies |
+| Name | Type | Default | Description |
+| -------------- | -------- | ----------------- | --------------------------------------------------------------------- |
+| `output` | `string` | - | The directory where HTML, JavaScript, and CSS files will be written |
+| `templatePath` | `string` | `'template.html'` | Path to the HTML template file |
+| `imports` | `object` | See below | Object mapping `#theme/` aliases to component paths for customization |
+
+#### Default `imports`
+
+| Alias | Default | Description |
+| ------------------- | -------------------------------------------- | -------------------------------------------- |
+| `#theme/Logo` | `@node-core/ui-components/Common/NodejsLogo` | Logo rendered inside the navigation bar |
+| `#theme/Navigation` | Built-in `NavBar` component | Top navigation bar |
+| `#theme/Sidebar` | Built-in `SideBar` component | Sidebar with version selector and page links |
+| `#theme/Layout` | Built-in `Layout` component | Outermost wrapper around the full page |
+
+Override any alias in your config file to swap in a custom component:
+
+```js
+// doc-kit.config.mjs
+export default {
+ web: {
+ imports: {
+ '#theme/Logo': './src/MyLogo.jsx',
+ '#theme/Sidebar': './src/MySidebar.jsx',
+ },
+ },
+};
+```
diff --git a/src/generators/web/constants.mjs b/src/generators/web/constants.mjs
index 82632a3a..04e8a51e 100644
--- a/src/generators/web/constants.mjs
+++ b/src/generators/web/constants.mjs
@@ -23,17 +23,9 @@ export const NODE_MODULES = resolve(
* An object containing mappings for various JSX components to their import paths.
*/
export const JSX_IMPORTS = {
- NavBar: {
- name: 'NavBar',
- source: resolve(ROOT, './ui/components/NavBar'),
- },
- SideBar: {
- name: 'SideBar',
- source: resolve(ROOT, './ui/components/SideBar'),
- },
- MetaBar: {
- name: 'MetaBar',
- source: resolve(ROOT, './ui/components/MetaBar'),
+ Layout: {
+ name: 'Layout',
+ source: '#theme/Layout',
},
CodeBox: {
name: 'CodeBox',
@@ -58,10 +50,6 @@ export const JSX_IMPORTS = {
isDefaultExport: false,
source: '@node-core/ui-components/MDX/Tooltip',
},
- TableOfContents: {
- name: 'TableOfContents',
- source: '@node-core/ui-components/Common/TableOfContents',
- },
ChangeHistory: {
name: 'ChangeHistory',
source: '@node-core/ui-components/Common/ChangeHistory',
@@ -70,10 +58,6 @@ export const JSX_IMPORTS = {
name: 'AlertBox',
source: '@node-core/ui-components/Common/AlertBox',
},
- Article: {
- name: 'Article',
- source: '@node-core/ui-components/Containers/Article',
- },
Blockquote: {
name: 'Blockquote',
source: '@node-core/ui-components/Common/Blockquote',
diff --git a/src/generators/web/index.mjs b/src/generators/web/index.mjs
index 00b72d20..f881bebf 100644
--- a/src/generators/web/index.mjs
+++ b/src/generators/web/index.mjs
@@ -30,7 +30,12 @@ export default createLazyGenerator({
templatePath: join(import.meta.dirname, 'template.html'),
title: 'Node.js',
imports: {
- '#config/Logo': '@node-core/ui-components/Common/NodejsLogo',
+ '#theme/Logo': '@node-core/ui-components/Common/NodejsLogo',
+ '#theme/Navigation': join(import.meta.dirname, './ui/components/NavBar'),
+ '#theme/Sidebar': join(import.meta.dirname, './ui/components/SideBar'),
+ '#theme/Metabar': join(import.meta.dirname, './ui/components/MetaBar'),
+ '#theme/Footer': join(import.meta.dirname, './ui/components/NoOp'),
+ '#theme/Layout': join(import.meta.dirname, './ui/components/Layout'),
},
},
});
diff --git a/src/generators/web/ui/components/Layout/index.jsx b/src/generators/web/ui/components/Layout/index.jsx
new file mode 100644
index 00000000..508f4db9
--- /dev/null
+++ b/src/generators/web/ui/components/Layout/index.jsx
@@ -0,0 +1,37 @@
+import TableOfContents from '@node-core/ui-components/Common/TableOfContents';
+import Article from '@node-core/ui-components/Containers/Article';
+
+import Footer from '#theme/Footer';
+import MetaBar from '#theme/Metabar';
+import NavBar from '#theme/Navigation';
+import SideBar from '#theme/Sidebar';
+
+/**
+ * Default page Layout component.
+ *
+ * Renders the full page structure: navigation, sidebar, table of contents,
+ * main content, meta bar, and footer. Override via `#theme/Layout` in your
+ * configuration's `imports` to customize the entire page structure.
+ *
+ * @param {{ sideBarProps: object, metaBarProps: object, children: import('preact').ComponentChildren }} props
+ */
+export default ({ sideBarProps, metaBarProps, children }) => (
+ <>
+
+
+
+
+
+
+ >
+);
diff --git a/src/generators/web/ui/components/NavBar.jsx b/src/generators/web/ui/components/NavBar.jsx
index 48fbe98c..fe26e629 100644
--- a/src/generators/web/ui/components/NavBar.jsx
+++ b/src/generators/web/ui/components/NavBar.jsx
@@ -7,7 +7,7 @@ import SearchBox from './SearchBox';
import { STATIC_DATA } from '../constants.mjs';
import { useTheme } from '../hooks/useTheme.mjs';
-import Logo from '#config/Logo';
+import Logo from '#theme/Logo';
/**
* NavBar component that displays the headings, search, etc.
diff --git a/src/generators/web/ui/components/NoOp.jsx b/src/generators/web/ui/components/NoOp.jsx
new file mode 100644
index 00000000..461f67a0
--- /dev/null
+++ b/src/generators/web/ui/components/NoOp.jsx
@@ -0,0 +1 @@
+export default () => null;