This is the monorepo for next-youtube-livechat package hook, create with Turborepo.
Include a demo NextJS 14 website demonstrate the usage of next-youtube-livechat
react hook library.
Fetch YouTube live chat without API using NextJS which bypass CORS.
Demo site: https://next-youtube-livechat.vercel.app/
π¨ You will need to take full responsibility for your action π¨
Package already provide types files
npm i next-youtube-livechat
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
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
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 };
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>)
}
Part of the code is referenced from LinaTsukusu/youtube-chat, many thanks π
βββ README.md
βββ apps
β βββ web
βββ components.json
βββ next.config.mjs
βββ package-lock.json
βββ package.json
βββ packages
β βββ eslint-config
β βββ next-youtube-livechat
β βββ prettier-config
β βββ typescript-config
βββ postcss.config.js
βββ tailwind.config.ts
βββ tsconfig.json
βββ turbo.json
apps/web
- Demo websitepackages/next-youtube-livechat
- React hook librarynext-youtube-livechat
packages/eslint-config
- eslint configurations (includeseslint-config-next
,eslint-config-prettier
andeslint-config-turbo
)packages/typescript-config
- tsconfig.json used throughout the monorepopackages/prettier-config
- prettier config
Restore dependencies:
npm i
Developing apps & packages should be able to hot reload on file changed, also with linting & typecheck.
To develop (all apps and packages), run:
turbo dev
To build all apps and packages, run:
turbo build
turbo lint
turbo format
turbo format:fix # prettier fix
turbo typecheck # tsc --noEmit typecheck
Publish package local and manually:
turbo build # build dist for all the packages and apps
cd packages/next-youtube-livechat
#... do bump version stuffs
npm login
npm publish