> For the complete documentation index, see [llms.txt](https://dpapi.gitbook.io/docs-dpapi-mutliplayer/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dpapi.gitbook.io/docs-dpapi-mutliplayer/miscellaneous/tutorials.md).

# Tutorials

## WALKTHROUGH

### 1. Clone Calculator app (or any other React JS app)

```bash
git clone https://github.com/madzadev/calculator.git
```

Open the repository in your choice of code editor and run command <mark style="color:blue;">`npm install`</mark> to install the dependencies. You can test out the original app by running the command <mark style="color:blue;">`npm run start`</mark>.

### 2. Install DPAPI Packages

```bash
npm i @dpapi/server @dpapi/react
```

{% hint style="warning" %}
Remember to first uninstall React v16 and then re-install React v18

<mark style="color:orange;background-color:blue;">`npm uninstall react react-dom`</mark>

<mark style="color:orange;">`npm install react@18.2.0 react-dom@18.2.0`</mark>
{% endhint %}

### 3. Create RoomProvider

Wrap the child elements with <mark style="color:blue;">`RoomProvider`</mark>

<details>

<summary>src/index.js</summary>

<pre class="language-javascript" data-line-numbers><code class="lang-javascript">import React from "react";
import ReactDOM from "react-dom";
<strong>import {RoomProvider} from "@dpapi/react";
</strong>
import App from "./App";
import "./index.css";

const rootElement = document.getElementById("root");
ReactDOM.render(
<strong>  &#x3C;RoomProvider>
</strong>    &#x3C;App />
<strong>  &#x3C;/RoomProvider>,
</strong>  rootElement
);
</code></pre>

</details>

### 4. Add Multiplayer Functionalities

<mark style="color:blue;">`useContext`</mark> is used to create client socket connection.\ <mark style="color:blue;">`joinRoom`</mark>, <mark style="color:blue;">`roomCount`</mark> and <mark style="color:blue;">`liveCursors`</mark> are added to the React App which shall be rendered.

<details>

<summary>src/App.js</summary>

<pre class="language-javascript" data-line-numbers><code class="lang-javascript">// Retain all app import statements 👈🏼
<strong>import {useContext} from "react";
</strong><strong>import "./App.css";
</strong><strong>import {
</strong><strong>  clientSocket,
</strong><strong>  roomCount,
</strong><strong>  liveCursors,
</strong><strong>  joinRoom,
</strong><strong>} from "@dpapi/react";
</strong>
// Retain original calculator app code 👈🏼

const App = () => {
<strong>  const socket = useContext(clientSocket);
</strong><strong>  joinRoom("calcRoom", socket);
</strong><strong>  const usersCount = roomCount("calcRoom", socket);
</strong><strong>  const cursors = liveCursors("calcRoom", socket);
</strong>
  let [calc, setCalc] = useState({/* Retain code here */});
  // Retain original calculator app code 👈🏼
  const resetClickHandler = () => {/* Retain code here🏼*/};

  return (
<strong>    &#x3C;div className="App"> // ❗ Remember to add a CSS file
</strong><strong>      &#x3C;h1>Number of users in the room: {usersCount}&#x3C;/h1>
</strong><strong>      {cursors.map((cursor, index) => {
</strong><strong>        if (cursor.socketId !== socket.id) {
</strong><strong>          return (
</strong><strong>            &#x3C;div
</strong><strong>              key={cursor.socketId || index}
</strong><strong>              className="other-cursor" // ❗ Style your cursors with CSS
</strong><strong>              style={{
</strong><strong>                left: cursor.x,
</strong><strong>                top: cursor.y,
</strong><strong>              }}
</strong><strong>            />
</strong><strong>          );
</strong><strong>        } else { return null; }
</strong><strong>      })}
</strong><strong>      &#x3C;br />
</strong>      &#x3C;Wrapper>
        // Retain original calculator app code 👈🏼
      &#x3C;/Wrapper>
<strong>    &#x3C;/div>
</strong>  );
};

export default App;
</code></pre>

</details>

### 5. Cursor CSS Elements

Create a new file called <mark style="color:blue;">`App.css`</mark> in the <mark style="color:blue;">`src`</mark> directory.

<details>

<summary>src/App.css</summary>

<pre class="language-css" data-line-numbers><code class="lang-css"><strong>.App {
</strong><strong>  text-align: center;
</strong><strong> }
</strong><strong>
</strong><strong>.other-cursor {
</strong><strong>  position: absolute;
</strong><strong>  width: 10px;
</strong><strong>  height: 10px;
</strong><strong>  border: 0;
</strong><strong>  border-radius: 50%;
</strong><strong>  background-color: red;
</strong><strong> }
</strong></code></pre>

</details>

## <mark style="color:purple;">EXTRA: Custom Cursor</mark>

In this section, we will assign random cursor icons to every client.\
This is useful for providing a fun and dynamic user experience in a shared space.

We make use of React <mark style="color:purple;">`useState`</mark> & <mark style="color:purple;">`useEffect`</mark> hooks to assign and re-render cursor icons.

<details>

<summary>src/App.js</summary>

<pre class="language-javascript" data-line-numbers><code class="lang-javascript">// Retain all app import statements 👈🏼
<strong>import {useEffect} from "react";
</strong>// Retain original calculator app code 👈🏼

<strong>const cursorUrlArray = [
</strong><strong>  "https://icons.iconarchive.com/icons/svengraph/daft-punk/256/Daft-Punk-Guyman-Off-icon.png",
</strong><strong>  "https://icons.iconarchive.com/icons/everaldo/starwars/128/Darth-Vader-icon.png",
</strong><strong>  "https://icons.iconarchive.com/icons/everaldo/starwars/128/clone-old-icon.png",
</strong><strong>  "https://icons.iconarchive.com/icons/svengraph/daft-punk/256/Daft-Punk-Thomas-On-icon.png",
</strong><strong>];
</strong>
const App = () => {

  // Retain DPAPI functions 👈🏼
  
<strong>  const [cursorUrl, setCursorUrl] = useState("");
</strong><strong>  useEffect(() => {
</strong><strong>  setCursorUrl(
</strong><strong>    cursorUrlArray[Math.floor(Math.random() * cursorUrlArray.length)]
</strong><strong>  );
</strong><strong>  },[]);
</strong>
  let [calc, setCalc] = useState({/* Retain code here */});
  // Retain original calculator app code 👈🏼
  const resetClickHandler = () => {/* Retain code here🏼*/};

  return (
        // Retain DPAPI code from above 👈🏼
              &#x3C;div
              key={cursor.socketId || index}
              className="other-cursor" // ❗ Style your cursors with CSS
              style={{
                left: cursor.x,
                top: cursor.y,
<strong>                backgroundImage: `url(${cursorUrl})`,
</strong>              }}
        // Retain all other code from above 👈🏼
    );
};

export default App;
</code></pre>

</details>

{% hint style="info" %}
Inside the <mark style="color:blue;">`useEffect`</mark> hook, the <mark style="color:blue;">`setCursorUrl`</mark> function is called to randomly select one of the <mark style="color:blue;">`cursorUrl`</mark> values from the array and set it as the initial state of <mark style="color:blue;">`cursorUrl`</mark>
{% endhint %}

### <mark style="color:purple;">Update Cursor CSS Elements</mark>

<details>

<summary>src/App.css</summary>

<pre class="language-css" data-line-numbers><code class="lang-css">.App {
  text-align: center;
 }
 
.other-cursor {
    position : absolute;
    width: 35px;
    height: 35px;
<strong>    background-size: contain;
</strong><strong>    border-radius: 100%;
</strong>}
</code></pre>

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dpapi.gitbook.io/docs-dpapi-mutliplayer/miscellaneous/tutorials.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
