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
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 80
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Enforce Unix newlines
* text=auto eol=lf
22 changes: 22 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: '/'
schedule:
interval: monthly
commit-message:
prefix: meta
cooldown:
default-days: 3
open-pull-requests-limit: 10

- package-ecosystem: npm
directory: '/'
versioning-strategy: increase
schedule:
interval: monthly
commit-message:
prefix: meta
cooldown:
default-days: 3
open-pull-requests-limit: 10
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Security Notes
# Only selected Actions are allowed within this repository. Please refer to (https://github.com/nodejs/nodejs.org/settings/actions)
# for the full list of available actions. If you want to add a new one, please reach out a maintainer with Admin permissions.
# REVIEWERS, please always double-check security practices before merging a PR that contains workflow changes!!
# AUTHORS, please only use actions with explicit SHA references, and avoid using `@master` or `@main` references or `@version` tags.

name: Linting and Tests

# This workflow should run either on `merge_group`, `pull_request`, or `push` events
# since we want to run lint checks against any changes on pull requests, or the final patch on merge groups
# or if direct pushes happen to main (or when changes in general land on the `main` (default) branch)
# Note that the reason why we run this on pushes against `main` is that on rare cases, maintainers might do direct pushes against `main`

on:
push:
branches:
- main
pull_request:
branches:
- main
types: [opened, synchronize, reopened, ready_for_review]
merge_group:

# The permissions specified below apply to workflows triggered by `merge_group`, `push`, and `pull_request` events that originate from the same repository (non-fork).
# However, workflows triggered by `pull_request` events from forked repositories are treated differently for security reasons:
# - These workflows **do not** have access to any secrets configured in the repository.
# - They are also **not granted any permissions** to perform actions on the base repository.
#
# This is a deliberate security restriction designed to prevent potential abuse through malicious pull requests from forks.
# For a deeper explanation and best practices for securing your GitHub Actions workflows, particularly against so-called "pwn requests",
# refer to https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/
permissions:
contents: read
actions: read

jobs:
lint:
name: Quality checks
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version: lts/*
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run quality checks
run: node --run lint:fix && node --run format:check
52 changes: 52 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Deploy

on:
workflow_dispatch:
push:
branches: [main]

permissions:
contents: read

jobs:
# Build job
build:
# Specify runner + build & upload the static files as an artifact
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version: lts/*
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build
run: mkdir out && npm run build

- name: Upload static files as artifact
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
with:
path: out/

deploy:
needs: build

permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
out
components/config.json
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
6 changes: 6 additions & 0 deletions .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"**/*.{js,mjs,ts,tsx,md,mdx,json.yml}": [
"eslint --fix",
"prettier --check --write"
]
}
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
11 changes: 11 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"jsxSingleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "avoid"
}
3 changes: 3 additions & 0 deletions .remarkrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["@node-core/remark-lint"]
}
54 changes: 54 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Contributing to nodejs/learn

Thank you for your interest in contributing! This repository contains the
Node.js learning guides.

## Content structure

All articles live under `pages/`, organized into topic sections:

| Directory | Topics covered |
| --------------------- | ------------------------------------------------------- |
| `getting-started/` | Introduction, V8 engine, dev vs production, WebAssembly |
| `asynchronous-work/` | Event loop, callbacks, promises, streams |
| `command-line/` | REPL, environment variables, CLI I/O |
| `diagnostics/` | Debugging, profiling, memory, performance |
| `file-system/` | File paths, stats, reading, writing, folders |
| `http/` | HTTP transactions, fetch, WebSockets, proxies |
| `package-management/` | npm, publishing packages, Node-API modules |
| `security/` | Security best practices |
| `testing/` | Test runner, mocking, code coverage |
| `typescript/` | TypeScript with Node.js |

## Making changes

### Editing an existing article

1. Find the relevant `.md` file under `pages/`.
2. Edit the content (standard GitHub-flavored Markdown).
3. Open a pull request — no build step required to review prose changes.

### Adding a new article

1. Choose the most relevant section directory, or propose a new one in your PR.
2. Create a new `.md` file with a descriptive kebab-case name.
3. Include frontmatter at the top of the file if required by `doc-kit`.

### Adding a new section

