Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/site/authors.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@
"name": "Giovanny Gongora",
"website": "https://github.com/Gioyik"
},
"Guilherme Araújo": {
"id": "araujogui",
"name": "Guilherme Araújo",
"website": "https://github.com/araujogui"
},
"Isaac Schlueter": {
"id": "isaacs",
"name": "Isaac Schlueter",
Expand Down
13 changes: 8 additions & 5 deletions apps/site/components/withNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,14 @@ const WithNavBar: FC = () => {
<WithBanner section="index" />

<NavBar
navItems={navigationItems.map(([, { label, link, target }]) => ({
link,
text: label,
target,
}))}
navItems={navigationItems.map(
([, { label, link, target, accent }]) => ({
link,
text: label,
target,
accent,
})
)}
pathname={pathname}
as={Link}
Logo={WithNodejsLogo}
Expand Down
4 changes: 3 additions & 1 deletion apps/site/hooks/useSiteNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type MappedNavigationEntry = {
label: FormattedMessage;
link: string;
target?: HTMLAttributeAnchorTarget | undefined;
accent?: boolean;
};

// Provides Context replacement for variables within the Link. This is also something that is not going
Expand All @@ -44,13 +45,14 @@ const useSiteNavigation = () => {
t.rich(label, context[key] || {}) as FormattedMessage;

return Object.entries(entries).map(
([key, { label, link, items, target }]): [
([key, { label, link, items, target, accent }]): [
string,
MappedNavigationEntry,
] => [
key,
{
target,
accent,
label: label ? getFormattedMessage(label, key) : '',
link: link ? replaceLinkWithContext(link, context[key]) : '',
items: items ? mapNavigationEntries(items, context) : [],
Expand Down
6 changes: 6 additions & 0 deletions apps/site/navigation.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
"link": "https://nodejs.org/docs/latest/api/",
"label": "components.containers.navBar.links.docs"
},
"betaDocs": {
"link": "https://beta.docs.nodejs.org/",
"label": "components.containers.navBar.links.betaDocs",
"target": "_blank",
"accent": true
},
"contribute": {
"link": "https://github.com/nodejs/node/blob/main/CONTRIBUTING.md",
"label": "components.containers.navBar.links.contribute",
Expand Down
37 changes: 37 additions & 0 deletions apps/site/pages/en/blog/announcements/new-api-docs-beta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
date: '2026-07-24T19:00:00.000Z'
category: announcements
title: Check out the New Node.js API Documentation Preview
layout: blog-post
author: Guilherme Araújo
---

We've been rebuilding how Node.js generates and presents its API documentation, and a preview is now live at [beta.docs.nodejs.org](https://beta.docs.nodejs.org/). Before it becomes the default, we want as many people as possible to use it for real work and tell us what you think.

## What's different for readers

The content itself hasn't changed: every page is generated from the same Markdown files in the [nodejs/node](https://github.com/nodejs/node) repository that power the current docs. The features you rely on today made the trip too: light and dark themes, ESM/CJS switching and copy buttons on snippets, stability badges, version history, and the Markdown version of every page.

The redesign goes deeper than visuals, though: navigation, layout, and readability were all reworked so that finding and understanding an API takes less effort. On top of that, the beta adds things the current docs have never had:

- **Search**: For the first time, the API docs have built-in search. A search box on every page, with a keyboard shortcut, lets you jump anywhere in the API without a detour through a search engine.
- **One design across the project**: The API docs now share the design system of the nodejs.org website, with a persistent sidebar listing every module, an always-visible per-page table of contents, and a layout that works on small screens.
- **llms.txt**: We've already shipped [llms.txt](https://nodejs.org/llms.txt), giving AI tools a clean, structured entry point to the API reference.

And that's not the whole list: the beta also ships features like reading times and announcement bars.

We also care about the needs of every user, and we pay attention to the ones that are easy to overlook. Every page stays usable even with JavaScript disabled and offline.

## Under-the-hood

The redesigned documentation is built with [doc-kit](https://github.com/nodejs/doc-kit), a standalone tool developed by the Node.js Project to replace the previous legacy documentation generator.

For more information on doc-kit and its capabilities for other projects, please refer to [its repository](https://github.com/nodejs/doc-kit). This will also be the place where bug reports, feature requests, and other tasks should be tracked.

## We need your feedback

While we are proud to state that the redesigned documentation is entering its final stage of development, feedback is still a crucial part of this migration, and we'd love to hear your thoughts on this process. Please open an issue on the [nodejs/doc-kit](https://github.com/nodejs/doc-kit/issues) repository with anything you find, big or small.

## Acknowledgments

None of this would exist without the [Node.js Web Team](https://github.com/nodejs/web-team/blob/main/MEMBERS.md), whose members designed, built, and reviewed everything described in this post. Thanks as well to the Node.js community and the collaborators who have already helped by reviewing, testing, and making suggestions along the way. Thank you all for making this possible.
13 changes: 11 additions & 2 deletions apps/site/tests/e2e/general-behavior.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const locators = {
mobileMenuToggleName:
englishLocale.components.containers.navBar.controls.toggle,
navLinksLocator: `[aria-label="${englishLocale.components.containers.navBar.controls.toggle}"] + div`,
// The Beta Docs link renders untranslated (English) across locales, so we
// match on its English label to skip it during translation checks.
betaDocsName: englishLocale.components.containers.navBar.links.betaDocs,
// Global UI controls
languageDropdownName: englishLocale.components.common.languageDropdown.label,
themeToggleName: englishLocale.components.header.buttons.theme,
Expand Down Expand Up @@ -55,8 +58,14 @@ const verifyTranslation = async (page: Page, locale: Locale | string) => {

// Verify each navigation link text matches an expected translation
for (const link of links) {
const linkText = await link.textContent();
expect(expectedTexts).toContain(linkText!.trim());
const linkText = (await link.textContent())!.trim();
// Skip the Beta Docs link: it renders untranslated (English) across
// locales and has no translation entry in most locale files, so it
// won't appear in `expectedTexts` for non-English locales (e.g. es).
if (linkText === locators.betaDocsName) {
continue;
}
expect(expectedTexts).toContain(linkText);
}
};

Expand Down
2 changes: 2 additions & 0 deletions apps/site/types/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type NavigationKeys =
| 'about'
| 'download'
| 'docs'
| 'betaDocs'
| 'getInvolved'
| 'certification'
| 'learn'
Expand All @@ -26,6 +27,7 @@ export type NavigationEntry = {
link?: string;
items?: Record<string, NavigationEntry>;
target?: HTMLAttributeAnchorTarget | undefined;
accent?: boolean;
};

export type SiteNavigation = {
Expand Down
1 change: 1 addition & 0 deletions packages/i18n/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"about": "About",
"download": "Download",
"docs": "Docs",
"betaDocs": "Beta Docs",
"guides": "Guides",
"learn": "Learn",
"security": "Security",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
gap-2
rounded-sm
px-3
py-2;
py-2
motion-safe:transition-colors;

.label {
@apply text-base
Expand Down Expand Up @@ -45,6 +46,19 @@
}
}

&.accent {
@apply bg-transparent
ring-1
ring-neutral-200
ring-inset
dark:ring-neutral-900;

&:hover {
@apply bg-neutral-200
dark:bg-neutral-900;
}
}

&.footer {
.label {
@apply text-neutral-800
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type NavItemProps = {
type?: NavItemType;
className?: string;
target?: HTMLAttributeAnchorTarget | undefined;
accent?: boolean;

pathname: string;
active?: boolean;
Expand All @@ -27,12 +28,18 @@ const NavItem: FC<PropsWithChildren<NavItemProps>> = ({
children,
className,
target,
accent,
...props
}) => (
<BaseActiveLink
target={target}
href={href}
className={classNames(styles.navItem, styles[type], className)}
className={classNames(
styles.navItem,
styles[type],
{ [styles.accent]: accent },
className
)}
activeClassName={styles.active}
allowSubPath={href.startsWith('/')}
{...props}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export const Default: Story = {
text: 'Docs',
link: '/docs',
},
{
text: 'Beta Docs',
link: 'https://beta.docs.nodejs.org/',
target: '_blank',
accent: true,
},
{
text: 'Download',
link: '/download',
Expand Down
4 changes: 3 additions & 1 deletion packages/ui-components/src/Containers/NavBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type NavbarProps = {
text: FormattedMessage;
link: string;
target?: HTMLAttributeAnchorTarget | undefined;
accent?: boolean;
}>;
Logo?: ElementType;
as: LinkLike;
Expand Down Expand Up @@ -92,14 +93,15 @@ const NavBar: FC<PropsWithChildren<NavbarProps>> = ({
<div className={classNames(styles.main, `hidden peer-checked:flex`)}>
{navItems && navItems.length > 0 && (
<div className={styles.navItems}>
{navItems.map(({ text, link, target }) => (
{navItems.map(({ text, link, target, accent }) => (
<NavItem
pathname={pathname}
active={link === activeLink}
as={Component}
key={link}
href={link}
target={target}
accent={accent}
>
{text}
</NavItem>
Expand Down
Loading