Skip to content

Commit

Permalink
feat(docs): update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
sawaYch committed Mar 29, 2024
1 parent c739077 commit 399fb3f
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 15 deletions.
167 changes: 163 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,166 @@
# Next Youtube Livechat Monorepo

This is the monorepo for next-youtube-livechat package hook, create with [Turborepo](https://turbo.build/repo).
Contains a demo NextJS 14 website demonstrate the usage of `next-youtube-livechat` react hook library.
Include a demo NextJS 14 website demonstrate the usage of `next-youtube-livechat` react hook library.

## Package `next-youtube-livechat`

Fetch YouTube live chat without API using NextJS which bypass CORS.
Demo site: [https://next-youtube-livechat.vercel.app/](https://next-youtube-livechat.vercel.app/)

<sup><sub>🚨 You will need to take full responsibility for your action 🚨</sub></sup>

### Getting started

#### Installation

> Package already provide types files
```ts
npm i next-youtube-livechat
```

#### Source Code

Hook

> React hook for getting livestream message data, event handling
- `src/hooks/useLiveChat.tsx`

Youtube related functions

> Use to parse chat message / emoji
> API functions contain payload for fetching live chatroom (without using YouTube Data API)
- `src/lib/yt-api-parser.ts`
- `src/lib/yt-api-requests.ts`

#### Usage

##### NextJS API

Add the follow API code to bypass CORS, otherwise this library will not work.
Here is the example for NextJS 14 app directory:

`app\api\yt-api\[...slug]\route.ts`

```ts
import { NextRequest, NextResponse } from 'next/server';

const YOUTUBE_URL = 'https://www.youtube.com';

const buildYouTubeEndpoint = (req: NextRequest) => {
const path = req.nextUrl.pathname.replace('/api/yt-api', '');
const suffix = `${path}${req.nextUrl.search}`;
const url = `${YOUTUBE_URL}${suffix}`;
return url;
};

const GET = async (req: NextRequest) => {
const res = await fetch(buildYouTubeEndpoint(req), { cache: 'no-store' })
.then((d) => d.text())
.then((d) => {
return d;
})
.catch((error) => {
throw new Error(`Server Action Failed: ${error.message}`);
});
return NextResponse.json(res, { status: 200 });
};

const POST = async (req: NextRequest) => {
const postData = await req.json();
const data = await fetch(buildYouTubeEndpoint(req), {
method: 'POST',
cache: 'no-store',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData),
})
.then((d) => d.json())
.catch((error) => {
throw new Error(`Server Action Failed: ${error.message}`);
});
return NextResponse.json(data, { status: 200 });
};

export { GET, POST };
```

##### Example

```ts
import { useLiveChat } from 'next-youtube-livechat';

/** Example Demo page component **/
export const Demo = () => {
/** loading state, optional. Can use to control show spinner before fetching start & hide spinner after fetching start **/
const [isLoading, setIsLoading] = useState<boolean>();

/** ready state, required. Use to control start/termination of chat message polling **/
const [isReady, setIsReady] = useState<boolean>();

/** url state, required. Use to provide YouTube livestream target to fetch chat message **/
const [url, setUrl] = useState<string | undefined>();

const onBeforeStart = useCallback(async () => {
setIsLoading(true);
}, [setIsLoading]);

const onStart = useCallback(async () => {
setIsLoading(false);
setIsReady(true);
}, [setIsLoading, setIsReady]);

const onChatItemsReceive = useCallback(async (newChatItems: ChatItem[], existingChatItems: ChatItem[]) => {
console.log('new chat items', newChatItems);
console.log('received chat items', existingChatItems);
}, []);

const onError = useCallback(async () => {
setIsLoading(false);
setIsReady(false);
setUrl();
}, [setIsLoading, setIsReady, setUrl]);

const { displayedMessage, rawChatItems, liveDetails } = useLiveChat({
url,
isReady,
onBeforeStart,
onStart,
onChatItemsReceive,
onError,
});

return (<div>
{liveDetails && (
<div className='items-center flex flex-col justify-center'>
<Image
src={liveDetails.thumbnail}
width={240}
height={160}
alt='thumbnail'
/>
<div>{liveDetails.title}</div>
<div>Channel Owner Name: {liveDetails.channelName}</div>
<div>Channel Profile URL: {liveDetails.channelUrl}</div>
</div>
)}
{displayedMessage?.map((it, index) => (
<span key={`${it.message}${index}`}>{it.message}</span>
))}
</div>)
}
```

### Reference

Part of the code is referenced from [LinaTsukusu/youtube-chat](https://github.com/LinaTsukusu/youtube-chat), many thanks 🙌




## Monorepo structure

Expand All @@ -24,7 +183,7 @@ Contains a demo NextJS 14 website demonstrate the usage of `next-youtube-livecha
└── turbo.json
```

- `apps/web` - Demo website
- `apps/web` - Demo website
- `packages/next-youtube-livechat` - React hook library `next-youtube-livechat`
- `packages/eslint-config` - eslint configurations (includes `eslint-config-next`, `eslint-config-prettier` and `eslint-config-turbo`)
- `packages/typescript-config` - tsconfig.json used throughout the monorepo
Expand All @@ -38,8 +197,8 @@ Restore dependencies:
npm i
```

To develop all apps and packages, run:
Both app & packages should be hot reload on file changed, and supporting linting & typecheck.
Developing apps & packages should be able to hot reload on file changed, also with linting & typecheck.
To develop (all apps and packages), run:

```sh
turbo dev
Expand Down
10 changes: 5 additions & 5 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"next": "^14.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"next-youtube-livechat": "*",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-slot": "^1.0.2",
Expand All @@ -25,8 +21,12 @@
"clsx": "^2.1.0",
"framer-motion": "^11.0.20",
"lucide-react": "^0.338.0",
"next": "^14.1.1",
"next-themes": "^0.2.1",
"next-youtube-livechat": "*",
"react": "^18.2.0",
"react-device-detect": "^2.2.3",
"react-dom": "^18.2.0",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
"zustand": "^4.5.2"
Expand All @@ -35,8 +35,8 @@
"@next/eslint-plugin-next": "^14.1.1",
"@repo/eslint-config": "*",
"@repo/typescript-config": "*",
"@types/eslint": "^8.56.5",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/eslint": "^8.56.5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
Expand Down
3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 11 additions & 4 deletions packages/next-youtube-livechat/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
# `next-youtube-livechat`

Fetch YouTube live chat without API using NextJS which bypass CORS.

🚨 You will need to take full responsibility for your action 🚨

Fetch YouTube live chat without API using NextJS which bypass CORS.
Demo site: [https://next-youtube-livechat.vercel.app/](https://next-youtube-livechat.vercel.app/)

<sup><sub>🚨 You will need to take full responsibility for your action 🚨</sub></sup>

## Getting started

### Installation

> Package already provide types files
```ts
npm i next-youtube-livechat
```

### Source Code

Hook
Expand Down
2 changes: 1 addition & 1 deletion packages/next-youtube-livechat/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next-youtube-livechat",
"version": "0.1.22",
"version": "0.1.23",
"private": false,
"description": "Fetch YouTube live chat without API using NextJS + React Hook which bypass CORS.",
"author": "Sawa",
Expand Down

0 comments on commit 399fb3f

Please sign in to comment.