diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/arabic/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index 4b210cf253e..58cc1763d59 100644
--- a/curriculum/challenges/arabic/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/arabic/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/arabic/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/chinese-traditional/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/chinese-traditional/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index d0912f88606..b72c778dbaa 100644
--- a/curriculum/challenges/chinese-traditional/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/chinese-traditional/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Number Sorter
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/chinese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/chinese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index 0a51d0fa4ff..b0ef1c77230 100644
--- a/curriculum/challenges/chinese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/chinese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Number Sorter
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/chinese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator.md b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator.md
index 9b1dbe05bbd..7d46fcf656f 100644
--- a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator.md
+++ b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator.md
@@ -11,7 +11,7 @@ dashedName: comparisons-with-the-logical-and-operator
A veces tendrás que probar más de una cosa a la vez. El operador lógico and (`&&`) devuelve `true` si y solo si los operandos a la izquierda y a la derecha son verdaderos.
-The same effect could be achieved by nesting an `if` statement inside another `if`.
+Se podría lograr el mismo efecto anidando una sentencia `if` dentro de otra `if`.
```js
if (num > 5) {
@@ -22,7 +22,7 @@ if (num > 5) {
return "No";
```
-This code will return `Yes` if `num` is greater than `5` and less than `10`. The same logic can be written with the logical and operator.
+Este código devolverá `Yes` si `num` es mayor que `5` y menor que `10`. La misma lógica se puede escribir con el operador lógico and.
```js
if (num > 5 && num < 10) {
diff --git a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md
index 9634d2a22d0..49afe0ec8f9 100644
--- a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md
+++ b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md
@@ -11,7 +11,7 @@ dashedName: escape-sequences-in-strings
Las comillas no son los únicos caracteres que pueden ser escapados dentro de una cadena. Las secuencias de escape le permiten utilizar caracteres que de otro modo no podrías usar en una cadena.
-
Código
Resultado
\'
comilla simple
\"
comilla doble
\\
barra invertida
\n
línea nueva
\t
tabulador
\r
retorno del carro
\b
backspace
\f
fuente de formulario
+
Código
Resultado
\'
comilla simple
\"
comilla doble
\\
barra invertida
\n
línea nueva
\t
tabulador
\r
retorno del carro
\b
retroceso
\f
fuente de formulario
*Ten en cuenta que la barra invertida debe escaparse para que aparezca como tal.*
diff --git a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-with-javascript.md b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-with-javascript.md
index 03c6387500d..a8a0d05b1d7 100644
--- a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-with-javascript.md
+++ b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-with-javascript.md
@@ -9,25 +9,25 @@ dashedName: generate-random-whole-numbers-with-javascript
# --description--
-You can generate random decimal numbers with `Math.random()`, but sometimes you need to generate random whole numbers. The following process will give you a random whole number less than `20`:
+Puedes generar números decimales aleatorios con `Math.random()`, pero a veces es necesario generar números enteros aleatorios. El siguiente proceso te dará un número entero aleatorio menor que `20`:
-1. Use `Math.random()` to generate a random decimal number.
-2. Multiply that random decimal number by `20`.
-3. Use `Math.floor()` to round this number down to its nearest whole number.
+1. Usa `Math.random()` para generar un número decimal aleatorio.
+2. Multiplica ese número decimal aleatorio por `20`.
+3. Usa `Math.floor()` para redondear este número hacia abajo a su número entero más cercano.
-Remember that `Math.random()` can never quite return a `1`, so it's impossible to actually get `20` since you are rounding down with `Math.floor()`. This process will give you a random whole number in the range from `0` to `19`.
+Recuerda que `Math.random()` nunca puede devolver un `1`, así que es imposible obtener `20` ya que estás redondeando hacia abajo con `Math.floor()`. Este proceso te dará un número entero aleatorio en el rango de `0` a `19`.
-Putting everything together, this is what your code looks like:
+Poniendo todo junto, así es como se ve nuestro código:
```js
Math.floor(Math.random() * 20);
```
-You are calling `Math.random()`, multiplying the result by 20, then passing the value to `Math.floor()` to round the value down to the nearest whole number.
+Estás llamando a `Math.random()`, multiplicando el resultado por 20 y pasando el valor a la función `Math.floor()` para redondear el valor hacia abajo al número entero más cercano.
# --instructions--
-Use this technique to generate and return a random whole number in the range from `0` to `9`.
+Utiliza esta técnica para generar y devolver un número entero aleatorio entre `0` y `9`.
# --hints--
@@ -49,7 +49,7 @@ Debes usar `Math.random` para generar un número aleatorio.
assert(code.match(/Math.random/g).length >= 1);
```
-You should have multiplied the result of `Math.random` by 10 to make it a number in the range from zero to nine.
+Debes haber multiplicado el resultado de `Math.random` por 10 para convertirlo en un número en el rango de cero a nueve.
```js
assert(
diff --git a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-within-a-range.md b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-within-a-range.md
index a997835e1d0..63368724002 100644
--- a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-within-a-range.md
+++ b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-within-a-range.md
@@ -9,11 +9,11 @@ dashedName: generate-random-whole-numbers-within-a-range
# --description--
-You can generate a random whole number in the range from zero to a given number. You can also pick a different lower number for this range.
+Puedes generar un número entero aleatorio en el rango de cero a un número determinado. También puedes elegir un número inferior diferente para este rango.
-You'll call your minimum number `min` and your maximum number `max`.
+Llamarás a tu número mínimo `min` y a tu número máximo `max`.
-This formula gives a random whole number in the range from `min` to `max`. Tómate un momento para leerla e intenta entender lo que este código está haciendo:
+Esta fórmula da un número entero aleatorio en el rango desde `min` hasta `max`. Tómate un momento para leerla e intenta entender lo que este código está haciendo:
```js
Math.floor(Math.random() * (max - min + 1)) + min
@@ -21,7 +21,7 @@ Math.floor(Math.random() * (max - min + 1)) + min
# --instructions--
-Create a function called `randomRange` that takes a range `myMin` and `myMax` and returns a random whole number that's greater than or equal to `myMin` and less than or equal to `myMax`.
+Crea una función llamada `randomRange` que tenga un rango `myMin` y `myMax` y devuelva un número entero aleatorio mayor o igual a `myMin`, y es menor o igual a `myMax`.
# --hints--
diff --git a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md
index e8445ec49cb..469171a469b 100644
--- a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md
+++ b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md
@@ -21,8 +21,8 @@ Completa la función utilizando las reglas siguientes para modificar el objeto p
- Tu función debe devolver siempre el objeto `records` completo.
- Si `value` es una cadena vacía, elimina la propiedad `prop` dada del álbum.
-- If `prop` isn't `tracks` and `value` isn't an empty string, assign the `value` to that album's `prop`.
-- If `prop` is `tracks` and value isn't an empty string, add the `value` to the end of the album's `tracks` array. You need to create this array first if the album does not have a `tracks` property.
+- Si `prop` no es `tracks` y `value` no es una cadena vacía, asigna el `value` a la `prop` de ese álbum.
+- Si `prop` es `tracks` y value no es una cadena vacía, añade el `value` al final del arreglo `tracks` del álbum. Necesitas crear este arreglo primero si el álbum no tiene una propiedad `tracks`.
**Nota:** Para las pruebas se utiliza una copia del objeto `recordCollection`. No debes modificar directamente el objeto `recordCollection`.
diff --git a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements.md b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements.md
index 10f57a6fb02..692c19679a0 100644
--- a/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements.md
+++ b/curriculum/challenges/espanol/02-javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements.md
@@ -9,7 +9,7 @@ dashedName: selecting-from-many-options-with-switch-statements
# --description--
-If you need to match one value against many options, you can use a switch statement. A `switch` statement compares the value to the case statements which define various possible values. Any valid JavaScript statements can be executed inside a case block and will run from the first matched `case` value until a `break` is encountered.
+Si necesitas coincidir un valor contra muchas opciones, puedes usar una sentencia switch. Una sentencia `switch` compara el valor para las sentencias case las cuales definen varios posibles valores. Cualquier sentencia válida JavaScript puede ser ejecutada dentro de un bloque case y se ejecutará desde el primer valor de coincidencia `case` hasta que un `break` sea encontrado.
Aquí hay un ejemplo de una declaración `switch`:
diff --git a/curriculum/challenges/espanol/03-front-end-development-libraries/jquery/target-the-parent-of-an-element-using-jquery.md b/curriculum/challenges/espanol/03-front-end-development-libraries/jquery/target-the-parent-of-an-element-using-jquery.md
index 271c381796d..c79da9571a6 100644
--- a/curriculum/challenges/espanol/03-front-end-development-libraries/jquery/target-the-parent-of-an-element-using-jquery.md
+++ b/curriculum/challenges/espanol/03-front-end-development-libraries/jquery/target-the-parent-of-an-element-using-jquery.md
@@ -10,7 +10,7 @@ dashedName: target-the-parent-of-an-element-using-jquery
Cada elemento HTML tiene un elemento `parent` (padre) del cual `inherits` (hereda) propiedades.
-For example, the `h3` element in your `jQuery Playground` has the parent element of `
`, which itself has the parent element of `body`.
+Por ejemplo, el elemento `h3` en tu `jQuery Playground` tiene el elemento padre de `
`, que en sí mismo tiene el elemento padre de `body`.
jQuery tiene una función llamada `parent()` que te permite acceder al padre del elemento que hayas seleccionado.
diff --git a/curriculum/challenges/espanol/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md b/curriculum/challenges/espanol/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md
index 8825a718ed3..857bd071a03 100644
--- a/curriculum/challenges/espanol/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md
+++ b/curriculum/challenges/espanol/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md
@@ -18,7 +18,7 @@ La directiva `@if` en Sass es útil para probar un caso específico: funciona ig
}
```
-And just like in JavaScript, the `@else if` and `@else` directives test for more conditions:
+Y al igual que en JavaScript, las directrices `@else if` y `@else` prueban más condiciones:
```scss
@mixin text-effect($val) {
@@ -39,7 +39,7 @@ And just like in JavaScript, the `@else if` and `@else` directives test for more
# --instructions--
-Crea un mixin llamado `border-stroke` que toma un parámetro `$val`. The mixin should check for the following conditions using `@if`, `@else if`, and `@else` directives:
+Crea un mixin llamado `border-stroke` que toma un parámetro `$val`. El mixin debe comprobar las siguientes condiciones utilizando las directrices `@if`, `@else if`, y `@else`:
```scss
light - 1px solid black
@@ -47,7 +47,7 @@ medium - 3px solid black
heavy - 6px solid black
```
-If the `$val` parameter value is not `light`, `medium`, or `heavy`, then the `border` property should be set to `none`.
+Si el valor del parámetro `$val` no es `light`, `medium`, o `heavy`, entonces la propiedad de `border` debe establecerse a `none`.
# --hints--
diff --git a/curriculum/challenges/espanol/04-data-visualization/json-apis-and-ajax/post-data-with-the-javascript-xmlhttprequest-method.md b/curriculum/challenges/espanol/04-data-visualization/json-apis-and-ajax/post-data-with-the-javascript-xmlhttprequest-method.md
index 69881ee1eb8..0866fe28eb2 100644
--- a/curriculum/challenges/espanol/04-data-visualization/json-apis-and-ajax/post-data-with-the-javascript-xmlhttprequest-method.md
+++ b/curriculum/challenges/espanol/04-data-visualization/json-apis-and-ajax/post-data-with-the-javascript-xmlhttprequest-method.md
@@ -26,33 +26,33 @@ const body = JSON.stringify({ userName: userName, suffix: ' loves cats!' });
xhr.send(body);
```
-Ya has visto varios de estos métodos anteriormente. Here the `open` method initializes the request as a `POST` to the given URL of the external resource, and passes `true` as the third parameter - indicating to perform the operation asynchronously.
+Ya has visto varios de estos métodos anteriormente. Aquí el método `open` inicializa la solicitud como un `POST` a la URL dada del recurso externo, y para `true` como tercer parámetro, lo que indica que realizar la operación de forma asíncrona.
-The `setRequestHeader` method sets the value of an HTTP request header, which contains information about the sender and the request. It must be called after the `open` method, but before the `send` method. The two parameters are the name of the header and the value to set as the body of that header.
+El método `setRequestHeader` establece el valor de un encabezado de solicitud HTTP, que contiene información sobre el remitente y la solicitud. Debe ser llamado después del método `open`, pero antes del método `send`. Los dos parámetros son el nombre de encabezado y el valor a establecer como el cuerpo de ese encabezado.
-Next, the `onreadystatechange` event listener handles a change in the state of the request. A `readyState` of `4` means the operation is complete, and a `status` of `201` means it was a successful request. Therefore, the document's HTML can be updated.
+A continuación, el detector de eventos `onreadystatechange` maneja un cambio en el estado de la solicitud. Un `readyState` de `4` significa que la operación está completa, y un `status` de `201` significa que fue una solicitud exitosa. Por lo tanto, el HTML del documento puede ser actualizado.
-Finally, the `send` method sends the request with the `body` value. The `body` consists of a `userName` and a `suffix` key.
+Finalmente, el método `send` envía la solicitud con el valor `body`. El `body` consiste en un `userName` y una clave `suffix`.
# --instructions--
-Update the code so it makes a `POST` request to the API endpoint. Then type your name in the input field and click `Send Message`. Your AJAX function should replace `Reply from Server will be here.` with data from the server. Format the response to display your name appended with the text `loves cats`.
+Actualiza el código para que hagas una solicitud `POST` al endpoint de la API. Luego escribe tu nombre en el campo de entrada y haz clic en `Send Message`. Tu función AJAX debe reemplazar `Reply from Server will be here.` con los datos del servidor. Formatea la respuesta para mostrar tu nombre adjuntado con el texto `loves cats`.
# --hints--
-Your code should create a new `XMLHttpRequest`.
+Tu código debe crear un nuevo `XMLHttpRequest`.
```js
assert(code.match(/new\s+?XMLHttpRequest\(\s*?\)/g));
```
-Your code should use the `open` method to initialize a `POST` request to the server.
+Tu código debe utilizar el método `open` para inicializar una solicitud `POST` a al servidor.
```js
assert(code.match(/\.open\(\s*?('|")POST\1\s*?,\s*?url\s*?,\s*?true\s*?\)/g));
```
-Your code should use the `setRequestHeader` method.
+Tu código debe utilizar el método `setRequestHeader`.
```js
assert(
@@ -62,13 +62,13 @@ assert(
);
```
-Your code should have an `onreadystatechange` event handler set to a function.
+Tu código debe tener un manejador de eventos `onreadystatechange` establecido a una función.
```js
assert(code.match(/\.onreadystatechange\s*?=/g));
```
-Your code should get the element with class `message` and change its `textContent` to `userName loves cats`
+Tu código debe obtener el elemento con la clase `message` y cambiar su `textContent` a `userName loves cats`
```js
assert(
@@ -78,7 +78,7 @@ assert(
);
```
-Your code should use the `send` method.
+Tu código debe usar el método `send`.
```js
assert(code.match(/\.send\(\s*?body\s*?\)/g));
diff --git a/curriculum/challenges/espanol/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/espanol/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index 1016bbdbdee..3f70decea22 100644
--- a/curriculum/challenges/espanol/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/espanol/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Number Sorter
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/espanol/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/german/00-certifications/responsive-web-design-certification/responsive-web-design-certification.yml b/curriculum/challenges/german/00-certifications/responsive-web-design-certification/responsive-web-design-certification.yml
index 27093b61d7b..9930203ae15 100644
--- a/curriculum/challenges/german/00-certifications/responsive-web-design-certification/responsive-web-design-certification.yml
+++ b/curriculum/challenges/german/00-certifications/responsive-web-design-certification/responsive-web-design-certification.yml
@@ -7,7 +7,7 @@ isPrivate: true
tests:
-
id: bd7158d8c442eddfaeb5bd18
- title: Erstelle einer Tributseite
+ title: Erstellung einer Tributseite
-
id: 587d78af367417b2b2512b03
title: Erstellung eines Umfrageformulars
diff --git a/curriculum/challenges/german/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/german/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index cecfd633b1c..34d65f401f8 100644
--- a/curriculum/challenges/german/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/german/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Number Sorter
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/german/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/italian/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/italian/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index 96a269522da..a54b278658a 100644
--- a/curriculum/challenges/italian/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/italian/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Number Sorter
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d128eaedcc773d2ded2128.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d128eaedcc773d2ded2128.md
index 13047472853..a8d0f0af0b0 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d128eaedcc773d2ded2128.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d128eaedcc773d2ded2128.md
@@ -26,79 +26,79 @@ L'array `myFavoriteFootballTeam.players` dovrebbe avere due valori.
assert.isAtLeast(myFavoriteFootballTeam.players.length, 2);
```
-Your `myFavoriteFootballTeam.players` array should have an object as the second value.
+L'array `myFavoriteFootballTeam.players` dovrebbe avere un oggetto come secondo valore.
```js
assert.isObject(myFavoriteFootballTeam.players[1])
```
-Your new object should have a `name` property.
+Il nuovo oggetto dovrebbe avere una proprietà `name`.
```js
assert.property(myFavoriteFootballTeam.players[1], 'name');
```
-Your `name` property should be set to `Sergio Batista`.
+La proprietà `name` dovrebbe essere impostata su `Sergio Batista`.
```js
assert.equal(myFavoriteFootballTeam.players[1]?.name, 'Sergio Batista');
```
-Your new object should have a `position` property.
+Il nuovo oggetto dovrebbe avere una proprietà `position`.
```js
assert.property(myFavoriteFootballTeam.players[1], 'position');
```
-Your `position` property should be set to `midfielder`.
+La proprietà `position` dovrebbe essere impostata su `midfielder`.
```js
assert.equal(myFavoriteFootballTeam.players[1]?.position, 'midfielder');
```
-Your new object should have a `number` property.
+Il nuovo oggetto dovrebbe avere una proprietà `number`.
```js
assert.property(myFavoriteFootballTeam.players[1], 'number');
```
-Your `number` property should be a number.
+La proprietà `number` dovrebbe essere un numero.
```js
assert.isNumber(myFavoriteFootballTeam.players[1]?.number);
```
-Your `number` property should be set to `2`.
+La proprietà `number` dovrebbe essere impostata su `2`.
```js
assert.equal(myFavoriteFootballTeam.players[1]?.number, 2);
```
-Your new object should have a `isCaptain` property.
+Il nuovo oggetto dovrebbe avere una proprietà `isCaptain`.
```js
assert.property(myFavoriteFootballTeam.players[1], 'isCaptain');
```
-Your `isCaptain` property should be a boolean.
+La proprietà `isCaptain` dovrebbe essere un booleano.
```js
assert.isBoolean(myFavoriteFootballTeam.players[1]?.isCaptain);
```
-Your `isCaptain` property should be set to `false`.
+La proprietà `isCaptain` dovrebbe essere impostata su `false`.
```js
assert.equal(myFavoriteFootballTeam.players[1]?.isCaptain, false);
```
-Your new object should have a `nickname` property.
+Il nuovo oggetto dovrebbe avere una proprietà `nickname`.
```js
assert.property(myFavoriteFootballTeam.players[1], 'nickname');
```
-Your `nickname` property should be set to `null`.
+La proprietà `nickname` dovrebbe essere impostata su `null`.
```js
assert.isNull(myFavoriteFootballTeam.players[1]?.nickname);
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d12b9c7aaee43de1ba265d.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d12b9c7aaee43de1ba265d.md
index e117f81605f..e0efde2abf3 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d12b9c7aaee43de1ba265d.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d12b9c7aaee43de1ba265d.md
@@ -7,16 +7,16 @@ dashedName: step-14
# --description--
-The rest of the data for the `myFavoriteFootballTeam.players` array has been filled out for you.
+Il resto dei dati per l'array `myFavoriteFootballTeam.players` è stato aggiunto per te.
-The next step is to ensure that you can't modify this object by adding or removing any properties. We are going to use a method called `Object.freeze(obj)` which will freeze this object and prevent any changes being made to it.
+Il prossimo passo è assicurarti di non poter modificare quest'oggetto aggiungendo o rimuovendo delle proprietà. Stiamo per usare un metodo chiamato `Object.freeze(obj)` che congelerà questo oggetto e impedirà che gli vengano apportate modifiche.
-Use the `Object.freeze()` method to freeze the `myFavoriteFootballTeam` object.
+Usa il metodo `Object.freeze()` per congelare l'oggetto `myFavoriteFootballTeam`.
# --hints--
-You should use the `Object.freeze()` method to freeze the `myFavoriteFootballTeam` object.
+Dovresti usare il metodo `Object.freeze()` per congelare l'oggetto `myFavoriteFootballTeam`.
```js
assert.isFrozen(myFavoriteFootballTeam);
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d12fe2a595263e8f5084f7.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d12fe2a595263e8f5084f7.md
index 6e03cf91edf..2a5081f1193 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d12fe2a595263e8f5084f7.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63d12fe2a595263e8f5084f7.md
@@ -7,15 +7,15 @@ dashedName: step-15
# --description--
-To check if the `Object.freeze()` method is working, you can try to assign a new value to one of the existing properties.
+Per verificare se il metodo `Object.freeze()` sta funzionando, puoi provare ad assegnare un nuovo valore a una delle proprietà esistenti.
-Below the `Object.freeze(myFavoriteFootballTeam)`, assign the `USA` string to `myFavoriteFootballTeam.team`. Below that, add a `console.log` for `myFavoriteFootballTeam.team`.
+Sotto `Object.freeze(myFavoriteFootballTeam)`, assegna la stringa `USA` a `myFavoriteFootballTeam.team`. Di seguito, aggiungi un `console.log` per `myFavoriteFootballTeam.team`.
-When you open up the console, you will see an `Uncaught TypeError` message. This error appears because the `Object.freeze()` method does not allow you to overwrite that value.
+Aprendo la console vedrai il messaggio `Uncaught TypeError`. Questo errore appare perché il metodo `Object.freeze()` non consente di sovrascrivere quel valore.
# --hints--
-You should assign the `USA` string to `myFavoriteFootballTeam.team`.
+Dovresti assegnare la stringa `USA` a `myFavoriteFootballTeam.team`.
```js
@@ -23,7 +23,7 @@ assert.match(code, /myFavoriteFootballTeam\.team\s*=\s*('|"|`)USA\1\s*/);
```
-You should add a `console.log` for `myFavoriteFootballTeam.team`.
+Dovresti aggiungere un `console.log` per `myFavoriteFootballTeam.team`.
```js
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e02a333354343b595d64ca.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e02a333354343b595d64ca.md
index c9a4a2ad0f4..8ca919e108a 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e02a333354343b595d64ca.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e02a333354343b595d64ca.md
@@ -7,27 +7,27 @@ dashedName: step-16
# --description--
-Now that you have tested the `Object.freeze()` method, you can delete those two lines of code from the last lesson.
+Ora che hai testato il metodo `Object.freeze()`, puoi eliminare le due righe di codice dello step precedente.
The next step is to access the `key` called `sport` from the `myFavoriteFootballTeam` object and assign it to a new `const` variable called `sport`.
-Remember you can use dot notation for this.
+Ricorda che puoi usare la notazione con punto per questo.
# --hints--
-You should remove your assignment of the `USA` string to `myFavoriteFootballTeam.team`.
+Dovresti rimuovere l'assegnazione della stringa `USA` a `myFavoriteFootballTeam.team`.
```js
assert.notMatch(code, /myFavoriteFootballTeam\.team\s*=\s*('|"|`)USA\1\s*/);
```
-You should remove your `console.log` for `myFavoriteFootballTeam.team`.
+Dovresti rimuovere il `console.log` per `myFavoriteFootballTeam.team`.
```js
assert.notMatch(code, /console\.log\(\s*myFavoriteFootballTeam\.team\s*\)/);
```
-You should use `const` to declare a `sport` variable.
+Dovresti usare `const` per dichiarare la variabile `sport`.
```js
assert.match(code, /const\s+sport\s*=/);
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e0334b7a24bd3c96aca4de.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e0334b7a24bd3c96aca4de.md
index f95ca095c29..cb5fb399a2f 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e0334b7a24bd3c96aca4de.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e0334b7a24bd3c96aca4de.md
@@ -11,7 +11,7 @@ Below the `sport` variable, access the `key` called `team` from the `myFavoriteF
# --hints--
-You should use `const` to declare a `team` variable.
+Dovresti usare `const` per dichiarare la variabile `team`.
```js
assert.match(code, /const\s+team\s*=/);
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e036373fc9173d284e165a.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e036373fc9173d284e165a.md
index ce0835fa4d9..ea087fbaa2f 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e036373fc9173d284e165a.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e036373fc9173d284e165a.md
@@ -7,9 +7,9 @@ dashedName: step-18
# --description--
-In the last two steps, you have been accessing properties from the `myFavoriteFootballTeam` object using dot notation and assigning them to new `const` variables. But in JavaScript, there is an easier way to accomplish the same goal.
+Negli ultimi due step, hai potuto accedere alle proprietà dall'oggetto `myFavoriteFootballTeam` usando la notazione con punto e hai assegnato le nuove variabili con `const`. Ma in JavaScript, c'è un modo più facile per raggiungere lo stesso obiettivo.
-The object destructuring syntax allows you to unpack values from arrays and objects:
+La sintassi di destrutturazione degli oggetti ti consente di spacchettare valori da array e oggetti:
```js
const developerObj = {
@@ -21,11 +21,11 @@ const developerObj = {
const { name, isDeveloper } = developerObj;
```
-Rewrite the two lines of code below using the new destructuring syntax. Your answer should be one line of code.
+Riscrivi le due righe di codice qui sotto usando la nuova sintassi di destrutturazione. La tua risposta dovrebbe essere una riga di codice.
# --hints--
-Use object destructuring to access the `sport` and `team` values.
+Usa la destrutturazione degli oggetti per accedere ai valori `sport` e `team`.
```js
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e03b86008bbb3e1c3de846.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e03b86008bbb3e1c3de846.md
index de3439a814b..d92e4fa4405 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e03b86008bbb3e1c3de846.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e03b86008bbb3e1c3de846.md
@@ -7,11 +7,11 @@ dashedName: step-19
# --description--
-Next, add the `year` and `players` to your destructuring assignment.
+Adesso aggiungi `year` e `players` all'assegnazione destrutturante.
# --hints--
-You should add the `year` and `players` values to your destructuring assignment.
+Dovresti aggiungere i valori `year` e `players` all'assegnazione destrutturante.
```js
assert.match(code, /const\s*{\s*((sport\s*,\s*team\s*,\s*year\s*,\s*players)|(team\s*,\s*sport\s*,\s*year\s*,\s*players)|(year\s*,\s*sport\s*,\s*team\s*,\s*players)|(sport\s*,\s*year\s*,\s*team\s*,\s*players)|(team\s*,\s*year\s*,\s*sport\s*,\s*players)|(year\s*,\s*team\s*,\s*sport\s*,\s*players)|(year\s*,\s*team\s*,\s*players\s*,\s*sport)|(team\s*,\s*year\s*,\s*players\s*,\s*sport)|(players\s*,\s*year\s*,\s*team\s*,\s*sport)|(year\s*,\s*players\s*,\s*team\s*,\s*sport)|(team\s*,\s*players\s*,\s*year\s*,\s*sport)|(players\s*,\s*team\s*,\s*year\s*,\s*sport)|(players\s*,\s*sport\s*,\s*year\s*,\s*team)|(sport\s*,\s*players\s*,\s*year\s*,\s*team)|(year\s*,\s*players\s*,\s*sport\s*,\s*team)|(players\s*,\s*year\s*,\s*sport\s*,\s*team)|(sport\s*,\s*year\s*,\s*players\s*,\s*team)|(year\s*,\s*sport\s*,\s*players\s*,\s*team)|(team\s*,\s*sport\s*,\s*players\s*,\s*year)|(sport\s*,\s*team\s*,\s*players\s*,\s*year)|(players\s*,\s*team\s*,\s*sport\s*,\s*year)|(team\s*,\s*players\s*,\s*sport\s*,\s*year)|(sport\s*,\s*players\s*,\s*team\s*,\s*year)|(players\s*,\s*sport\s*,\s*team\s*,\s*year))\s*}\s*=\s*myFavoriteFootballTeam\s*/);
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e042661ad2663f0d468740.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e042661ad2663f0d468740.md
index 95eda5017a7..d04587e87fa 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e042661ad2663f0d468740.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e042661ad2663f0d468740.md
@@ -7,11 +7,11 @@ dashedName: step-20
# --description--
-Now you need to access the `coachName` value from the `myFavoriteFootballTeam.headCoach` object using the destructuring syntax.
+Ora devi accedere al valore `coachName` dall'oggetto `myFavoriteFootballTeam.headCoach` utilizzando la sintassi di destrutturazione.
# --hints--
-Use object destructuring to access the `coachName` value.
+Usa la destrutturazione degli oggetti per accedere al valore di `coachName`.
```js
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e050bf935ac341b88326d6.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e050bf935ac341b88326d6.md
index 8179fd09158..71fd2dad160 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e050bf935ac341b88326d6.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e050bf935ac341b88326d6.md
@@ -7,15 +7,15 @@ dashedName: step-21
# --description--
-Now you need to start displaying the team's information on the screen.
+Ora devi iniziare a mostrare le informazioni della squadra sullo schermo.
-Below your destructuring assignments, assign the `sport` variable to `typeOfSport.innerHTML`. Remember that the `innerHTML` property sets the HTML for that particular element.
+Sotto le assegnazioni di destrutturazione, assegna la variabile `sport` a `typeOfSport.innerHTML`. Ricorda che la proprietà `innerHTML` imposta l'HTML per un particolare elemento.
-Once you complete that task, you should see the result in the preview window.
+Una volta terminato questo compito dovresti essere in grado di vedere il risultato nella finestra di anteprima.
# --hints--
-You should assign the `sport` variable to `typeOfSport.innerHTML`.
+Dovresti assegnare la variabile `sport` a `typeOfSport.innerHTML`.
```js
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e05557016dfd45ea49152c.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e05557016dfd45ea49152c.md
index 587342d8d66..d30fd8ff5a7 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e05557016dfd45ea49152c.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e05557016dfd45ea49152c.md
@@ -7,11 +7,11 @@ dashedName: step-22
# --description--
-Below `typeOfSport.innerHTML`, assign the `team` variable to `teamName.innerHTML`.
+Sotto `typeOfSport.innerHTML`, assegna la variabile `team` a `teamName.innerHTML`.
# --hints--
-You should assign the `team` variable to `teamName.innerHTML`.
+Dovresti assegnare la variabile `team` a `teamName.innerHTML`.
```js
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e05c00b615bb46ac87273a.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e05c00b615bb46ac87273a.md
index fd77bba607c..1e0d9bb81db 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e05c00b615bb46ac87273a.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e05c00b615bb46ac87273a.md
@@ -7,13 +7,13 @@ dashedName: step-23
# --description--
-Below `teamName.innerHTML`, assign the `year` variable to `worldCupYear.innerHTML`. Below that, assign the `coachName` variable to `headCoach.innerHTML`.
+Sotto `teamName.innerHTML`, assegna la variabile `year` a `worldCupYear.innerHTML`. Sotto questa, assegna la variabile `coachName` a `headCoach.innerHTML`.
-You should now see all of that information displayed on the screen below `Team stats`.
+Ora dovresti vedere tutte queste informazioni sullo schermo sotto `Team stats`.
# --hints--
-You should assign the `year` variable to `worldCupYear.innerHTML`.
+Dovresti assegnare la variabile `year` a `worldCupYear.innerHTML`.
```js
@@ -21,7 +21,7 @@ assert.match(code, /worldCupYear.innerHTML\s*=\s*year\s*/)
```
-You should assign the `coachName` variable to `headCoach.innerHTML`.
+Dovresti assegnare la variabile `coachName` a `headCoach.innerHTML`.
```js
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e060df21bca347b2d2b374.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e060df21bca347b2d2b374.md
index 64e5e01482a..0f2e80daeda 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e060df21bca347b2d2b374.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e060df21bca347b2d2b374.md
@@ -7,38 +7,38 @@ dashedName: step-24
# --description--
-Now you will start building out the function that will show player cards based on the selections made by the user in the `Filter Teammates` dropdown menu.
+Ora inizierai a costruire la funzione che mostrerà le figurine dei giocatori in base alle selezioni effettuate dall'utente nel menu a discesa `Filter Teammates`.
-Start by creating an empty arrow function called `setPlayerCards`. You do not need to add a parameter because that will be taken care of in the next step.
+Inizia creando una funzione freccia vuota chiamata `setPlayerCards`. Non è necessario aggiungere un parametro perché te ne occuperai nel prossimo step.
# --hints--
-You should use `const` to declare a `setPlayerCards` variable.
+Dovresti usare `const` per dichiarare una variabile `setPlayerCards`.
```js
assert.match(code, /const\s+setPlayerCards\s*=/);
```
-Your `setPlayerCards` variable should be a function.
+La variabile `setPlayerCards` dovrebbe essere una funzione.
```js
assert.isFunction(setPlayerCards);
```
-Your `setPlayerCards` function should use arrow syntax.
+La funzione `setPlayerCards` dovrebbe utilizzare la sintassi freccia.
```js
assert.match(code, /const\s+setPlayerCards\s*=\s*\(.*\)\s*=>/);
```
-Your `setPlayerCards` function should not take a parameter.
+La funzione `setPlayerCards` non dovrebbe prendere alcun parametro.
```js
assert.match(code, /const\s+setPlayerCards\s*=\s*\(\s*\)\s*=>/);
```
-Your `setPlayerCards` function should be empty.
+La funzione `setPlayerCards` dovrebbe essere vuota.
```js
assert.match(code, /const\s+setPlayerCards\s*=\s*\(\s*\)\s*=>\s*{\s*}/);
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e062d6090ebb486a4eda3a.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e062d6090ebb486a4eda3a.md
index e2fd95b4278..7dea22bdad2 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e062d6090ebb486a4eda3a.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e062d6090ebb486a4eda3a.md
@@ -7,7 +7,7 @@ dashedName: step-25
# --description--
-Function parameters can be initialized with default values. If a function is called without an argument, then the default value will be used:
+I parametri di funzione possono essere inizializzati con valori predefiniti. Se una funzione viene chiamata senza argomento, verrà utilizzato il valore predefinito:
```js
const greeting = (name = "Anonymous") => {
@@ -18,17 +18,17 @@ console.log(greeting("John")); // Hello John
console.log(greeting()); // Hello Anonymous
```
-Add a new parameter to your `setPlayerCards` function called `arr` and assign it a default value of `players`.
+Aggiungi un nuovo parametro chiamato `arr` alla funzione `setPlayerCards` e assegnagli il valore predefinito `players`.
# --hints--
-Your `setPlayerCards` function should take an `arr` parameter.
+La funzione `setPlayerCards` dovrebbe prendere un parametro `arr`.
```js
assert.match(code, /const\s+setPlayerCards\s*=\s*\(\s*arr/);
```
-Your `arr` parameter should have a default value of `players`.
+Il parametro `arr` dovrebbe avere il valore predefinito `players`.
```js
assert.match(code, /const\s+setPlayerCards\s*=\s*\(\s*arr\s*=\s*players\s*\)/);
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e949b8327aa2aca2ca8eac.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e949b8327aa2aca2ca8eac.md
index c5f10540ae0..ddfe97fa316 100644
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e949b8327aa2aca2ca8eac.md
+++ b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-modern-javascript-methods-by-building-football-team-cards/63e949b8327aa2aca2ca8eac.md
@@ -7,33 +7,33 @@ dashedName: step-26
# --description--
-The next step is to create a new array that will be responsible for adding the player card information to the page.
+Il prossimo passo è creare un nuovo array che aggiungerà sulla pagina le informazioni della figurina del giocatore.
-Inside the `setPlayerCards` function, start by adding the `map` method to `arr` that will take in an empty callback function. Then, use the addition assignment `+=` operator to assign the new array to `playerCards.innerHTML`.
+All'interno della funzione `setPlayerCards`, inizia aggiungendo ad `arr` il metodo `map` che prenderà una funzione callback vuota. Quindi, utilizza l'operatore di assegnazione composta `+=` per assegnare `playerCards.innerHTML` al nuovo array.
-Remember that the `innerHTML` property gets, or in this case, sets the HTML markup for the `playerCards` element.
+Ricorda che la proprietà `innerHTML` ottiene o, in questo caso, imposta il markup HTML per l'elemento `playerCards`.
# --hints--
-You should call the `.map()` method on your `arr` parameter.
+Dovresti chiamare il metodo `.map()` sul parametro `arr`.
```js
assert.match(setPlayerCards.toString(), /arr\.map\(.*\)/);
```
-Your `.map()` method should take an empty callback function.
+Il metodo `.map()` dovrebbe avere una funzione callback vuota.
```js
assert.match(code, /arr\.map\(\s*\(\s*\)\s*=>\s*\{\s*\}\s*\)/);
```
-You should use the `+=` operator on `playerCards.innerHTML`.
+Dovresti usare l'operatore `+=` su `playerCards.innerHTML`.
```js
assert.match(setPlayerCards.toString(), /playerCards\.innerHTML\s*\+=/);
```
-You should assign `arr.map()` to the `playerCards.innerHTML` using the `+=` operator.
+Dovresti assegnare `playerCards.innerHTML` ad `arr.map()` usando l'operatore `+=`.
```js
assert.match(code, /playerCards\.innerHTML\s+\+=\s*arr\.map\(\s*\(\s*\)\s*=>\s*\{\s*\}\s*\)/)
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/italian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/japanese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/japanese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index 704fc77febc..8a4fe530821 100644
--- a/curriculum/challenges/japanese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/japanese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Number Sorter
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/japanese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/portuguese/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md b/curriculum/challenges/portuguese/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md
index 3df0eb30112..f3e98261677 100644
--- a/curriculum/challenges/portuguese/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md
+++ b/curriculum/challenges/portuguese/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md
@@ -18,7 +18,7 @@ A diretiva `@if` no Sass é útil para testar um caso específico - funciona exa
}
```
-And just like in JavaScript, the `@else if` and `@else` directives test for more conditions:
+Assim como em JavaScript, as diretivas `@else if` e `@else` testam para mais condições:
```scss
@mixin text-effect($val) {
@@ -39,7 +39,7 @@ And just like in JavaScript, the `@else if` and `@else` directives test for more
# --instructions--
-Crie um mixin chamado `border-stroke` que recebe o parâmetro `$val`. The mixin should check for the following conditions using `@if`, `@else if`, and `@else` directives:
+Crie um mixin chamado `border-stroke` que recebe o parâmetro `$val`. O mixin deve verificar as seguintes condições usando as diretivas `@if`, `@else if` e `@else`:
```scss
light - 1px solid black
@@ -47,7 +47,7 @@ medium - 3px solid black
heavy - 6px solid black
```
-If the `$val` parameter value is not `light`, `medium`, or `heavy`, then the `border` property should be set to `none`.
+Se o parâmetro `$val` não for `light`, `medium` ou `heavy`, a propriedade `border` deve ser ajustada para `none`.
# --hints--
diff --git a/curriculum/challenges/portuguese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/portuguese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index 09ded627cc2..76163895b95 100644
--- a/curriculum/challenges/portuguese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/portuguese/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6350854411ffb73feb6bb84e.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6350854411ffb73feb6bb84e.md
index b0dd8f59b53..e7987905ac3 100644
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6350854411ffb73feb6bb84e.md
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6350854411ffb73feb6bb84e.md
@@ -1,25 +1,25 @@
---
id: 6350854411ffb73feb6bb84e
-title: Step 12
+title: Passo 12
challengeType: 0
dashedName: step-12
---
# --description--
-The `.reduce()` method takes a second parameter that is used as the initial value of the accumulator. Without a second parameter, the `.reduce()` method uses the first element of the array as the accumulator, which can lead to unexpected results.
+O método `.reduce()` recebe um segundo parâmetro que é usado como o valor inicial do acumulador. Sem um segundo parâmetro, o método `.reduce()` usa o primeiro elemento do array como o acumulador, o que pode levar a resultados inesperados.
-To be safe, it's best to set an initial value. Here is an example of setting the initial value to an empty string:
+Para garantir, é melhor definir um valor inicial. Aqui está um exemplo de configuração do valor inicial para uma string vazia:
```js
array.reduce((acc, el) => acc + el.toLowerCase(), "");
```
-Set the initial value of the accumulator to `0`.
+Defina o valor inicial do acumulador como `0`.
# --hints--
-Your `reduce` method should have `0` as the initial value.
+O método `reduce` deve ter `0` como valor inicial.
```js
assert.match(getMean.toString(), /(array\.reduce\(\(acc\s*,\s*el\s*\)\s*=>|array\.reduce\(function\s*\(acc\s*,\s*el\)\s*\{)\s*(return)?\s*acc\s*\+\s*el;\s*\}?\s*,\s*0\)/)
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635085da54fc2041e0303e75.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635085da54fc2041e0303e75.md
index 0ff64ecf7b7..0fdb7eebe6f 100644
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635085da54fc2041e0303e75.md
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635085da54fc2041e0303e75.md
@@ -1,6 +1,6 @@
---
id: 635085da54fc2041e0303e75
-title: Step 14
+title: Passo 14
challengeType: 0
dashedName: step-14
---
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/63508bb4afb069534e81f33b.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/63508bb4afb069534e81f33b.md
index 17f62174f30..9a8152f0bc4 100644
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/63508bb4afb069534e81f33b.md
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/63508bb4afb069534e81f33b.md
@@ -7,19 +7,19 @@ dashedName: step-20
# --description--
-O primeiro passo para o cálculo da mediana é assegurar que a lista de números seja classificada do menor para o maior. Once again, there is an array method ideal for this – the `.sort()` method.
+O primeiro passo para o cálculo da mediana é assegurar que a lista de números seja classificada do menor para o maior. Novamente, há um método de array ideal para isso – o método `.sort()`.
-Declare a `sorted` variable and assign `array.sort()` to it.
+Declare a variável `sorted` e atribua `array.sort()` a ela.
# --hints--
-Your `getMedian` function should have a `sorted` variable.
+A função `getMedian` deve ter uma variável `sorted`.
```js
assert.match(getMedian.toString(), /sorted\s*=/);
```
-Your `getMedian` function should assign `array.sort()` to the `sorted` variable.
+A função `getMedian` deve atribuir `array.sort()` à variável `sorted`.
```js
assert.match(getMedian.toString(), /sorted\s*=\s*array\.sort\(\s*\);/);
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635090f47eb6d9563a6fed05.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635090f47eb6d9563a6fed05.md
index f6e0343b71c..373d39d9ee5 100644
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635090f47eb6d9563a6fed05.md
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635090f47eb6d9563a6fed05.md
@@ -1,43 +1,43 @@
---
id: 635090f47eb6d9563a6fed05
-title: Step 22
+title: Passo 22
challengeType: 0
dashedName: step-22
---
# --description--
-The next step is to find the number in the middle of the list. If the list has an odd number of numbers, the middle number is the median. If the list has an even number of numbers, the median is the average of the two middle numbers.
+O próximo passo é encontrar o número no meio da lista. Se a lista tem um número ímpar de números, o número do meio é a mediana. Se a lista tem um número par de números, a mediana é a média dos dois números do meio.
-You can check if a number is even or odd with the modulus operator, which is represented by the `%` symbol. This operator returns the remainder of the division of two numbers. If the remainder is `0`, the number is even. If the remainder is `1`, the number is odd:
+Você pode verificar se um número é par ou ímpar com o operador de módulo, que é representado pelo símbolo `%`. Esse operador retorna o resto da divisão de dois números. Se o resto for `0`, o número é par. Se o resto for `1`, o número é ímpar:
```js
array.length % 2 === 0;
```
-Declare a `median` variable. Using the ternary operator, check if the length of `array` is even. If the length of `array` is even, find the two middle numbers and calculate the mean of those numbers. If the length of `array` is odd, find the middle number and assign it to the `median` variable.
+Declara uma variável `median`. Usando o operador ternário, verifique se o comprimento do `array` é par. Se o comprimento do `array` for par, encontre os dois números do meio e calcule a média desses números. Se o comprimento da `array` for ímpar, encontre o número do meio e atribua-o à variável `median`.
# --hints--
-Your `getMedian` function should have a `median` variable.
+A função `getMedian` deve ter uma variável `median`.
```js
assert.match(getMedian.toString(), /median\s*=/);
```
-Your `median` variable should use a ternary operator to check if the `array.length` is even.
+A variável `median` deve usar um operador ternário para verificar se `array.length` é par.
```js
assert.match(getMedian.toString(), /median\s*=\s*array\.length\s*%\s*2\s*===\s*0\s*\?/);
```
-If the `array.length` is even, your `median` variable should use the `getMean` function to calculate the mean of the two middle numbers. Your first argument should be the value of `sorted` at `array.length / 2`, and the second at `array.length / 2 - 1`.
+Se `array.length` for par, a variável `median` deve usar a função `getMean` para calcular a média dos dois números do meio. O primeiro argumento deve ser o valor de `sorted` em `array.length / 2` e o segundo em `array.length / 2 - 1`.
```js
assert.match(getMedian.toString(), /median\s*=\s*array\.length\s*%\s*2\s*===\s*0\s*\?\s*getMean\(\s*\[sorted\[array\.length\s*\/\s*2\]\s*,\s*sorted\[\s*array\.length\s*\/\s*2\s*-\s*1\]\]\)\s*\:/);
```
-If the `array.length` is odd, your `median` variable should assign the middle number to the `median` variable. The middle number is the value of `sorted` at `Math.floor(array.length / 2)`.
+Se `array.length` for ímpar, sua variável `median` deverá atribuir o número do meio à variável `median`. O número do meio é o valor de `sorted` em `Math.floor(array.length / 2)`.
```js
assert.match(getMedian.toString(), /median\s*=\s*array\.length\s*%\s*2\s*===\s*0\s*\?\s*getMean\(\s*\[sorted\[array\.length\s*\/\s*2\]\s*,\s*sorted\[\s*array\.length\s*\/\s*2\s*-\s*1\]\]\)\s*\:\s*sorted\[\s*Math\.floor\(\s*array\.length\s*\/\s*2\)\];/);
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635091f8dbf554575fb5aa0c.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635091f8dbf554575fb5aa0c.md
index 5306ff72463..92b07dbe5e0 100644
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635091f8dbf554575fb5aa0c.md
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/635091f8dbf554575fb5aa0c.md
@@ -1,19 +1,19 @@
---
id: 635091f8dbf554575fb5aa0c
-title: Step 23
+title: Passo 23
challengeType: 0
dashedName: step-23
---
# --description--
-Finally, return the value of `median`.
+Por fim, retorne o valor de `median`.
-Like the `getMean` function, you could condense this code into one line and reduce the number of variables you instantiate. However, it is important to remember that shorter code is not always better code. In this case, reducing the lines of code would make the code harder to read and understand, impacting future maintainability.
+Como na função `getMean`, você pode condensar esse código em uma linha e reduzir o número de variáveis que você instancia. No entanto, é importante lembrar-se de que o código mais curto nem sempre é o melhor. Neste caso, reduzir as linhas de código tornaria o código mais difícil de ler e entender, afetando a futura manutenção.
# --hints--
-Your `getMedian` function should return the value of `median`.
+A função `getMedian` deve retornar o valor de `median`.
```js
assert.match(getMedian.toString(), /return\s+median;/);
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352ebd3ab962c168a122e85.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352ebd3ab962c168a122e85.md
index b7b8aa2f930..203ca7af2be 100644
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352ebd3ab962c168a122e85.md
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352ebd3ab962c168a122e85.md
@@ -1,31 +1,31 @@
---
id: 6352ebd3ab962c168a122e85
-title: Step 29
+title: Passo 29
challengeType: 0
dashedName: step-29
---
# --description--
-Now you need to find the value that occurs with the highest frequency. You'll use the `Object.keys()` method for this.
+Agora, você precisa encontrar o valor que ocorre com a maior frequência. Você usará o método `Object.keys()` para isso.
-Start by declaring a `highest` variable, and assigning it the value of the `counts` object's `Object.keys()` method.
+Comece declarando uma variável `highest` e atribuindo a ela o valor do método `Object.keys()` do objeto `counts`.
# --hints--
-Your `getMode` function should have a `highest` variable.
+A função `getMode` deve ter uma variável `highest`.
```js
assert.match(getMode.toString(), /highest\s*=/);
```
-Your `getMode` function should use the `Object.keys()` method to get the keys of the `counts` object.
+A função `getMode` deve ter o método `Object.keys()` para obter as chaves do objeto `counts`.
```js
assert.match(getMode.toString(), /Object\.keys\(\s*counts\s*\)/);
```
-Your `getMode` function should use the `Object.keys()` method to get the keys of the `counts` object and assign them to the `highest` variable.
+A função `getMode` deve usar o método `Object.keys()` para obter as chaves do objeto `counts` e atribuí-las à variável `highest`.
```js
assert.match(getMode.toString(), /highest\s*=\s*Object\.keys\(\s*counts\s*\)/);
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352f2526dccb523150b64fb.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352f2526dccb523150b64fb.md
index d562fff11bf..1293462e812 100644
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352f2526dccb523150b64fb.md
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352f2526dccb523150b64fb.md
@@ -1,23 +1,23 @@
---
id: 6352f2526dccb523150b64fb
-title: Step 36
+title: Passo 36
challengeType: 0
dashedName: step-36
---
# --description--
-Add the logic for calculating and displaying the range to your `calculate` function.
+Adicione a lógica para calcular e exibir o intervalo para a função `calculate`.
# --hints--
-Your `calculate` function should set a `range` variable to the result of `getRange(numbers)`.
+A função `calculate` deve definir uma variável `range` para o resultado de `getRange(numbers)`.
```js
assert.match(calculate.toString(), /range\s*=\s*getRange\(numbers\);/);
```
-Your `calculate` function should set the `#range` element's `textContent` to the `range` variable.
+A função `calculate` deve definir o `textContent` do elemento `#range` para a variável `range`.
```js
assert.match(calculate.toString(), /document\.querySelector\(('|")#range\1\)\.textContent\s*=\s*range;/);
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352faf71a9db52631864634.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352faf71a9db52631864634.md
index 5deeebe823b..40a6dade337 100644
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352faf71a9db52631864634.md
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-advanced-array-methods-by-building-a-statistics-calculator/6352faf71a9db52631864634.md
@@ -1,35 +1,35 @@
---
id: 6352faf71a9db52631864634
-title: Step 38
+title: Passo 38
challengeType: 0
dashedName: step-38
---
# --description--
-The next step is to calculate how far each element is from the mean. Declare a `differences` variable, and assign it the value of `array.map()`. For the callback, return the value of `el` minus `mean`.
+O próximo passo é calcular a distância que cada elemento está da média. Declare uma variável `differences` e atribua a ela o valor de `array.map()`. Para a callback, retorne o valor de `el` menos `mean`.
# --hints--
-Your `getVariance` function should have a `differences` variable.
+A função `getVariance` deve ter uma variável `differences`.
```js
assert.match(getVariance.toString(), /differences\s*=/);
```
-Your `differences` variable should use the `array.map()` method.
+A variável `differences` deve usar o método `array.map()`.
```js
assert.match(getVariance.toString(), /differences\s*=\s*array\.map\(/);
```
-Your `differences` variable should use the `el` parameter in the callback function.
+A variável `differences` deve usar o parâmetro `el` na função de callback.
```js
assert.match(getVariance.toString(), /differences\s*=\s*array\.map\(function\s*\(?\s*el\s*\)?/);
```
-Your `map` callback should return the value of `el` minus `mean`.
+A callback `map` deve retornar o valor de `el` menos `mean`.
```js
assert.match(getVariance.toString(), /differences\s*=\s*array\.map\(function\s*\(?\s*el\s*\)?\s*\{\s*return\s*el\s*-\s*mean;?\s*\}/);
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Number Sorter
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/portuguese/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/ukrainian/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md b/curriculum/challenges/ukrainian/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
index 63b7311fc10..05bdbf47dda 100644
--- a/curriculum/challenges/ukrainian/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
+++ b/curriculum/challenges/ukrainian/10-coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree.md
@@ -74,6 +74,7 @@ assert(
}
test.add(4);
test.add(1);
+ test.add(1);
test.add(7);
test.add(87);
test.add(34);
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
new file mode 100644
index 00000000000..190c2ed141e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-basic-algorithmic-thinking-by-building-a-number-sorter/64061a98f704a014b44afdb2.md
@@ -0,0 +1,327 @@
+---
+id: 64061a98f704a014b44afdb2
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+In this project, you will be building a number sorter. The HTML and CSS have been provided for you. Feel free to explore them.
+
+When you are ready, declare a `sortButton` variable and assign it the value of `.getElementById()` with the argument `sort`.
+
+# --hints--
+
+You should declare a `sortButton` variable with `const`.
+
+```js
+assert.match(code, /const\s+sortButton\s*=/);
+```
+
+You should call `document.getElementById()` with the argument `sort`.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+You should assign the value of `document.getElementById()` to `sortButton`.
+
+```js
+assert.match(code, /sortButton\s*=\s*document\.getElementById\(\s*('|"|`)sort\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Number Sorter
+
+
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: "Lato", Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin: 30px auto;
+}
+
+h2 {
+ margin-bottom: 15px;
+}
+
+form {
+ width: 100%;
+ padding: 15px auto;
+ text-align: center;
+ padding: 15px;
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+}
+
+fieldset div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.bracket,
+.comma {
+ font-size: 2.3em;
+}
+
+form .comma {
+ margin-left: 2px;
+}
+
+select {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ min-height: 38px;
+ width: 50px;
+ text-align: center;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output-container {
+ width: 95%;
+ min-height: 55px;
+ margin-top: 25px;
+ border-radius: 0;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.output-array {
+ width: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.output-value {
+ font-size: 2em;
+}
+
+.alert {
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+@media (min-width: 550px) {
+ form,
+ .output-container {
+ max-width: 480px;
+ }
+
+ fieldset {
+ max-width: 400px;
+ }
+
+ .output-array {
+ max-width: 420px;
+ }
+}
+```
+
+```js
+const sortButton = document.getElementById("sort");
+
+const sortInputArray = (event) => {
+ event.preventDefault();
+
+ const inputValues = [
+ ...document.getElementsByClassName("values-dropdown")
+ ].map((dropdown) => Number(dropdown.value));
+
+ const sortedValues = inputValues.sort((a, b) => {
+ return a - b;
+ });
+
+ updateUI(sortedValues);
+}
+
+const updateUI = (array = []) => {
+ array.forEach((num, i) => {
+ const outputValueNode = document.getElementById(`output-value-${i}`);
+ outputValueNode.innerText = num;
+ })
+}
+
+const bubbleSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ for (let j = 0; j < array.length - 1; j++) {
+ if (array[j] > array[j + 1]) {
+ const temp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = temp;
+ }
+ }
+ }
+
+ return array;
+}
+
+const selectionSort = (array) => {
+ for (let i = 0; i < array.length; i++) {
+ let minIndex = i;
+
+ for (let j = i + 1; j < array.length; j++) {
+ if (array[j] < array[minIndex]) {
+ minIndex = j;
+ }
+ }
+
+ const temp = array[i];
+ array[i] = array[minIndex];
+ array[minIndex] = temp;
+ }
+
+ return array;
+}
+
+const insertionSort = (array) => {
+ for (let i = 1; i < array.length; i++) {
+ const currValue = array[i];
+ let j = i - 1;
+
+ while (j >= 0 && array[j] > currValue) {
+ array[j + 1] = array[j];
+ j--;
+ }
+ array[j + 1] = currValue;
+ }
+ return array;
+}
+
+sortButton.addEventListener("click", sortInputArray);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
new file mode 100644
index 00000000000..147ef7b6ee1
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641d9a19bff38d34d5a5edb8.md
@@ -0,0 +1,148 @@
+---
+id: 641d9a19bff38d34d5a5edb8
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+All the HTML and CSS for this project has been provided for you. You can take a look at the two files to familiarize yourself with them.
+
+Start by getting the `#author-container` and `#load-more-btn` elements with the `.getElementById()` method. Assign them to the variables `authorContainer` and `loadMoreBtn`, respectively.
+
+The variables will not change, so use `const` to declare them.
+
+# --hints--
+
+You should use `document.getElementById()` to get the `#author-container` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should assign the `#authorContainer` element to the variable `authorContainer`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+authorContainer\s*\=\s*document\.getElementById\(\s*('|"|`)author\-container\1\)/);
+```
+
+You should use `document.getElementById()` to get the `#load-more-btn` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+You should assign the `#load-more-btn` element to the variable `loadMoreBtn`. Don't forget to use `const` to declare the variable.
+
+```js
+assert.match(code, /const\s+loadMoreBtn\s*\=\s*document\.getElementById\(\s*('|"|`)load\-more\-btn\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
new file mode 100644
index 00000000000..0e15f84dd7a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da3c6b6fbd742bff6ee40.md
@@ -0,0 +1,143 @@
+---
+id: 641da3c6b6fbd742bff6ee40
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+The Fetch API is a built-in JavaScript interface to make network requests to a server. It has a `fetch()` method you can use to make `GET`, `POST`, `PUT`, or `PATCH` requests. In this project, you'll make a `GET` request to a URL for a JSON file with information about authors on freeCodeCamp News.
+
+Here is how you can make a `GET` request with the `fetch()` method:
+
+```js
+fetch("url-goes-here")
+```
+
+Make a `GET` request to this URL: `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`. Don't terminate your code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should not have a semi-colon after your `fetch` call.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
new file mode 100644
index 00000000000..fd3652ca525
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da42481d90c4314c99e94.md
@@ -0,0 +1,173 @@
+---
+id: 641da42481d90c4314c99e94
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+The `fetch()` method returns a `Promise`, which is a placeholder object that will either be fulfilled if your request is successful, or rejected if your request is unsuccessful.
+
+If the `Promise` is fulfilled, it resolves to a `Response` object, and you can use the `.then()` method to access the `Response`.
+
+Here's how you can chain `.then()` to the `fetch()` method:
+
+```js
+fetch("sample-url-goes-here")
+ .then((res) => res)
+```
+
+Chain the `.then()` method to your `fetch` call. Inside the `.then()` method, add a callback function with `res` as a parameter, then log the `res` to the console so you can see the `Response` object. Open your console and expand the `Response` object to see what it contains.
+
+Again, don't terminate the code with a semi-colon yet.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain the `.then()` method to your `fetch()` syntax
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(/)
+```
+
+You should add a `res` parameter to your `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?/)
+```
+
+Your `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*/)
+```
+
+You should log the `res` parameter to the console so you can see the `Response` object.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
new file mode 100644
index 00000000000..7fec2d783a4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da465273051435d332b15.md
@@ -0,0 +1,146 @@
+---
+id: 641da465273051435d332b15
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+The data you get from a `GET` request is not usable at first. To make the data usable, you can use the `.json()` method on the `Response` object to parse it into JSON. If you expand the `Prototype` of the `Response` object in the console, you will see the `.json()` method there.
+
+Remove `console.log(res)` and implicitly return `res.json()` instead.
+
+# --hints--
+
+You should remove the `console.log(res)`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*console\.log\(res\)\)/)
+```
+
+You should implicitly return `res.json()` in your `.then()`.
+
+```js
+assert.match(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\)/)
+```
+
+You should not have a semi-colon after your `.then()`.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+--fcc-editable-region--
+.then((res) => console.log(res))
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
new file mode 100644
index 00000000000..a9459eaf14d
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da4b16937be43ba24c63d.md
@@ -0,0 +1,176 @@
+---
+id: 641da4b16937be43ba24c63d
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+In order to start working with the data, you will need to use another `.then()` method.
+
+Chain another `.then()` to the existing `.then()` method. This time, pass in `data` as the parameter for the callback function. For the callback, use a curly brace because you will have more than one expression. Within your callback function, log `data` to the console to see what it looks like.
+
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+Your first `.then()` should not have a semi-colon.
+
+```js
+assert.notMatch(code, /\.then\(\(?res\)?\s*=>\s*res.json\(\)\);/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\)/)
+```
+
+Your second `.then()` should not not have semi-colon after it.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\s*\}\s*\);/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
new file mode 100644
index 00000000000..0b4247deead
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da51a9810e74411262fcc.md
@@ -0,0 +1,198 @@
+---
+id: 641da51a9810e74411262fcc
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+The `.catch()` method is another asynchronous JavaScript method you can use to handle errors. This is useful in case the `Promise` gets rejected.
+
+Chain `.catch()` to the last `.then()`. Pass in a callback function with `err` as the parameter. Inside the callback, use `console.error()` to log possible errors to the console with the text `There was an error: ${err}`. Since you're using `err` in the text, don't forget to use a template literal string with backticks (``) instead of single or double quotes.
+
+**Note**: Now you can terminate your code with a semicolon. You couldn't do that in the previous steps because you'll signal to JavaScript to stop parsing your code, which will affect the `fetch()` syntax.
+
+# --hints--
+
+You should use the `fetch()` method to make a `GET` request to `https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)/)
+```
+
+You should chain another `.then()` to the existing `.then()`.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(/)
+```
+
+You should add a `data` parameter to your second `.then()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?/)
+```
+
+Your second `.then()` method should use arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*/)
+```
+
+Your second `.then()` method should have curly braces.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*/)
+```
+
+Your second `.then()` method should log `data` to the console.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\)/)
+```
+
+Your second `.then()` should not have a semicolon.
+
+```js
+assert.notMatch(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\);/)
+```
+
+You should chain the `.catch()` method to the second `.then()` you already have.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(/)
+```
+
+You should add an `err` parameter to your `.catch()` method.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?/)
+```
+
+Your `.catch()` method should have an arrow function syntax.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?/)
+```
+
+Your `.catch()` method should use `console.error()` to log `err` to the console with the text \``There was an error: ${err}``. Don't forget to use backticks.
+
+```js
+assert.match(code, /fetch\(('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1\)\s*\.then\(\(?res\)?\s*=>\s*res.json\(\)\)\s*\.then\(\(?data\)?\s*=>\s*\{\s*\n?\s*?console\.log\(data\);?\n?\s*\}\s*\)\n?\s*\.catch\(\(?err\)?\s*=>\s*\{?\n?(\s*)?console\.error\(`There\swas\san\serror:\s?\$\{err\}`\);?\n?(\s*)?\}?\)\s*;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
new file mode 100644
index 00000000000..60a5b23e01e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5462576784453146ec2.md
@@ -0,0 +1,172 @@
+---
+id: 641da5462576784453146ec2
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+Now that you have the data you want, you can use it to populate the UI. But the fetched data contains an array of 26 authors, and if you add them all to the page at the same time, it could lead to poor performance.
+
+Instead, you should add 8 authors at a time, and have a button to add 8 more until there's no more data to display.
+
+Use `let` to create 2 variables named `startingIndex` and `endingIndex`, and assign them the number values `0` and `8`, respectively. Also, create an `authorDataArr` variable with `let` and set it to an empty array.
+
+# --hints--
+
+You should use `let` to declare a variable named `startingIndex`.
+
+```js
+assert.match(code, /let\s+startingIndex/)
+```
+
+You should set your `startingIndex` variable to `0`.
+
+```js
+assert.match(code, /let\s+startingIndex\s*=\s*0;?/)
+```
+
+You should use `let` to declare a variable named `endingIndex`.
+
+```js
+assert.match(code, /let\s*endingIndex/)
+```
+
+You should set your `endingIndex` variable to `8`.
+
+```js
+assert.match(code, /let\s+endingIndex\s*=\s*8;?/)
+```
+
+You should use `let` to declare a variable named `authorDataArr`.
+
+```js
+assert.match(code, /let\s+authorDataArr/)
+```
+
+You should set your `authorDataArr` variable to an empty array (`[]`).
+
+```js
+assert.match(code, /let\s+authorDataArr\s*=\s*\[\];?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
freeCodeCamp News Author Page
+
+
+
+
+
+
+
+
+
+```
+
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --main-bg-color: #1b1b32;
+ --light-grey: #f5f6f7;
+ --dark-purple: #5a01a7;
+ --golden-yellow: #feac32;
+}
+
+body {
+ background-color: var(--main-bg-color);
+ text-align: center;
+}
+
+.title {
+ color: var(--light-grey);
+ margin: 20px 0;
+}
+
+#author-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.user-card {
+ border-radius: 15px;
+ width: 300px;
+ height: 350px;
+ background-color: var(--light-grey);
+ margin: 20px;
+}
+
+.user-img {
+ width: 150px;
+ height: 150px;
+ object-fit: cover;
+}
+
+.purple-divider {
+ background-color: var(--dark-purple);
+ width: 100%;
+ height: 15px;
+}
+
+.author-name {
+ margin: 10px;
+}
+
+.bio {
+ margin: 20px;
+}
+
+.error-msg {
+ color: var(--light-grey);
+}
+
+.btn {
+ cursor: pointer;
+ width: 200px;
+ margin: 10px;
+ color: var(--main-bg-color);
+ font-size: 14px;
+ background-color: var(--golden-yellow);
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border-color: var(--golden-yellow);
+ border-width: 3px;
+}
+```
+
+```js
+const authorContainer = document.getElementById('author-container');
+const loadMoreBtn = document.getElementById('load-more-btn');
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
+ .then((res) => res.json())
+ .then((data) => {
+ console.log(data);
+ })
+ .catch((err) => {
+ console.error(`There was an error: ${err}`);
+ });
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
new file mode 100644
index 00000000000..b213299f6d4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da5abaac81844a54adb03.md
@@ -0,0 +1,168 @@
+---
+id: 641da5abaac81844a54adb03
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
+
+Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
+
+# --hints--
+
+You should use `const` to create an empty function named `displayAuthors`.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*/)
+```
+
+`displayAuthors` should be a function.
+
+```js
+assert.isFunction(displayAuthors)
+```
+
+Your `displayAuthors` function should use an arrow syntax.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(.*\)\s*=>\s*/)
+```
+
+Your `displayAuthors` function should take an `authors` parameter.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors/)
+```
+
+Your `displayAuthors` function should be empty.
+
+```js
+assert.match(code, /const\s+displayAuthors\s*=\s*\(authors\)\s*=>\s*\{\n?\s*?\};?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
new file mode 100644
index 00000000000..aacdc42bf9a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da73b09e7f046c758e0ed.md
@@ -0,0 +1,159 @@
+---
+id: 641da73b09e7f046c758e0ed
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+To see the authors' names on the page, you need to call the `displayAuthors` function inside the second `.then()` method. But before that, you need to assign the author data to the empty `authorDataArr` array.
+
+First, remove your `console.log()` statement. Then, assign `data` to the `authorDataArr` variable.
+
+# --hints--
+
+You should remove the console log showing the `data`.
+
+```js
+assert.notMatch(code, /console\.log\(data\);/)
+```
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
new file mode 100644
index 00000000000..8ae28f085f4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da791d0c34a472b8d15b6.md
@@ -0,0 +1,171 @@
+---
+id: 641da791d0c34a472b8d15b6
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Now `authorDataArr` is the same as the `data` you logged to the console a while ago. Log `authorDataArr` to the console to confirm this.
+
+Inside your `console.log()` statement, add the text `Author Data Array:` as the first parameter and `authorDataArr` as the second parameter. Use comma to separate the text from `authorDataArr`.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should have a console log with the text `Author Data Array:`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1/)
+```
+
+You should use comma to separate your `Author Data Array:` text and `authorDataArr`.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,/)
+```
+
+`authorDataArr` should be the second parameter of your console log statement.
+
+```js
+assert.match(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
new file mode 100644
index 00000000000..afeba760e74
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da7bfbc7f0f477438ad8a.md
@@ -0,0 +1,184 @@
+---
+id: 641da7bfbc7f0f477438ad8a
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Now it's time to call the `displayAuthors` function. But again, you don't want to populate the page with all the authors at once. Instead, you can extract a portion of the authors with the `startingIndex` and `endingIndex` variables. The best method to do this is the `.slice()` array method.
+
+First, remove the console log statement showing `authorDataArr`. Then, call the `displayAuthors` function with the `authorDataArr` array and `.slice()`. Use the `startingIndex` variable for the starting point and the `endingIndex` variable for the ending point.
+
+# --hints--
+
+You should assign `data` to the `authorDataArr` variable
+
+```js
+assert.match(code, /authorDataArr\s*=\s*data;?/)
+```
+
+You should remove the console log statement showing `authorDataArr`
+
+```js
+assert.notMatch(code, /console\.log\(("|'|`)Author\s+Data\s+Array:\s*\1\,\s*authorDataArr\);?/)
+```
+
+You should call your `displayAuthors` function.
+
+```js
+assert.match(code, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+assert.match(code, /displayAuthors\(authorDataArr.slice\(startingIndex\,\s*endingIndex\)\);?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
new file mode 100644
index 00000000000..237e51097fe
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da803d9892447d059804e.md
@@ -0,0 +1,170 @@
+---
+id: 641da803d9892447d059804e
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Now create an image tag and give it the `class` `user-img`. Use template interpolation to set the `src` attribute to `image` you destructured earlier. Set the `alt` attribute to `author` followed by the text `avatar`. Make sure there is a space between the `author` variable and the word `avatar`, for example, `Quincy Larson avatar`.
+
+# --hints--
+
+You should create an `img` element.
+
+```js
+assert.exists(document.querySelector('img'));
+```
+
+Your `img` element should have the class `user-img`.
+
+```js
+assert.include(document.querySelector('img')?.className, "user-img");
+```
+
+You should set the `src` attribute of your `img` element to `${image}`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('src'), authorDataArr[0].image);
+```
+
+You should set the `alt` attribute of your `img` element to `${author} avatar`.
+
+```js
+assert.equal(document.querySelector('img')?.getAttribute('alt'), `${authorDataArr[0].author} avatar`);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
new file mode 100644
index 00000000000..1eef6b31025
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da836581c254815f785fe.md
@@ -0,0 +1,168 @@
+---
+id: 641da836581c254815f785fe
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+The next thing you'll show are biographical details about the author. You can do this with `bio` that you destructured earlier.
+
+Add a paragraph element with the `class` `bio`, then interpolate `bio` inside the paragraph element.
+
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.exists(document.querySelector('p'));
+```
+
+Your `p` element should have the class `bio`
+
+```js
+assert.include(document.querySelector('p')?.className, 'bio');
+```
+
+You should interpolate `bio` in your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.innerText, authorDataArr[0].bio);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
new file mode 100644
index 00000000000..b5f13f13f69
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da86294fd9f485d3c2bf0.md
@@ -0,0 +1,181 @@
+---
+id: 641da86294fd9f485d3c2bf0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+Next, add a link to the author's page on freeCodeCamp News.
+
+Add an anchor element with the `class` `author-link`, interpolate `url` as the value for the `href` attribute, and set `target` to `_blank`. For the text of the anchor element, interpolate `author` followed by the text `'s author page`. For example, `Quincy Larson's author page`.
+
+# --hints--
+
+You should create an anchor element.
+
+```js
+assert.exists(document.querySelector('a'));
+```
+
+Your anchor element should have the class `author-link`.
+
+```js
+assert.include(document.querySelector('a')?.className, "author-link");
+```
+
+You should interpolate `url` as the value of your anchor's `href` attribute.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('href'), authorDataArr[0].url);
+```
+
+You should set the `target` attribute of your anchor element to `_blank`.
+
+```js
+assert.equal(document.querySelector('a')?.getAttribute('target'), '_blank');
+```
+
+You should interpolate `author` followed by the text `'s author page` inside your anchor element.
+
+```js
+assert.equal(document.querySelector('a')?.textContent, `${authorDataArr[0].author}'s author page`);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `)
+ )
+};
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
new file mode 100644
index 00000000000..2cb8442eb5d
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da895fb7ec648a5bdf19c.md
@@ -0,0 +1,182 @@
+---
+id: 641da895fb7ec648a5bdf19c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Now you have everything you want to include in the UI. The next step is to make the `Load More Authors` button fetch more authors whenever it's clicked. You can do this by adding a `click` event to the button and carefully incrementing the `startingIndex` and `endingIndex` variables.
+
+Create a `fetchMoreAuthors` function with the arrow function syntax. Don't put anything in it yet. Make sure you use curly braces because you'll have more than one expression inside the function.
+
+# --hints--
+
+You should use `const` to create a `fetchMoreAuthors` function.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*/)
+```
+
+`fetchMoreAuthors` should be a function.
+
+```js
+assert.isFunction(fetchMoreAuthors)
+```
+
+Your `fetchMoreAuthors` function should not take any parameter.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\s*\)\s*/)
+```
+
+Your `fetchMoreAuthors` function should use arrow syntax.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*/)
+```
+
+Your `fetchMoreAuthors` function should be empty.
+
+```js
+assert.match(code, /const fetchMoreAuthors\s*=\s*\(\)\s*=>\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
new file mode 100644
index 00000000000..456f240c26f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da97c987a514959ada414.md
@@ -0,0 +1,187 @@
+---
+id: 641da97c987a514959ada414
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Now call the `displayAuthors` function with a portion of the author data just like you did before.
+
+If you click the `Load More Authors` button after calling the function, it won't work. That's because you still have to add the `click` event listener to the button. You'll do that next.
+
+# --hints--
+
+You should call your `displayAuthors` function.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(/)
+```
+
+You should call your `displayAuthors` function and pass in an argument of `authorDataArr.slice()`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(/)
+```
+
+The first parameter of your `slice()` method should be `startingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex/)
+```
+
+The second parameter of your `slice()` method should be `endingIndex`.
+
+```js
+const afterAdd = code.split("endingIndex += 8;")[1];
+assert.match(afterAdd, /displayAuthors\(authorDataArr\.slice\(startingIndex\,\s*endingIndex\)\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+```
+
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
new file mode 100644
index 00000000000..2ca307dc026
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9aceb788e49a73ebcc9.md
@@ -0,0 +1,180 @@
+---
+id: 641da9aceb788e49a73ebcc9
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+Remember that in step 1 you selected the `Load More Authors` button and assigned it to `loadMoreBtn`.
+
+Use `addEventListener` to add a `click` event listener to `loadMoreBtn`. Also, pass in a reference to the `fetchMoreAuthors` function to run whenever the button is clicked.
+
+After that, when you click the button you should see 8 more authors.
+
+# --hints--
+
+You should call the `addEventListener()` method on your `loadMoreBtn` variable.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(/)
+```
+
+Your event listener should listen for a `click` event.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1/)
+```
+
+Your event listener should take `fetchMoreAuthors` as the function to run.
+
+```js
+assert.match(code, /loadMoreBtn\.addEventListener\(('|"|`)click\1,\s*fetchMoreAuthors\);?/)
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
new file mode 100644
index 00000000000..6c610c97896
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641da9ea9b847a49fe6ee9b6.md
@@ -0,0 +1,180 @@
+---
+id: 641da9ea9b847a49fe6ee9b6
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+Your fCC Authors Page is now complete. But you could improve on a few things.
+
+First, if you click the `Load More Authors` button a couple of time, you'll see that it won't add more authors to the page. That's because you've reached the end of the authors list. For a better user experience, you should make it clear when there's no more data to display by disabling the button and changing its text. An `if` statement is the perfect tool for this.
+
+Inside the `fetchMoreAuthors` function, write an `if` statement and set the condition to `authorDataArr.length <= endingIndex` – meaning there's no more data to load.
+
+# --hints--
+
+You should have an `if` statement.
+
+```js
+assert.match(code, /if\s*\(/)
+```
+
+Your `if` statement should take in `authorDataArr.length <= endingIndex` as its condition.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*/)
+```
+
+Your `if` statement should be empty.
+
+```js
+assert.match(code, /if\s*\(authorDataArr\.length\s*<=\s*endingIndex\)\s*\{\s*\}/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
new file mode 100644
index 00000000000..3044291e9e2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa5ea050f24a7cade6e6.md
@@ -0,0 +1,172 @@
+---
+id: 641daa5ea050f24a7cade6e6
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+If this condition is met, disable the button by setting its `disabled` property to `true`. Also, set the text content of the button to `No more data to load`.
+
+# --hints--
+
+You should set the `disabled` property of `loadMoreBtn` to `true`.
+
+```js
+assert.match(code, /loadMoreBtn\.disabled\s*=\s*true;?/)
+```
+
+You should set the `textContent` of `loadMoreBtn` to `No more data to load`.
+
+```js
+assert.match(code, /loadMoreBtn\.textContent\s*=\s*('|"|`)No\s+more\s+data\s+to\s+load\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
new file mode 100644
index 00000000000..21ca08cbc44
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daa8c2c3e364ac3650b37.md
@@ -0,0 +1,176 @@
+---
+id: 641daa8c2c3e364ac3650b37
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Next, there's not a lot of separation between each author's name and image, and the rest of the details on the card. A divider will give the author cards a clear visual hierarchy.
+
+Add a `div` element above the author's bio and give it the `class` `purple-divider`.
+
+# --hints--
+
+You should create a `div` element before your `p` element.
+
+```js
+assert.equal(document.querySelector('p')?.previousElementSibling?.tagName, 'DIV');
+```
+
+Your `div` element should have the `class` set to `purple-divider`.
+
+```js
+assert.include(document.querySelector('p')?.previousElementSibling?.className, 'purple-divider');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
new file mode 100644
index 00000000000..bc2fa142948
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daabed8d0584b1150c953.md
@@ -0,0 +1,195 @@
+---
+id: 641daabed8d0584b1150c953
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Some of the author bios are much longer than others. To give the cards a uniform look, you can extract the first 50 characters of each one and replace the rest with an ellipsis (...). Otherwise, you can show the entire bio.
+
+Within the paragraph element, replace `bio` with a ternary operator. For the condition, check if the length of `bio` is greater than 50. If it is, use the `.slice()` method to extract the first 50 characters of `bio` and add an ellipsis at the end. Otherwise, show the full `bio`.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+assert.match(code, /
/);
+```
+
+You should check if the length of the `bio` text is greater than `50`.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50/)
+```
+
+If the `bio` text is greater than `50` characters, you should extract the first 50 characters with `slice()` and replace the rest with `...`. Don't forget that indexes are zero-based.
+
+```js
+assert.match(code, /
\$\{\s*bio\.length\s*>\s*50\s*\?\s*bio\.slice\(\s*0\,\s*49\s*\)\s*\+\s*("|')\.\.\.\2\s*\:/)
+```
+
+If the `bio` text is less than 50 characters, use the `bio` text directly.
+
+```js
+assert.match(code, /
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
new file mode 100644
index 00000000000..0dbdf935ee3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641daae5e18eae4b562633e4.md
@@ -0,0 +1,191 @@
+---
+id: 641daae5e18eae4b562633e4
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Finally, what if there's an error and the author data fail to load? Then we need to show an error in the UI. That's exactly what the `.catch()` method is for – handling errors.
+
+Inside the `.catch()`, remove the `console.error()` and set the `innerHTML` of the author container to a `p` element with the `class` `error-msg` and text `There was an error loading the authors`.
+
+# --hints--
+
+You should remove your `console.error` and its text.
+
+```js
+assert.notMatch(code, /console\.error\(`There\s+was\s+an\s+error:\s+\$\{err\}`\);/)
+```
+
+You should access the `innerHTML` of `authorContainer` and set it to a `p` element. Don't forget to surround the `p` element with a template literal.
+
+
+```js
+assert.match(code, /authorContainer\.innerHTML\s*=\s*(`|"|').*<\/p>\1/)
+```
+
+Your `p` element should have the class `error-msg`.
+
+```js
+assert.match(code, /(`|"|')
/)
+```
+
+Your `p` element should have the text `There was an error loading the authors`.
+
+```js
+assert.match(code, /(`|"|')
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
new file mode 100644
index 00000000000..80288b931fb
--- /dev/null
+++ b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-fetch-and-promises-by-building-an-fcc-authors-page/641dab13c1b6f14b9828e6b1.md
@@ -0,0 +1,332 @@
+---
+id: 641dab13c1b6f14b9828e6b1
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+One more thing. If you keep clicking the `Load More Authors` button until there's no more data to load and the text changes to `No more data to load`, the cursor value is still `pointer`. Why not change the cursor value to `not-allowed` instead?
+
+Access the `style` property of the `Load More Authors` button and set `cursor` to `not-allowed`.
+
+With that, your author page is complete!
+
+# --hints--
+
+You should access the `style` property of `loadMoreBtn` with a dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style/)
+```
+
+You should access `cursor` from the `style` property with dot notation.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor/)
+```
+
+You should set the value of the `cursor` property to `not-allowed`.
+
+```js
+assert.match(code, /loadMoreBtn.style.cursor\s*=\s*('|"|`)not\-allowed\1;?/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ freeCodeCamp News Author Page
+
+
+
+
+ `;
+ });
+};
+
+loadMoreBtn.addEventListener('click', fetchMoreAuthors);
+```
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
new file mode 100644
index 00000000000..f8587e80b09
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-a.md
@@ -0,0 +1,194 @@
+---
+id: 63ee3f71381756f9716727ef
+title: CSS Foundations Exercise A
+challengeType: 14
+dashedName: css-foundations-exercise-a
+---
+
+# --description--
+
+**Objective:** In this exercise, you're going to practice adding CSS to an HTML file using all three methods: external CSS, internal CSS, and inline CSS. You should only be using type selectors for this exercise when adding styles via the external and internal methods. You should also use keywords for colors (e.g. "blue") instead of using `RGB` or `HEX` values.
+
+## User Stories
+
+1. You should see a `div` element with a `red` background, `white` text, a font size of `32px`, center aligned, and `bold`.
+
+1. The CSS of the `div` element should be added externally by using a type selector.
+
+1. You should see a `p` element with a `green` background, `white` text, and a font size of `18px`.
+
+1. The CSS of the `p` element should be added internally by using a type selector.
+
+1. You should see a `button` element with an orange background and a font size of `18px`.
+
+1. The CSS of the `button` element should have an inline style.
+
+# --hints--
+
+There should be one `div` element and should contains some text and be aligned in the center.
+
+```js
+const aligned = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('text-align');
+
+assert(aligned === 'center');
+assert(document.getElementsByTagName('DIV')?.length == 1);
+assert(document.getElementsByTagName('DIV')?.[0]?.innerText.length > 0)
+```
+
+The `div` element should have a `background-color` of `red` and a text color of `white`.
+
+```js
+
+const bgc = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('background-color');
+
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(bgc === 'red');
+assert(color === 'white');
+```
+
+The `div` element should have a `font-weight` of bold and a `font-size` of `32px`.
+
+```js
+const fontSize = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-size');
+const fontWeight = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('font-weight');
+
+assert(fontSize === '32px');
+assert(fontWeight === 'bold');
+```
+
+The `div` element should have its CSS added externally.
+
+```js
+assert(!document.getElementsByTagName('style')?.[0]?.innerText.includes('div'));
+assert(!document.getElementsByTagName('div')?.[0]?.hasAttribute('style'));
+```
+
+There should be one `p` element and it should contain some text.
+
+```js
+assert(document.getElementsByTagName('P')?.length == 1);
+assert(document.getElementsByTagName('P')?.[0]?.innerText.length > 0)
+```
+
+The `p` element should have its `color` set to `white`.
+
+```js
+const color = new __helpers.CSSHelp(document).getStyle('div')?.getPropertyValue('color');
+
+assert(color == 'white');
+```
+
+The `p` element should have a `font-size` of `18px`.
+
+```js
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pHasFontSize18 = false;
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p' && rule.style.fontSize === '18px') {
+ pHasFontSize18 = true;
+ break;
+ }
+ }
+}
+
+assert(pHasFontSize18);
+```
+
+The `p` element should have its style added internally.
+
+```js
+
+const styleTag = document.getElementsByTagName('style')?.[0];
+let pIsStyled = false;
+
+
+const rules = styleTag?.sheet?.cssRules || styleTag?.sheet?.rules;
+if (rules) {
+ for (let j = 0; j < rules.length; j++) {
+ const rule = rules[j];
+ if (rule.selectorText === 'p') {
+ pIsStyled = true;
+ break;
+ }
+ }
+}
+
+assert(pIsStyled);
+```
+
+The `button` element should have its `background-color` set to `orange`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.backgroundColor === 'orange')
+```
+
+The `button` element should have its `font-size` set to `18px`.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.style.fontSize === '18px')
+```
+
+The `button` element should have an inline style.
+
+```js
+assert(document.getElementsByTagName('button')?.[0]?.hasAttribute('style'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+ Exercise A
+
+
+
+
+
+```
+
+```css
+/* style.css */
+```
+
+# --solutions--
+
+```html
+
+
+
+ My Styling Example
+
+
+
+
+
Hello World!
+
This is a paragraph.
+
+
+
+```
+
+```css
+div {
+ background-color: red;
+ color: white;
+ font-size: 32px;
+ text-align: center;
+ font-weight: bold;
+}
+```
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
new file mode 100644
index 00000000000..cd1a07e15f5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations-projects/css-foundations-exercise-b.md
@@ -0,0 +1,172 @@
+---
+id: 63ee3fe4381756f9716727f0
+title: CSS Foundations Exercise B
+challengeType: 14
+dashedName: css-foundations-exercise-b
+---
+
+# --description--
+
+**Objective:** There are several elements in the HTML file provided, which you will have to add either class or ID attributes to. You will then have to add rules in the CSS file provided using the correct selector syntax.
+
+## User Stories
+
+1. You should see a `yellow` background for all odd numbered elements in the list.
+
+1. You should have a `class` selector used for all odd numbered elements in the list.
+
+1. You should see that the second element in the list has `blue` text and a `font-size` of `36px`.
+
+1. The `font-size` and text color on the second element should be set by using an `id` attribute.
+
+1. You should see that the third element in the list has a `font-size` of `24px`.
+
+1. The `font-size` on the third element should be set by using a `class` attribute.
+
+1. You should see that the fourth element in the list has a `red` background, a `font-size` of `24px`, and a `font-weight` of `bold`.
+
+1. The `font-size` of the fourth element should be set with a `class` attribute the `font-weight` and the color should be set with an `id` attribute.
+
+# --hints--
+
+Every odd element should have a `class` attribute.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPHasClass = p?.every((paragraph) => paragraph.classList.length > 0);
+
+assert(everyPHasClass);
+```
+
+Your odd elements should have a `background-color` of `yellow`.
+
+```js
+const p = Array.from(document.querySelectorAll('P'));
+
+const everyPhasBackgroundColor = p?.every((paragraph) => {
+
+ const style = getComputedStyle(paragraph);
+
+ return style?.backgroundColor === 'rgb(255, 255, 0)';
+})
+```
+
+Your second element should have blue text and a `font-size` of `36px`.
+
+```js
+const secondElementId = document.querySelectorAll('div')?.[0]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${secondElementId}`);
+
+assert.equal(style?.color, 'rgb(0, 0, 255)')
+assert.equal(style?.fontSize, '36px');
+```
+
+Your third element should have text and a `font-size` of `24px`.
+
+```js
+const thirdElement = document.querySelectorAll('p')?.[1]?.classList;
+
+```
+
+The fourth element should have a `font-size` of `24px`.
+
+```js
+const fourthElementClass = document.querySelectorAll('div')?.[1]?.classList[0];
+
+const style = new __helpers.CSSHelp(document).getStyle(`.${fourthElementClass}`);
+
+assert(style?.fontSize === '24px');
+```
+
+The fourth element should have a red `background-color`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.backgroundColor === 'red');
+```
+
+The fourth element should have a `font-weight` of `bold`.
+
+```js
+const fourthElement = document.querySelectorAll('div')?.[1]?.id;
+
+const style = new __helpers.CSSHelp(document).getStyle(`#${fourthElement}`);
+
+assert(style?.fontWeight === 'bold');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
Number 1 - I'm a class!
+
Number 2 - I'm one ID.
+
Number 3 - I'm a class, but cooler!
+
Number 4 - I'm another ID.
+
Number 5 - I'm a class!
+
+
+```
+
+```css
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Class and ID Selectors
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+div {
+ color: white;
+}
+```
+
+Here, all three `
` elements would be selected, while the `
` element wouldn’t be.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the CSS code given above?
+
+## --answers--
+
+The code applies a `white` color to all elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `div` elements in the HTML file.
+
+---
+
+The code applies a `white` color to all `p` elements in the HTML file.
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
new file mode 100644
index 00000000000..aad3818d270
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-b.md
@@ -0,0 +1,75 @@
+---
+id: 63ee35240d8d4841c3a7091b
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question B
+challengeType: 15
+dashedName: css-foundations-question-b
+---
+
+# --description--
+
+Class selectors will select all elements with the given `class`, which is just an attribute you place on an HTML element. Here’s how you add a class to an HTML tag and select it in CSS:
+
+```html
+
+
+
+ Please agree to our terms of service.
+
+```
+
+```css
+/* styles.css */
+
+.alert-text {
+ color: red;
+}
+```
+
+Note the syntax for `class` selectors: a period immediately followed by the case-sensitive value of the class attribute. Classes aren’t required to be unique, so you can use the same `class` on as many elements as you want.
+
+Another thing you can do with the `class` attribute is to add multiple classes to a single element as a space-separated list, such as `class="alert-text severe-alert"`. Since whitespace is used to separate `class` names like this, you should never use spaces for multi-worded names and should use a hyphen instead.
+
+## ID Selectors
+ID selectors are similar to `class` selectors. They select an element with the given `id`, which is another attribute you place on an HTML element:
+
+```html
+
+
+
My Awesome 90's Page
+```
+
+```css
+/* styles.css */
+
+#title {
+ background-color: red;
+}
+```
+
+Instead of a period, you use a hashtag immediately followed by the case-sensitive value of the `id` attribute. A common pitfall is people overusing the `id` attribute when they don’t necessarily need to, and when classes will suffice. While there are cases where using an `id` makes sense or is needed, such as taking advantage of specificity or having links redirect to a section on the current page, you should use `id`s sparingly (if at all).
+
+The major difference between classes and IDs is that an element can only have one `id`. An `id` cannot be repeated on a single page, and the `id` attribute should not contain any whitespace at all.
+
+# --question--
+
+## --text--
+
+What is the syntax for class and ID selectors?
+
+## --answers--
+
+To select a `class` you use `$` and to select an `id` you use `#`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `*`
+
+---
+
+To select a `class` you use `.` and to select an `id` you use `#`
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
new file mode 100644
index 00000000000..eb36575f5e7
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-c.md
@@ -0,0 +1,90 @@
+---
+id: 63ee352b0d8d4841c3a7091c
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question C
+challengeType: 15
+dashedName: css-foundations-question-c
+---
+
+# --description--
+
+What if you have two groups of elements that share some of their style declarations?
+
+```css
+.read {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+
+.unread {
+ color: white;
+ background-color: black;
+ /* several unique declarations */
+}
+```
+
+Both our `.read` and `.unread` selectors share the `color: white;` and `background-color: black;` declarations, but otherwise have several of their own unique declarations. To cut down on the repetition, you can group these two selectors together as a comma-separated list:
+
+```css
+.read,
+.unread {
+ color: white;
+ background-color: black;
+}
+
+.read {
+ /* several unique declarations */
+}
+
+.unread {
+ /* several unique declarations */
+}
+```
+
+Both of the examples above (with and without grouping) will have the same result, but the second example reduces the repetition of declarations and makes it easier to edit either the `color` or `background-color` for both classes at once.
+
+# --question--
+
+## --text--
+
+How would you apply a single rule to two different selectors, `.red-box` and `.yellow-box`?
+
+## --answers--
+
+```css
+.red-box,
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ height: 25px;
+}
+
+.yellow-box {
+ width: 25px;
+ height: 25px;
+}
+```
+
+---
+
+```css
+.red-box {
+ width: 25px;
+ .yellow-box {
+ height: 25px;
+ }
+}
+```
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
new file mode 100644
index 00000000000..4cfe1014093
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-d.md
@@ -0,0 +1,86 @@
+---
+id: 63ee35300d8d4841c3a7091d
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question D
+challengeType: 15
+dashedName: css-foundations-question-d
+---
+
+# --description--
+
+Another way to use selectors is to chain them as a list without any separation. Let’s say you had the following HTML:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You have two elements with the `subsection` class that have some sort of unique styles, but what if you only want to apply a separate rule to the element that also has `header` as a second class? Well, you could chain both the `class` selectors together in your CSS like so:
+
+```css
+.subsection.header {
+ color: red;
+}
+```
+
+What `.subsection.header` does is it selects any element that has both the `subsection` and `header` classes. Notice how there isn’t any space between the `.subsection` and `.header` `class` selectors. This syntax basically works for chaining any combination of selectors, except for chaining more than one type selector.
+
+This can also be used to chain a class and an ID, as shown below:
+
+```html
+
+
Latest Posts
+
This is where a preview for a post might go.
+
+```
+
+You can take the two elements above and combine them with the following:
+
+```css
+.subsection.header {
+ color: red;
+}
+
+.subsection#preview {
+ color: blue;
+}
+```
+
+In general, you can’t chain more than one type selector since an element can’t be two different types at once. For example, chaining two type selectors like `div` and `p` would give us the selector `divp`, which wouldn’t work since the selector would try to find a literal `` element, which doesn’t exist.
+
+# --question--
+
+## --text--
+
+Given an element that has an `id` of `title` and a `class` of `primary`, how would you use both attributes for a single rule?
+
+## --answers--
+
+```css
+.title.primary {
+ ...
+}
+```
+
+---
+
+```css
+.title > primary {
+ ...
+}
+```
+
+---
+
+```css
+#title.primary {
+ ...
+}
+```
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
new file mode 100644
index 00000000000..b6038767181
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-e.md
@@ -0,0 +1,61 @@
+---
+id: 63ee35370d8d4841c3a7091e
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question E
+challengeType: 15
+dashedName: css-foundations-question-e
+---
+
+# --description--
+
+Combinators allow us to combine multiple selectors differently than either grouping or chaining them, as they show a relationship between the selectors. There are four types of combinators in total, but for right now we’re going to only show you the descendant combinator, which is represented in CSS by a single space between selectors. A descendant combinator will only cause elements that match the last selector to be selected if they also have an ancestor (parent, grandparent, etc) that matches the previous selector.
+
+So something like `.ancestor .child` would select an element with the class `child` if it has an ancestor with the class `ancestor`. Another way to think of it is child will only be selected if it is nested inside of `ancestor`, no matter how deep. Take a quick look at the example below and see if you can tell which elements would be selected based on the CSS rule provided:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* styles.css */
+
+.ancestor .contents {
+ /* some declarations */
+}
+```
+
+In the above example, the first two elements with the `contents` class (`B` and `C`) would be selected, but that last element (`D`) won’t be. Was your guess correct?
+
+There’s really no limit to how many combinators you can add to a rule, so `.one .two .three .four` would be totally valid. This would just select an element that has a class of `four` if it has an ancestor with a class of `three`, and if that ancestor has its own ancestor with a class of `two`, and so on. You generally want to avoid trying to select elements that need this level of nesting, though, as it can get pretty confusing and long, and it can cause issues when it comes to specificity.
+
+# --question--
+
+## --text--
+
+What does the descendant combinator do?
+
+## --answers--
+
+It groups certain classes together which share the same declarations.
+
+---
+
+It gives the ability to select an element that shares the same `class` and `id`.
+
+---
+
+It allows you to select an element based on its relationship with its ancestor (parent, grandparent, and so on).
+
+
+## --video-solution--
+
+3
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
new file mode 100644
index 00000000000..5a18ff3b1a4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-f.md
@@ -0,0 +1,47 @@
+---
+id: 63ee353e0d8d4841c3a7091f
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question F
+challengeType: 15
+dashedName: css-foundations-question-f
+---
+
+# --description--
+
+Okay, you went over quite a bit so far. The only thing left for now is to go over how to add all this CSS to your HTML. There are three methods to do so.
+
+External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML’s opening and closing `` tags with a self-closing `` element:
+
+First, you add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you’ll be utilizing, a URL relative to the location of the HTML file. In the example above, you are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file.
+
+Then inside of the newly created `styles.css` file, you have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a “declaration block”. Finally, you place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration.
+
+A note on file names: `styles.css` is just what you went with as the file name here. You can name the file whatever you want as long as the file type is `.css`, though “style” or “styles” is most commonly used.
+
+A couple of the pros to this method are:
+
+1. It keeps your HTML and CSS separated, which results in the HTML file being smaller and making things look cleaner.
+2. You only need to edit the CSS in one place, which is especially handy for websites with many pages that all share similar styles.
+
+# --question--
+
+## --text--
+
+Which of the following best describes the purpose of the `rel` attribute in the `` element when linking an external CSS file to an HTML file?
+
+## --answers--
+
+It specifies the location of the CSS file relative to the location of the HTML file.
+
+---
+
+It specifies the relationship between the HTML file and the linked file.
+
+---
+
+It specifies the type of file being linked (e.g. "stylesheet").
+
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
new file mode 100644
index 00000000000..7da4a22a122
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-g.md
@@ -0,0 +1,54 @@
+---
+id: 63ee35450d8d4841c3a70920
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question G
+challengeType: 15
+dashedName: css-foundations-question-g
+---
+
+# --description--
+
+Internal CSS (or embedded CSS) involves adding the CSS within the HTML file itself instead of creating a completely separate file. With the internal method, you place all the rules inside of a pair of opening and closing `
+
+...
+```
+
+This method can be useful for adding unique styles to a single page of a website, but it doesn’t keep things separate like the external method, and depending on how many rules and declarations there are it can cause the HTML file to get pretty big.
+
+# --question--
+
+## --text--
+
+Which of the following is a difference between internal and external CSS methods?
+
+## --answers--
+
+The external method places CSS rules in a separate file, while the internal method places CSS rules within the HTML file itself.
+
+---
+
+The internal method keeps CSS separate from HTML, while the external method embeds CSS directly in HTML.
+
+---
+
+The internal method uses `` element to link CSS to HTML, while the external method embeds CSS directly in HTML.
+
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
new file mode 100644
index 00000000000..2b39dd69ed3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/16-the-odin-project/top-learn-css-foundations/css-foundations-question-h.md
@@ -0,0 +1,46 @@
+---
+id: 63ee354c0d8d4841c3a70921
+videoId: LGQuIIv2RVA
+title: CSS Foundations Question H
+challengeType: 15
+dashedName: css-foundations-question-h
+---
+
+# --description--
+
+Inline `CSS` makes it possible to add styles directly to `HTML` elements, though this method isn’t as recommended:
+
+```html
+
+
...
+
+```
+
+The first thing to note is that there aren't any selectors here, since the styles are being added directly to the opening `
` tag itself. Next, you have the `style` attribute, with its value within the pair of quotation marks being the declarations.
+
+If you need to add a unique style for a single element, this method can work just fine. Generally, though, this isn’t exactly a recommended way for adding CSS to HTML for a few reasons:
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated. If you want many elements to have the same style, you would have to copy + paste the same style to each individual element, causing lots of unnecessary repetition and more bloat. Any inline CSS will override the other two methods, which can cause unexpected results. (While you won’t dive into it here, this can actually be taken advantage of).
+
+# --question--
+
+## --text--
+
+Which of the following is the main disadvantage of using inline CSS?
+
+## --answers--
+
+It can quickly become pretty messy once you start adding a lot of declarations to a single element, causing your HTML file to become unnecessarily bloated.
+
+---
+
+It requires using selectors, which can be complicated for beginners.
+
+---
+
+Any inline CSS will override the other two methods (internal and external), which can cause unexpected results.
+
+
+## --video-solution--
+
+3