Skip to content
Draft
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 11 additions & 17 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,17 @@ docs @nodejs/nodejs-website @nodejs/web-infra
SECURITY.md @nodejs/security-wg

# Node.js Release Blog Posts
apps/site/pages/en/blog/release @nodejs/releasers
apps/site/pages/en/blog/announcements @nodejs/releasers
packages/content/src/en/blog/release @nodejs/releasers
packages/content/src/en/blog/announcements @nodejs/releasers

# The following users DO NOT have write access, and their review is requested
# via a GitHub action.
apps/site/pages/en/learn/diagnostics @nodejs/diagnostics

apps/site/pages/en/learn/getting-started/security-best-practices.md @nodejs/security-wg

apps/site/pages/en/learn/manipulating-files @nodejs/fs

apps/site/pages/en/learn/test-runner @nodejs/test_runner

apps/site/pages/en/learn/typescript @nodejs/typescript

apps/site/pages/en/about/partners.mdx @nodejs/marketing
apps/site/pages/en/about/branding.mdx @nodejs/marketing

apps/site/pages/en/learn/getting-started/userland-migrations.md @nodejs/userland-migrations
apps/site/pages/en/blog/migrations @nodejs/userland-migrations
packages/content/src/en/learn/diagnostics @nodejs/diagnostics
packages/content/src/en/learn/getting-started/security-best-practices.md @nodejs/security-wg
packages/content/src/en/learn/manipulating-files @nodejs/fs
packages/content/src/en/learn/test-runner @nodejs/test_runner
packages/content/src/en/learn/typescript @nodejs/typescript
packages/content/src/en/about/partners.mdx @nodejs/marketing
packages/content/src/en/about/branding.mdx @nodejs/marketing
packages/content/src/en/learn/getting-started/userland-migrations.md @nodejs/userland-migrations
packages/content/src/en/blog/migrations @nodejs/userland-migrations
2 changes: 0 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ updates:
- shiki
- sval
- unist-util-*
- vfile
- vfile-*
- reading-time
- twoslash
orama:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/publish-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ jobs:
PKG_NAME=$(basename "$pkg")
PKG_JSON="$pkg/package.json"

IS_PRIVATE=$(jq -r '.private // false' "$PKG_JSON")
if [ "$IS_PRIVATE" = "true" ]; then
echo "⏭️ Skipping private package: $PKG_NAME"
continue
fi

# Determine if the package has changed (or include all on manual trigger)
if [ "$EVENT_NAME" == "workflow_dispatch" ] || ! git diff --quiet $COMMIT_SHA~1 $COMMIT_SHA -- "$pkg/"; then
OLD_VERSION=$(git show $COMMIT_SHA~1:$PKG_JSON | jq -r '.version')
Expand Down Expand Up @@ -113,6 +119,12 @@ jobs:
- name: Publish
working-directory: packages/${{ matrix.package }}
run: |
# Fail-safe
if jq -e '.private == true' package.json > /dev/null; then
echo "❌ Refusing to publish private package"
exit 0
fi

# Check if a custom publish script exists in package.json
if jq -e '.scripts.release' package.json > /dev/null; then
pnpm run release
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/translations-pr-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ on:
branches:
- main
paths:
- 'apps/site/pages/**/*.md'
- 'apps/site/pages/**/*.mdx'
- '!apps/site/pages/en/**/*.md'
- '!apps/site/pages/en/**/*.mdx'
- 'packages/content/src/**/*.md'
- 'packages/content/src/**/*.mdx'
- '!packages/content/src/en/**/*.md'
- '!packages/content/src/en/**/*.mdx'
- 'packages/i18n/src/locales/*.json'
- '!packages/i18n/src/locales/en.json'
- 'apps/site/snippets/**/*.bash'
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/translations-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,16 @@ jobs:
uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: |
apps/site/.eslintmdcache
apps/site/.prettiercache
.turbo/cache
.eslintmdcache
.stylelintcache
.prettiercache
# We want to restore Turborepo Cache and ESlint and Prettier Cache
# The ESLint and Prettier cache's are useful to reduce the overall runtime of ESLint and Prettier
# as they will only run on files that have changed since the last cached run
# this might of course lead to certain files not being checked against the linter, but the chances
# of such situation from happening are very slim as the checksums of both files would need to match
key: cache-lint-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('apps/site/.eslintmdcache') }}
key: cache-lint-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('.turbo/cache/**') }}
restore-keys: |
cache-lint-${{ hashFiles('pnpm-lock.yaml') }}-
cache-lint-
Expand All @@ -98,8 +100,8 @@ jobs:
fi

