diff --git a/docs/images/tutorials/javascript/react-app/alert-window.png b/docs/images/tutorials/javascript/react-app/alert-window.png
new file mode 100644
index 00000000000..7f0aec591c2
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/alert-window.png differ
diff --git a/docs/images/tutorials/javascript/react-app/browser-development-run.png b/docs/images/tutorials/javascript/react-app/browser-development-run.png
new file mode 100644
index 00000000000..67ecde22f42
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/browser-development-run.png differ
diff --git a/docs/images/tutorials/javascript/react-app/continuous-mode.png b/docs/images/tutorials/javascript/react-app/continuous-mode.png
new file mode 100644
index 00000000000..7df5f112d9f
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/continuous-mode.png differ
diff --git a/docs/images/tutorials/javascript/react-app/current-layout.png b/docs/images/tutorials/javascript/react-app/current-layout.png
new file mode 100644
index 00000000000..b47e783f919
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/current-layout.png differ
diff --git a/docs/images/tutorials/javascript/react-app/deployment-to-production.png b/docs/images/tutorials/javascript/react-app/deployment-to-production.png
new file mode 100644
index 00000000000..86b1fb298e8
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/deployment-to-production.png differ
diff --git a/docs/images/tutorials/javascript/react-app/edit-configurations-continuous.png b/docs/images/tutorials/javascript/react-app/edit-configurations-continuous.png
new file mode 100644
index 00000000000..931d01a2fa3
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/edit-configurations-continuous.png differ
diff --git a/docs/images/tutorials/javascript/react-app/hello-react-js.png b/docs/images/tutorials/javascript/react-app/hello-react-js.png
new file mode 100644
index 00000000000..14952b06588
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/hello-react-js.png differ
diff --git a/docs/images/tutorials/javascript/react-app/red-page.png b/docs/images/tutorials/javascript/react-app/red-page.png
new file mode 100644
index 00000000000..7f66ac7ddd0
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/red-page.png differ
diff --git a/docs/images/tutorials/javascript/react-app/social-buttons.png b/docs/images/tutorials/javascript/react-app/social-buttons.png
new file mode 100644
index 00000000000..7c58c317251
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/social-buttons.png differ
diff --git a/docs/images/tutorials/javascript/react-app/structured-layout.png b/docs/images/tutorials/javascript/react-app/structured-layout.png
new file mode 100644
index 00000000000..aac395ed272
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/structured-layout.png differ
diff --git a/docs/images/tutorials/javascript/react-app/two-videos-select.png b/docs/images/tutorials/javascript/react-app/two-videos-select.png
new file mode 100644
index 00000000000..3846dd92b2e
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/two-videos-select.png differ
diff --git a/docs/images/tutorials/javascript/react-app/website-api-data.png b/docs/images/tutorials/javascript/react-app/website-api-data.png
new file mode 100644
index 00000000000..7eedf1893fa
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/website-api-data.png differ
diff --git a/docs/images/tutorials/javascript/react-app/website-draft.png b/docs/images/tutorials/javascript/react-app/website-draft.png
new file mode 100644
index 00000000000..8992fa29672
Binary files /dev/null and b/docs/images/tutorials/javascript/react-app/website-draft.png differ
diff --git a/docs/kr.tree b/docs/kr.tree
index 6d823e41904..055f399945b 100644
--- a/docs/kr.tree
+++ b/docs/kr.tree
@@ -179,7 +179,7 @@
-
+
diff --git a/docs/topics/getting-started.md b/docs/topics/getting-started.md
index 0e3737f161c..2ee8d2af061 100644
--- a/docs/topics/getting-started.md
+++ b/docs/topics/getting-started.md
@@ -126,7 +126,7 @@ Here you'll learn how to develop and improve your frontend web application using
2. **Create your first frontend web application:**
* To start from scratch, [create a basic browser application with the IntelliJ IDEA project wizard](js-project-setup.md).
- * If you prefer more robust examples, complete the [Building Web Applications with React and Kotlin/JS](https://play.kotlinlang.org/hands-on/Building%20Web%20Applications%20with%20React%20and%20Kotlin%20JS/01_Introduction) hands-on tutorial. It includes a sample project that can serve as a good starting point for your own projects, and contains useful snippets and templates.
+ * If you prefer more robust examples, complete the [Build a web application with React and Kotlin/JS](js-react.md) tutorial. It includes a sample project that can serve as a good starting point for your own projects, and contains useful snippets and templates.
* Check out the list of [Kotlin/JS samples](js-samples.md) for more ideas on how to use Kotlin/JS.
3. **Use libraries in your application.** Learn more about [adding dependencies](js-project-setup.md#dependencies).
diff --git a/docs/topics/js/js-get-started.md b/docs/topics/js/js-get-started.md
index f0e2b4904b3..9c992dd142a 100644
--- a/docs/topics/js/js-get-started.md
+++ b/docs/topics/js/js-get-started.md
@@ -130,13 +130,13 @@ Enter your name in the text box and accept the greetings from your application!
## What's next?
-Once you have created your first application, you can go to Kotlin hands-on labs and complete long-form Kotlin/JS tutorials
+Once you have created your first application, you can complete long-form Kotlin/JS tutorials
or check out the list of Kotlin/JS sample projects for inspiration. Both types of resources contain useful snippets and
patterns and can serve as a nice jump-off point for your own projects.
-### Hands-on labs
+### Tutorials
-* [Building Web Applications with React and Kotlin/JS](https://play.kotlinlang.org/hands-on/Building%20Web%20Applications%20with%20React%20and%20Kotlin%20JS/01_Introduction)
+* [Build a web application with React and Kotlin/JS — tutorial](js-react.md)
guides you through the process of building a simple web application using the React framework, shows how a type-safe Kotlin
DSL for HTML makes it easy to build reactive DOM elements, and illustrates how to use third-party React components and
obtain information from APIs, all while writing the whole application logic in pure Kotlin/JS.
diff --git a/docs/topics/js/js-hands-ons.md b/docs/topics/js/js-hands-ons.md
deleted file mode 100644
index 5327cc24f91..00000000000
--- a/docs/topics/js/js-hands-ons.md
+++ /dev/null
@@ -1,20 +0,0 @@
-[//]: # (title: Hands-on labs for Kotlin/JS)
-
-Hands-on labs are long-form tutorials that help you get to know a technology by guiding you through
-a self-contained project related to a specific topic.
-
-They include sample projects, which can serve as jumping-off points for your own projects, and contain useful snippets and patterns.
-
-For Kotlin/JS, the following hands-on labs are currently available:
-
-* [Building Web Applications with React and Kotlin/JS](https://play.kotlinlang.org/hands-on/Building%20Web%20Applications%20with%20React%20and%20Kotlin%20JS/)
-guides you through the process of building a simple web application
- using the React framework, shows how a typesafe Kotlin DSL for HTML makes it convenient to build reactive DOM elements,
- and illustrates how to use third-party React components, and how to obtain information from APIs,
- while writing the whole application logic in pure Kotlin/JS.
-* [Building a Full Stack Web App with Kotlin Multiplatform](https://play.kotlinlang.org/hands-on/Full%20Stack%20Web%20App%20with%20Kotlin%20Multiplatform/)
-teaches the concepts behind building an application that targets Kotlin/JVM and Kotlin/JS by building a client-server application
-that makes use of common code, serialization, and other multiplatform paradigms.
-It also provides a brief introduction into working with Ktor both as a server- and client-side framework.
-
-We are continuously working on expanding the set of hands-on labs to make it as easy as possible for you to learn more about Kotlin/JS and adjacent technologies.
\ No newline at end of file
diff --git a/docs/topics/js/js-overview.md b/docs/topics/js/js-overview.md
index 9e547b43c1b..bb36946d421 100644
--- a/docs/topics/js/js-overview.md
+++ b/docs/topics/js/js-overview.md
@@ -120,12 +120,12 @@ main Kotlin/JS benefits, shares some tips and use cases, and talks about the pla
If you're new to Kotlin, a good first step is to familiarize yourself with the [basic syntax](basic-syntax.md) of the language.
To start using Kotlin for JavaScript, please refer to [Set up a Kotlin/JS project](js-project-setup.md). You can also
-pick a [hands-on](#hands-on-labs-for-kotlin-js) lab to work through or check out the list of [Kotlin/JS sample projects](#sample-projects-for-kotlin-js)
+complete a [tutorial](#tutorials-for-kotlin-js) to work through or check out the list of [Kotlin/JS sample projects](#sample-projects-for-kotlin-js)
for inspiration. They contain useful snippets and patterns and can serve as nice jump-off points for your own projects.
-## Hands-on labs for Kotlin/JS
+### Tutorials for Kotlin/JS
-* [Building Web Applications with React and Kotlin/JS](https://play.kotlinlang.org/hands-on/Building%20Web%20Applications%20with%20React%20and%20Kotlin%20JS/01_Introduction)
+* [Build a web application with React and Kotlin/JS — tutorial](js-react.md)
guides you through the process of building a simple web application using the React framework, shows how a type-safe Kotlin
DSL for HTML makes it easy to build reactive DOM elements, and illustrates how to use third-party React components and
obtain information from APIs, all while writing the whole application logic in pure Kotlin/JS.
@@ -135,7 +135,7 @@ teaches the concepts behind building an application that targets Kotlin/JVM and
application that makes use of shared code, serialization, and other multiplatform paradigms. It also provides a brief
introduction to working with Ktor both as a server- and client-side framework.
-## Sample projects for Kotlin/JS
+### Sample projects for Kotlin/JS
* [Full-stack Spring collaborative to-do list](https://github.com/Kotlin/full-stack-spring-collaborative-todo-list-sample)
shows how to create a to-do list for collaborative work using `kotlin-multiplatform` with JS and JVM targets, Spring
diff --git a/docs/topics/js/js-react.md b/docs/topics/js/js-react.md
new file mode 100644
index 00000000000..73cf0aa2dc4
--- /dev/null
+++ b/docs/topics/js/js-react.md
@@ -0,0 +1,1308 @@
+[//]: # (title: Build a web application with React and Kotlin/JS — tutorial)
+
+This tutorial will teach you how to build a browser application with Kotlin/JS and the [React](https://reactjs.org/)
+framework. You will:
+
+* Complete usual kinds of tasks associated with building a typical React application.
+* Explore how [Kotlin's DSLs](type-safe-builders.md) can be used to help express concepts concisely and uniformly without
+sacrificing readability, allowing to write a fully-fledged application completely in Kotlin.
+* Learn how to use ready-made npm components, use external libraries, and publish the final application.
+
+The output will be a _KotlinConf Explorer_ web app dedicated to the [KotlinConf](https://kotlinconf.com/) event
+with links to conference talks. Users will be able to watch all the talks on one page and mark them as seen or unseen.
+
+The tutorial assumes you have prior knowledge of Kotlin and basic knowledge of HTML and CSS. Understanding the basic
+concepts behind React may help understand some sample code but is not strictly required.
+
+> You can get the final application as well as the intermediate steps [here](https://github.com/kotlin-hands-on/web-app-react-kotlin-js-gradle).
+> Each step is available from its own branch and is linked at the bottom of each corresponding section.
+>
+{type="note"}
+
+## Before you start
+
+1. Download and install the latest version of [IntelliJ IDEA](https://www.jetbrains.com/idea/download/index.html).
+2. Clone the [project template](https://github.com/kotlin-hands-on/web-app-react-kotlin-js-gradle) and open it in IntelliJ
+ IDEA. The template includes a basic Kotlin/JS Gradle project with all required configurations and dependencies:
+
+ * Dependencies and tasks in the `build.gradle.kts` file:
+
+ ```kotlin
+ dependencies {
+ // React, React DOM + Wrappers
+ implementation(enforcedPlatform("org.jetbrains.kotlin-wrappers:kotlin-wrappers-bom:1.0.0-pre.354"))
+ implementation("org.jetbrains.kotlin-wrappers:kotlin-react")
+ implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom")
+
+ // Kotlin React Emotion (CSS)
+ implementation("org.jetbrains.kotlin-wrappers:kotlin-emotion")
+
+ // Video Player
+ implementation(npm("react-player", "2.10.1"))
+
+ // Share Buttons
+ implementation(npm("react-share", "4.4.0"))
+
+ // Coroutines & serialization
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3")
+ }
+ ```
+
+ * An HTML template page in `src/main/resources/index.html` for inserting the JS code:
+
+ ```html
+
+
+
+
+ Hello, Kotlin/JS!
+
+
+
+
+
+
+ ```
+ {validate="false"}
+
+ Kotlin/JS projects are automatically bundled with all of your code and its dependencies into a single JavaScript file
+with the same name as the project: `confexplorer.js` when you build them. As a typical [JavaScript convention](https://faqs.skillcrush.com/article/176-where-should-js-script-tags-be-linked-in-html-documents),
+the content of the body (including the `root` div) is loaded first to ensure that the browser loads all page elements
+before the scripts.
+
+* A code snippet in `src/main/kotlin/Main.kt`:
+
+ ```kotlin
+ import kotlinx.browser.document
+
+ fun main() {
+ document.bgColor = "red"
+ }
+ ```
+
+### Run the development server
+
+The Kotlin/JS Gradle plugin comes by default with support for an embedded `webpack-dev-server`, allowing to run
+the application from the IDE without manually setting up any server.
+
+To test that the program successfully runs inside the browser, start the development server by invoking the `run` or
+`browserDevelopmentRun` (available in the `other` or `kotlin browser` directory) task from the Gradle tool window inside
+IntelliJ IDEA:
+
+{width=700}
+
+To run the program from the Terminal, use `./gradlew run` instead.
+
+When the project is compiled and bundled, a red, blank page will appear in a browser window:
+
+{width=700}
+
+### Enable hot reload / continuous mode
+
+Configure the _[continuous compilation](dev-server-continuous-compilation.md)_ mode, instead of manually compiling and
+executing your project every time the changes are made. Make sure to stop all running development server instances before
+proceeding.
+
+1. Edit a run configuration that IntelliJ IDEA automatically generates after running the Gradle `run` task for the first time:
+
+ {width=700}
+
+2. In the **Run/Debug Configurations** dialog, add the `--continuous` option to the arguments for the run configuration:
+
+ {width=700}
+
+ After applying the changes, you can use the **Run** button inside IntelliJ IDEA to start the development server back up.
+ To run the Gradle continuous builds from the Terminal, use `./gradlew run --continuous` instead.
+
+3. To test this feature, change the color of the page to blue in the `Main.kt` file while the Gradle task is running:
+
+ ```kotlin
+ document.bgColor = "blue"
+ ```
+
+ The project then recompiles, and after a reload the browser will show the new color.
+
+You can keep the development server running in the continuous mode during the development process. It will automatically
+rebuild and reload the page when you make changes.
+
+> You can find this state of the project on the `master` branch [here](https://github.com/kotlin-hands-on/web-app-react-kotlin-js-gradle/tree/master).
+>
+{type="note"}
+
+## Create a web app draft
+
+### Add the first static page with React
+
+To make your app display a simple message, replace the code in the `Main.kt` file as follows:
+
+```kotlin
+import kotlinx.browser.document
+import react.*
+import emotion.react.css
+import csstype.Position
+import csstype.px
+import react.dom.html.ReactHTML.h1
+import react.dom.html.ReactHTML.h3
+import react.dom.html.ReactHTML.div
+import react.dom.html.ReactHTML.p
+import react.dom.html.ReactHTML.img
+import react.dom.client.createRoot
+import kotlinx.serialization.Serializable
+
+fun main() {
+ val container = document.getElementById("root") ?: error("Couldn't find root container!")
+ createRoot(container).render(Fragment.create {
+ h1 {
+ +"Hello, React+Kotlin/JS!"
+ }
+ })
+}
+```
+{validate="false"}
+
+* The `render()` function instructs [kotlin-react-dom](https://github.com/JetBrains/kotlin-wrappers/tree/master/kotlin-react-dom)
+ to render a first HTML element inside a [fragment](https://reactjs.org/docs/fragments.html) to the `root` element.
+ This element is a container defined in `src/main/resources/index.html`, which was included in the template.
+* The content is an `
` header and uses a typesafe DSL to render HTML.
+* `h1` is a function that takes a lambda parameter. When you add the `+` sign in front of the string literal,
+ the `unaryPlus()` function is actually invoked using [operator overloading](operator-overloading.md).
+ It appends the string to the enclosed HTML element.
+
+When the project recompiles, the browser displays this HTML page:
+
+{width=700}
+
+### Convert HTML to Kotlin's typesafe HTML DSL
+
+The Kotlin [wrappers](https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-react/README.md) for React come
+with a [domain-specific language (DSL)](type-safe-builders.md) that allows writing HTML in
+pure Kotlin code. In this way, it's similar to [JSX](https://reactjs.org/docs/introducing-jsx.html) from JavaScript.
+However, with this markup being Kotlin, you get all the benefits of a statically typed language, such as autocomplete or
+type checking.
+
+Compare classic HTML code for the future web app and its typesafe variant in Kotlin:
+
+
+
+
+```html
+
KotlinConf Explorer
+
+
Videos to watch
+
John Doe: Building and breaking things
+
Jane Smith: The development process
+
Matt Miller: The Web 7.0
+
Videos watched
+
Tom Jerry: Mouseless development
+
+
+
John Doe: Building and breaking things
+
+
+```
+
+
+
+
+```kotlin
+h1 {
+ +"Hello, React+Kotlin/JS!"
+}
+div {
+ h3 {
+ +"Videos to watch"
+ }
+ p {
+ + "John Doe: Building and breaking things"
+ }
+ p {
+ +"Jane Smith: The development process"
+ }
+ p {
+ +"Matt Miller: The Web 7.0"
+ }
+ h3 {
+ +"Videos watched"
+ }
+ p {
+ +"Tom Jerry: Mouseless development"
+ }
+}
+div {
+ h3 {
+ +"John Doe: Building and breaking things"
+ }
+ img {
+ src = "https://via.placeholder.com/640x360.png?text=Video+Player+Placeholder"
+ }
+}
+```
+
+
+
+
+Copy the Kotlin code and update the `Fragment.create()` function call inside the `main()` function, replacing the previous `h1` tag.
+
+Wait for the browser to reload. The page should now look like this:
+
+{width=700}
+
+### Add videos using Kotlin constructs in markup
+
+There are some advantages in writing HTML in Kotlin using this DSL. You can manipulate your app using regular Kotlin
+constructs, like loops, conditions, collections, string interpolation
+
+You can now replace the hardcoded list of videos with a list of Kotlin objects:
+
+1. In `Main.kt`, create a `Video` [data class](data-classes.md) to hold together video attributes:
+
+ ```kotlin
+ data class Video(
+ val id: Int,
+ val title: String,
+ val speaker: String,
+ val videoUrl: String
+ )
+ ```
+
+2. Fill up the two lists for unwatched videos and watched videos, respectively. Add these declarations at
+ file-level in `Main.kt`:
+
+ ```kotlin
+ val unwatchedVideos = listOf(
+ Video(1, "Opening Keynote", "Andrey Breslav", "https://youtu.be/PsaFVLr8t4E"),
+ Video(2, "Dissecting the stdlib", "Huyen Tue Dao", "https://youtu.be/Fzt_9I733Yg"),
+ Video(3, "Kotlin and Spring Boot", "Nicolas Frankel", "https://youtu.be/pSiZVAeReeg")
+ )
+
+ val watchedVideos = listOf(
+ Video(4, "Creating Internal DSLs in Kotlin", "Venkat Subramaniam", "https://youtu.be/JzTeAM8N1-o")
+ )
+ ```
+
+3. To use these videos on the page, write a Kotlin `for` loop to iterate over the collection of unwatched `Video` objects.
+Replace the three `p` tags under "Videos to watch" with the following snippet:
+
+ ```kotlin
+ for (video in unwatchedVideos) {
+ p {
+ +"${video.speaker}: ${video.title}"
+ }
+ }
+ ```
+
+4. Apply the same process to modify the code for the single tag following "Videos watched" as well:
+
+ ```kotlin
+ for (video in watchedVideos) {
+ p {
+ +"${video.speaker}: ${video.title}"
+ }
+ }
+ ```
+
+Wait for the browser to reload. The layout should stay the same as before. You can add some more videos to the list to make
+sure that the loop is working.
+
+### Add styles with typesafe CSS
+
+The [kotlin-emotion](https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-emotion/) wrapper for the [Emotion](https://emotion.sh/docs/introduction)
+library allows specifying CSS attributes – even dynamic ones – right alongside HTML with JavaScript. Conceptually, that
+makes it similar to [CSS-in-JS](https://reactjs.org/docs/faq-styling.html#what-is-css-in-js) – but for Kotlin.
+The benefit of using a DSL is that you can use Kotlin code constructs to express formatting rules.
+
+The template project for this tutorial already includes the dependency needed to use `kotlin-emotion`:
+
+```kotlin
+dependencies {
+ // ...
+ // Kotlin React Emotion (CSS) (chapter 3)
+ implementation("org.jetbrains.kotlin-wrappers:kotlin-emotion")
+ // ...
+}
+```
+
+With `kotlin-emotion`, you can specify a `css` block inside HTML elements `div` and `h3`, where you can define the styles.
+
+To move the video player to the top right corner of the page, use CSS and adjust the code for the video player
+(the last `div` in the snippet):
+
+```kotlin
+div {
+ css {
+ position = Position.absolute
+ top = 10.px
+ right = 10.px
+ }
+ h3 {
+ +"John Doe: Building and breaking things"
+ }
+ img {
+ src = "https://via.placeholder.com/640x360.png?text=Video+Player+Placeholder"
+ }
+}
+```
+
+Feel free to experiment with some other styles. For example, you could change the `fontFamily`, or add some `color` to your UI.
+
+> You can find this state of the project on the `02-first-static-page` branch [here](https://github.com/kotlin-hands-on/web-app-react-kotlin-js-gradle/tree/02-first-static-page).
+>
+{type="note"}
+
+## Design app components
+
+The basic building blocks in React are called _[components](https://reactjs.org/docs/components-and-props.html)_.
+Components themselves can also be composed of other, smaller components. By combining components, you build your application.
+If you structure components to be generic and reusable, you'll be able to use them in multiple parts of the app without
+duplicating code or logic.
+
+The content of the `render()` function generally describes a basic component. The current layout of your application looks
+like this:
+
+{width=700}
+
+If you decompose your application into individual components, you'll end up with a more structured layout, in which
+each component handles its responsibilities:
+
+{width=700}
+
+Components encapsulate a particular functionality. Using components shortens source code and makes it easier to read and
+understand.
+
+### Add the main component
+
+To start creating application structure, first explicitly specify the main component for rendering into the `root`
+element, the `App`:
+
+1. Create a new `App.kt` file in the `src/main/kotlin` folder.
+2. Inside this file, add the following snippet, and move the typesafe HTML from `Main.kt` into the snippet:
+
+ ```kotlin
+ import kotlinx.coroutines.async
+ import react.*
+ import react.dom.*
+ import kotlinx.browser.window
+ import kotlinx.coroutines.*
+ import kotlinx.serialization.decodeFromString
+ import kotlinx.serialization.json.Json
+ import emotion.react.css
+ import csstype.Position
+ import csstype.px
+ import react.dom.html.ReactHTML.h1
+ import react.dom.html.ReactHTML.h3
+ import react.dom.html.ReactHTML.div
+ import react.dom.html.ReactHTML.p
+ import react.dom.html.ReactHTML.img
+
+ val App = FC {
+ // typesafe HTML goes here, starting with the first h1 tag!
+ }
+ ```
+
+ The `FC` function creates a [function component](https://reactjs.org/docs/components-and-props.html#function-and-class-components).
+
+3. In the `Main.kt` file, update the `main()` function as follows:
+
+ ```kotlin
+ fun main() {
+ val container = document.getElementById("root") ?: error("Couldn't find root container!")
+ createRoot(container).render(App.create())
+ }
+ ```
+
+ Now the program creates an instance of the `App` component and renders it to the specified container.
+
+For more information on React concepts, see its [documentation and guides](https://reactjs.org/docs/hello-world.html#how-to-read-this-guide).
+
+### Extract a list component
+
+Since the `watchedVideos` and `unwatchedVideos` lists both contain a list of videos, it makes sense to create a single
+reusable component, and only adjust the content displayed in the lists.
+
+The `VideoList` component follows the same pattern as the `App` component. It uses the `FC` builder function,
+and contains the code from the `unwatchedVideos` list.
+
+1. Create a new `VideoList.kt` file in the `src/main/kotlin` folder and add the following code:
+
+ ```kotlin
+ import kotlinx.browser.window
+ import react.*
+ import react.dom.*
+ import react.dom.html.ReactHTML.p
+
+ val VideoList = FC {
+ for (video in unwatchedVideos) {
+ p {
+ +"${video.speaker}: ${video.title}"
+ }
+ }
+ }
+ ```
+
+2. In `App.kt`, use the `VideoList` component by invoking it without parameters:
+
+ ```kotlin
+ // . . .
+ div {
+ h3 {
+ +"Videos to watch"
+ }
+ VideoList()
+
+ h3 {
+ +"Videos watched"
+ }
+ VideoList()
+ }
+ // . . .
+ ```
+
+ For now, the `App` component has no control over the content that is shown by the `VideoList` component. It's hard-coded,
+ so you see the same list twice.
+
+### Add props to pass data between components
+
+For reusing the `VideoList` component, it should be possible to fill it with different content. You can add
+the ability to pass the list of items as an attribute to the component. In React, these attributes are called _props_.
+When the props of a component are changed in React, the framework automatically re-renders the component.
+
+For `VideoList`, you'll need a prop containing the list of videos to be shown. Define an interface
+that holds all the props which can be passed to a `VideoList` component:
+
+1. Add the following definition to the `VideoList.kt` file:
+
+ ```kotlin
+ external interface VideoListProps : Props {
+ var videos: List