diff --git a/docs/tutorials/create-dapp.md b/docs/tutorials/create-dapp.md
new file mode 100644
index 00000000..893ae662
--- /dev/null
+++ b/docs/tutorials/create-dapp.md
@@ -0,0 +1,422 @@
+---
+title: Create dApp in React
+id: create-dapp
+slug: /create-dapp
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+In this tutorial we will go over creating dApp in React with the `bee-js` library. Once build this dApp can be hosted directly on the Swarm network and interact with it.
+
+## Creating the dApp boilerplate
+
+We will use React Create App to bootstrap the environment for us. Run the following command (you can replace the `dApp` with your own project name).
+
+
+
+
+```sh
+npx create-react-app dApp
+```
+
+
+
+
+```sh
+npm init react-app dApp
+```
+
+
+
+
+```sh
+yarn create react-app dApp
+```
+
+
+
+
+For typescript support don't forget to add the `--template typescript` option:
+
+
+
+
+```sh
+npx create-react-app dApp --template typescript
+```
+
+
+
+
+```sh
+npm init react-app dApp --template typescript
+```
+
+
+
+
+```sh
+yarn create react-app dApp --template typescript
+```
+
+
+
+
+## Adding bee-js
+
+First of all, we need to add `bee-js` as a dependency to the project. Navigate to the project directory (e.g. in our case `cd dApp`) and let's install `bee-js`:
+
+
+
+
+```sh
+npm install @ethersphere/bee-js --save
+```
+
+
+
+
+```sh
+yarn add @ethersphere/bee-js --save
+```
+
+
+
+
+Now let's edit the main App file.
+
+
+
+
+```ts title="src/App.tsx"
+import React, { useState } from 'react'
+import './App.css'
+import { Bee } from '@ethersphere/bee-js'
+
+const beeUrl = "https://gateway.ethswarm.org"
+const bee = new Bee(beeUrl)
+
+function App() {
+ const [ file, setFile ] = useState(null)
+ const [ link, setLink ] = useState(null)
+ const [ uploading, setUploading ] = useState(false)
+
+ const handleSubmit = async (event: React.FormEvent)=> {
+ event.preventDefault()
+
+ if (file) {
+ setUploading(true)
+ const hash = await bee.uploadFile(file)
+ setLink(`${beeUrl}/files/${hash}`)
+ setUploading(false)
+ }
+ }
+
+ const onFileChange = (e: React.ChangeEvent) => {
+ const f = e.target && e.target.files && e.target.files[0]
+
+ setFile(f)
+ }
+
+ return (
+
+
Upload file to Swarm
+
+ { uploading &&
Uploading... }
+ { link &&
{link} }
+
+ )
+}
+
+export default App
+```
+
+
+
+
+```js title="src/App.jsx"
+import React, { useState } from 'react'
+import './App.css'
+import { Bee } from '@ethersphere/bee-js'
+
+const beeUrl = "https://gateway.ethswarm.org"
+const bee = new Bee(beeUrl)
+
+function App() {
+ const [ file, setFile ] = useState(null)
+ const [ link, setLink ] = useState(null)
+ const [ uploading, setUploading ] = useState(false)
+
+ const handleSubmit = async (event)=> {
+ event.preventDefault()
+
+ if (file) {
+ setUploading(true)
+ const hash = await bee.uploadFile(file)
+ setLink(`${beeUrl}/files/${hash}`)
+ setUploading(false)
+ }
+ }
+
+ const onFileChange = (e) => {
+ const f = e.target && e.target.files && e.target.files[0]
+
+ setFile(f)
+ }
+
+ return (
+
+
Upload file to Swarm
+
+ { uploading &&
Uploading... }
+ { link &&
{link} }
+
+ )
+}
+
+export default App
+```
+
+
+
+
+Let's break it down, the first important lines are importing the `Bee` class and creating the bee instance:
+
+
+
+
+```ts
+import { Bee } from '@ethersphere/bee-js'
+
+const beeUrl = "https://gateway.ethswarm.org"
+const bee = new Bee(beeUrl)
+```
+
+
+
+
+```js
+import { Bee } from '@ethersphere/bee-js'
+
+const beeUrl = "https://gateway.ethswarm.org"
+const bee = new Bee(beeUrl)
+```
+
+
+
+
+Next we'll have a look at the content of the `App` function. At the start of the function, we create few state variables. The `file` will hold the file to be uploaded, the `link` eventually contains the URL to download the file once it is uploaded to Swarm, and the `uploading` value indicates if the file is being uploaded right now.
+
+At the bottom of the `App` function there is a JSX code with a header, simple form to upload a single file and two text fields that are conditionally displayed. The important thing to notice is the `onFileChange` handler on the file input and the `handleSubmit` function.
+
+
+
+
+```ts
+function App() {
+ const [ file, setFile ] = useState(null)
+ const [ link, setLink ] = useState(null)
+ const [ uploading, setUploading ] = useState(false)
+
+ // Omitted code...
+
+ return (
+
+
Upload file to Swarm
+
+ { uploading &&
Uploading... }
+ { link &&
{link} }
+
+ )
+}
+```
+
+
+
+
+```js
+function App() {
+ const [ file, setFile ] = useState(null)
+ const [ link, setLink ] = useState(null)
+ const [ uploading, setUploading ] = useState(false)
+
+ // Omitted code...
+
+ return (
+
+
Upload file to Swarm
+
+ { uploading &&
Uploading... }
+ { link &&
{link} }
+
+ )
+}
+```
+
+
+
+
+Lets disect the two handlers. The `onFileChange` function listens to the file input changes and when a new file is selected, it just stores it in the `file` state variable.
+
+
+
+
+```ts
+const onFileChange = (e: React.ChangeEvent) => {
+ const f = e.target && e.target.files && e.target.files[0]
+
+ setFile(f)
+}
+```
+
+
+
+
+```js
+const onFileChange = (e) => {
+ const f = e.target && e.target.files && e.target.files[0]
+
+ setFile(f)
+}
+```
+
+
+
+
+
+The `handleSubmit` function does all the interesting work. If a file is selected, it uploads it to Swarm using the `uploadFile` function which returns the hash of the file. The function then sets the download URL and marks the upload process done.
+
+
+
+
+```ts
+ const handleSubmit = async (event: React.FormEvent)=> {
+ event.preventDefault()
+
+ if (file) {
+ setUploading(true)
+ const hash = await bee.uploadFile(file)
+ setLink(`${beeUrl}/files/${hash}`)
+ setUploading(false)
+ }
+ }
+```
+
+
+
+
+```js
+ const handleSubmit = async (event)=> {
+ event.preventDefault()
+
+ if (file) {
+ setUploading(true)
+ const hash = await bee.uploadFile(file)
+ setLink(`${beeUrl}/files/${hash}`)
+ setUploading(false)
+ }
+ }
+```
+
+
+
+
+## Making it a dApp - uploading to Swarm
+
+For the project to trully be a dApp, it should not be hosted on any centralised system. One way to achieve that is to upload it to Swarm. Before we do so, we need to edit few more things and build the project.
+
+Let's start with the `package.json` file. Here we need to set the homepage. This line makes the build process use relative path in the resulting bundle.
+
+```
+ "homepage": ".",
+```
+
+Next, we need to build the project with the provided build command.
+
+
+
+
+```sh
+npm run build
+```
+
+
+
+
+```sh
+yarn build
+```
+
+
+
+
+This will create a `dist` folder that should be uploaded to the Swarm. We are working on `swarm-cli` which will make the upload process easier, but in the mean time you can follow the [Host Your Website on Swarm tutorial in the bee docs](https://docs.ethswarm.org/docs/getting-started/host-your-website-using-ens).
\ No newline at end of file
diff --git a/sidebars.js b/sidebars.js
index 6b2d6f88..d8a9818e 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -12,6 +12,14 @@ module.exports = {
],
collapsed: false
},
+ {
+ type: 'category',
+ label: 'Tutorials',
+ items: [
+ 'tutorials/create-dapp',
+ ],
+ collapsed: false
+ },
{
type: 'category',
label: 'API Reference',