- name: Run ESLint
working-directory: apps/site
run: node --run lint:md -- --fix
working-directory: packages/content
run: node --run lint:fix

- name: Run Prettier
run: node --run prettier:fix
Expand Down
99 changes: 2 additions & 97 deletions apps/site/app/[locale]/[...path]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,2 @@
/**
* This file extends on the `page.tsx` file, which is the default file that is used to render
* the entry points for each locale and then also reused within the [...path] route to render the
* and contains all logic for rendering our dynamic and static routes within the Node.js Website.
*
* Note: that each `page.tsx` should have its own `generateStaticParams` to prevent clash of
* dynamic params, which will lead on static export errors and other sort of issues.
*/

import { availableLocaleCodes, defaultLocale } from '@node-core/website-i18n';
import { notFound } from 'next/navigation';

import { ENABLE_STATIC_EXPORT } from '#site/next.constants.mjs';
import { ENABLE_STATIC_EXPORT_LOCALE } from '#site/next.constants.mjs';
import { dynamicRouter } from '#site/next.dynamic.mjs';
import * as basePage from '#site/next.dynamic.page.mjs';

import type { DynamicParams } from '#site/types';
import type { FC } from 'react';

type PageParams = DynamicParams<{ path: Array<string> }>;

// This is the default Viewport Metadata
// @see https://nextjs.org/docs/app/api-reference/functions/generate-viewport#generateviewport-function
export const generateViewport = basePage.generateViewport;

// This generates each page's HTML Metadata
// @see https://nextjs.org/docs/app/api-reference/functions/generate-metadata
export const generateMetadata = basePage.generateMetadata;

// Generates all possible static paths based on the locales and environment configuration
// - Returns an empty array if static export is disabled (`ENABLE_STATIC_EXPORT` is false)
// - If `ENABLE_STATIC_EXPORT_LOCALE` is true, generates paths for all available locales
// - Otherwise, generates paths only for the default locale
// @see https://nextjs.org/docs/app/api-reference/functions/generate-static-params
export const generateStaticParams = async () => {
// Return an empty array if static export is disabled
if (!ENABLE_STATIC_EXPORT) {
return [];
}

const routes = await dynamicRouter.getAllRoutes();

// Helper function to fetch and map routes for a specific locale
const getRoutesForLocale = async (l: string) =>
routes.map(pathname => dynamicRouter.mapPathToRoute(l, pathname));

// Determine which locales to include in the static export
const locales = ENABLE_STATIC_EXPORT_LOCALE
? availableLocaleCodes
: [defaultLocale.code];

// Generates all possible routes for all available locales
const routesWithLocales = await Promise.all(locales.map(getRoutesForLocale));

return routesWithLocales.flat().sort();
};

// This method parses the current pathname and does any sort of modifications needed on the route
// then it proceeds to retrieve the Markdown file and parse the MDX Content into a React Component
// finally it returns (if the locale and route are valid) the React Component with the relevant context
// and attached context providers for rendering the current page
const getPage: FC<PageParams> = async props => {
const { path, locale: routeLocale } = await props.params;

// Gets the current full pathname for a given path
const [locale, pathname] = basePage.getLocaleAndPath(path, routeLocale);

// Gets the Markdown content and context
const [content, context] = await basePage.getMarkdownContext({
locale,
pathname,
});

// If we have a filename and layout then we have a page
if (context.filename && context.frontmatter.layout) {
return basePage.renderPage({
content,
layout: context.frontmatter.layout,
context,
});
}

return notFound();
};

// Enforces that this route is used as static rendering
// Except whenever on the Development mode as we want instant-refresh when making changes
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'force-static';