Open an issue first to discuss the proposed section before adding files.
Refer to the [Card Sort results](https://github.com/nodejs/nodejs.org/issues/8234)
for prior user-research context on content organisation.

## Building locally

```bash
npm install
npm run build
# Output is written to out/
```

## Code of Conduct

This project follows the
[Node.js Code of Conduct](https://github.com/nodejs/admin/blob/main/CODE_OF_CONDUCT.md).
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# nodejs/learn

Source content for the Node.js learning guides, published at https://nodejs.github.io/learn.

This repository was created as part of
[nodejs/nodejs.org#8612](https://github.com/nodejs/nodejs.org/issues/8612)
to give the Learn content a dedicated home, separate from the main website
monorepo. Content editors no longer need to deal with Next.js tooling or
website-specific git hooks.

## Content

All articles are Markdown files under `pages/`, grouped by topic:

```
pages/
├── getting-started/ # Introduction to Node.js
├── asynchronous-work/ # Event loop, callbacks, promises, streams
├── command-line/ # REPL, environment variables, CLI I/O
├── diagnostics/ # Debugging, profiling, memory, performance
├── file-system/ # File paths, stats, reading/writing, folders
├── http/ # HTTP, fetch, WebSockets, proxies
├── package-management/ # npm, publishing packages, Node-API modules
├── security/ # Security best practices
├── testing/ # Test runner, mocking, code coverage
└── typescript/ # TypeScript with Node.js
```

The structure is based on
[Card Sort research](https://github.com/nodejs/nodejs.org/issues/8234)
conducted at the 2025 Cambridge Node.js Collaborators' Summit.

## Development

```bash
npm install
npm run build # generates static site + Orama search DB in out/
```

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).
41 changes: 41 additions & 0 deletions components/Metabar/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import MetaBar from '@node-core/ui-components/Containers/MetaBar';
import AvatarGroup from '@node-core/ui-components/Common/AvatarGroup';
import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub';

import { authors } from '../config.json' with { type: 'json' };

/**
* @typedef MetaBarProps
* @property {Array<import('@vcarl/remark-headings').Heading>} headings
* @property {string} readingTime
* @property {Array<[string, string]>} viewAs
* @property {string} editThisPage
*/

/** @param {MetaBarProps} props */
export default ({ headings = [], readingTime, viewAs = [], editThisPage }) => {
const pageAuthors = authors[editThisPage];

return (
<MetaBar
heading="Table of Contents"
headings={{ items: headings }}
items={{
'Reading Time': readingTime,
...(CLIENT && pageAuthors?.length
? {
Authors: (
<AvatarGroup avatars={pageAuthors} as="a" clickable limit={5} />
),
}
: {}),
Contribute: (
<>
<GitHubIcon className="fill-neutral-700 dark:fill-neutral-100" />
<a href={editThisPage}>Edit this page</a>
</>
),
}}
/>
);
};
37 changes: 37 additions & 0 deletions components/Navigation/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import ThemeToggle from '@node-core/ui-components/Common/ThemeToggle';
import NavBar from '@node-core/ui-components/Containers/NavBar';
import styles from '@node-core/ui-components/Containers/NavBar/index.module.css';
import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub';

import SearchBox from '@node-core/doc-kit/src/generators/web/ui/components/SearchBox';
import { useTheme } from '@node-core/doc-kit/src/generators/web/ui/hooks/useTheme.mjs';

import Logo from '#theme/Logo';
import { topNav } from '../config.json' with { type: 'json' };

/**
* NavBar component that displays the headings, search, etc.
*/
export default () => {
const [theme, toggleTheme] = useTheme();

return (
<NavBar
Logo={Logo}
sidebarItemTogglerAriaLabel="Toggle navigation menu"
navItems={topNav}
>
<SearchBox />
<ThemeToggle
onClick={toggleTheme}
aria-label={`Switch to ${theme === 'light' ? 'dark' : 'light'} theme`}
/>
<a
href={`https://github.com/nodejs/learn`}
className={styles.ghIconWrapper}
>
<GitHubIcon />
</a>
</NavBar>
);
};
23 changes: 23 additions & 0 deletions components/Sidebar/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import SideBar from '@node-core/ui-components/Containers/Sidebar';

import { sideNav } from '../config.json' with { type: 'json' };

/**
* Redirect to a URL
* @param {string} url URL
*/
const redirect = url => (window.location.href = url);

/**
* Sidebar component for MDX documentation with page navigation
* @param {{ pathname: string }} props
*/
export default ({ pathname }) => (
<SideBar
pathname={pathname}
groups={sideNav}
onSelect={redirect}
as={props => <a {...props} rel="prefetch" />}
title="Navigation"
/>
);
Loading