> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Pipe Client Implementation

> You can use our client (frontend) SDKs to easily implement Pipe into your product.

## Frontend Packages

`@onehop/client`: The core library used by all other framework-specific
packages. Can also be used independently.\
`@onehop/react`: Our React-specific implementations for Pipe and Channels.

## Integrating Pipe with a React App

### Installing dependencies

Start off by adding both of our frontend packages to your project

```sh theme={null}
# Using npm
npm i @onehop/client @onehop/react

# Using yarn
yarn add @onehop/client @onehop/react
```

### Initializing the Hop SDK

Grab your **project ID** from the
[Project Settings page](https://console.hop.io/project/settings).

You should call the `init` function outside of a React component. For example,
in your application's entrypoint file:

```jsx theme={null}
import React from "react";
import ReactDOM from "react-dom";
import { hop } from "@onehop/client";

import App from "./App";

hop.init({ projectId: "project_xxx" // TODO: replace with your project ID });

ReactDOM.render(<App />, document.getElementById("root"));

```

### Integrating Pipe with React Hooks

The `@onehop/react` package exposes a collection of React hooks which allow you
to easily implement product features into your app. We'll focus on `usePipeRoom`
in this section.

#### `usePipeRoom`

`usePipeRoom` takes in an object as it's first and only argument, consisting of
`joinToken` and `ref`, where `ref` is a
[React reference](https://react.dev/learn/manipulating-the-dom-with-refs) to a video element.

Let's jump into an example bare-minimum component:

```jsx theme={null}
import {useRef} from 'react';
import {usePipeRoom} from '@onehop/react';

const joinToken = 'prjt_xxx'; // TODO: replace this with a real Pipe join token

export function Livestream() {
	const videoRef = useRef(null);

	const room = usePipeRoom({
		joinToken,
		ref: videoRef,
	});

	return (
		<>
			<button disabled={!room.canPlay} onClick={() => videoRef.current?.play()}>
				play
			</button>

			<video ref={videoRef} />
		</>
	);
}
```

As you can see, Pipe allows you to provide your own video element - Pipe just
hooks into it and controls the video source and live scrubbing. This gives you
flexibility to use any player wrapper or implement the video element however you
want.

`usePipeRoom` returns the following object:

| field        | type    | description                                   |
| ------------ | ------- | --------------------------------------------- |
| live         | boolean | whether the current room is live or offline   |
| canPlay      | boolean | whether the room is able to play the stream   |
| susbcription | string  | one of: available, unavailable, non\_existent |

## Integrating Pipe with Vanilla JS

```ts theme={null}
import {hop, pipe} from '@onehop/client';

// TypeScript only — declaring that `node` is a variable
// that exists, and is a DOM Video element
declare const node: HTMLVideoElement;

const client = hop.init({
	projectId: 'project_xxx',
});

const joinToken = 'join_token_xxx';

client.subscribeToPipeRoom(joinToken);

client.getRoomStateMap().addListener(map => {
	const room = map.get(joinToken);

	if (
		!room ||
		room.subscription !== 'available' ||
		!room.connection.llhls?.edge_endpoint
	) {
		console.log('Not ready:', {room});
		return;
	}

	pipe.mount(node, room.connection.llhls.edge_endpoint);
});
```