// Ensures that this endpoint is invalidated and re-executed every X minutes
// so that when new deployments happen, the data is refreshed
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
export const revalidate = 300;

export default getPage;
export * from '../page';
export { default } from '../page';
82 changes: 0 additions & 82 deletions apps/site/app/[locale]/blog/[...path]/page.tsx

This file was deleted.

46 changes: 10 additions & 36 deletions apps/site/app/[locale]/download/archive/[version]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,14 @@ import { notFound, redirect } from 'next/navigation';
import provideReleaseData from '#site/next-data/providers/releaseData';
import provideReleaseVersions from '#site/next-data/providers/releaseVersions';
import { ENABLE_STATIC_EXPORT } from '#site/next.constants.mjs';
import * as basePage from '#site/next.dynamic.page.mjs';
import { getMarkdownFile } from '#site/router';
import { renderPage } from '#site/router/render';

import type { DynamicParams } from '#site/types';
import type { FC } from 'react';

type PageParams = DynamicParams<{ version: string }>;

// This is the default Viewport Metadata
// @see https://nextjs.org/docs/app/api-reference/functions/generate-viewport#generateviewport-function
export const generateViewport = basePage.generateViewport;

// This generates each page's HTML Metadata
// @see https://nextjs.org/docs/app/api-reference/functions/generate-metadata
export const generateMetadata = basePage.generateMetadata;

// Generates all possible static paths based on the locales and environment configuration
// - Returns an empty array if static export is disabled (`ENABLE_STATIC_EXPORT` is false)
// - If `ENABLE_STATIC_EXPORT_LOCALE` is true, generates paths for all available locales
Expand All @@ -43,10 +36,7 @@ export const generateStaticParams = async () => {
// finally it returns (if the locale and route are valid) the React Component with the relevant context
// and attached context providers for rendering the current page
const getPage: FC<PageParams> = async props => {
const { version, locale: routeLocale } = await props.params;

// Gets the current full pathname for a given path
const [locale, pathname] = basePage.getLocaleAndPath(version, routeLocale);
const { version, locale } = await props.params;

if (version === 'current') {
const releaseData = await provideReleaseData();
Expand All @@ -59,35 +49,19 @@ const getPage: FC<PageParams> = async props => {
const versions = await provideReleaseVersions();

// Verifies if the current route is a dynamic route
const isDynamicRoute = versions.some(r => r.includes(pathname));

// Gets the Markdown content and context for Download Archive pages
const [content, context] = await basePage.getMarkdownContext({
locale,
pathname: 'download/archive',
});
const isDynamicRoute = versions.some(r => r.includes(version));

// If this isn't a valid dynamic route for archive version or there's no markdown
// file for this, then we fail as not found as there's nothing we can do.
if (isDynamicRoute && context.filename) {
return basePage.renderPage({
content,
layout: context.frontmatter.layout!,
context: { ...context, pathname: `/download/archive/${pathname}` },
});
if (isDynamicRoute) {
const markdown = (await getMarkdownFile(locale, 'download/archive'))!;
markdown.pathname = `/download/archive/${version}`;

return renderPage(markdown);
}

return notFound();
};

// Enforces that this route is used as static rendering
// Except whenever on the Development mode as we want instant-refresh when making changes
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'force-static';

// Ensures that this endpoint is invalidated and re-executed every X minutes
// so that when new deployments happen, the data is refreshed
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
export const revalidate = 300;

export default getPage;
export * from '#site/router/page';
4 changes: 2 additions & 2 deletions apps/site/app/[locale]/feed/[feed]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ export const generateStaticParams = async () =>
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
export const dynamicParams = false;

// Enforces that this route is cached and static as much as possible
// Enforces that this route is used as static rendering
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'force-static';

// Ensures that this endpoint is invalidated and re-executed every X minutes
// so that when new deployments happen, the data is refreshed
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
export const revalidate = 300;
export const revalidate = false;
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ export const generateStaticParams = async () => [
},
];

// Enforces that this route is cached and static as much as possible
// Enforces that this route is used as static rendering
// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
export const dynamic = 'force-static';
Loading
Loading