Package Exports
- next-youtube-livechat
- next-youtube-livechat/dist/index.js
- next-youtube-livechat/dist/index.mjs
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (next-youtube-livechat) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
next-youtube-livechat
Fetch YouTube live chat without API using NextJS which bypass CORS.
🚨 You will need to take full responsibility for your action 🚨
Demo site: https://next-youtube-livechat.vercel.app/
Getting started
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.tssrc/lib/yt-api-requests.ts
Next Backend API
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
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
import useLiveChat from '@/hooks/useLiveChat';
import { ChatItem } from '@/types/yt-data';
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, cleanUp } = useLiveChat({
url,
isReady,
onBeforeStart,
onStart,
onChatItemsReceive,
onError,
});
return (<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, many thanks 🙌