From e8804921fd763f8eb1d4bfbe57f165e805edaf94 Mon Sep 17 00:00:00 2001 From: Jonas Schell Date: Mon, 16 Sep 2024 12:21:35 +0200 Subject: [PATCH 1/3] cleanup css --- frontend/app/globals.css | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/frontend/app/globals.css b/frontend/app/globals.css index 13d40b8..b5c61c9 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -1,27 +1,3 @@ @tailwind base; @tailwind components; @tailwind utilities; - -:root { - --background: #ffffff; - --foreground: #171717; -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; -} - -@layer utilities { - .text-balance { - text-wrap: balance; - } -} From c8ea468f91c0486278fb68151ccf0256f00e2b94 Mon Sep 17 00:00:00 2001 From: Jonas Schell Date: Mon, 16 Sep 2024 12:21:47 +0200 Subject: [PATCH 2/3] clean up layout --- frontend/app/layout.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 1a3f956..a384131 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -1,11 +1,5 @@ -import type { Metadata } from "next"; import "./globals.css"; -export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", -}; - export default function RootLayout({ children, }: Readonly<{ From c75b3a06e44725bc4efe22cd1c6c6ae63bcbcca2 Mon Sep 17 00:00:00 2001 From: Jonas Schell Date: Mon, 16 Sep 2024 12:22:54 +0200 Subject: [PATCH 3/3] move endpoint in api folder --- frontend/app/api/connection-details/route.ts | 68 ++++++++++++++++++++ frontend/app/page.tsx | 5 +- 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 frontend/app/api/connection-details/route.ts diff --git a/frontend/app/api/connection-details/route.ts b/frontend/app/api/connection-details/route.ts new file mode 100644 index 0000000..d46c1c2 --- /dev/null +++ b/frontend/app/api/connection-details/route.ts @@ -0,0 +1,68 @@ +import { + AccessToken, + AccessTokenOptions, + VideoGrant, +} from "livekit-server-sdk"; +import { NextResponse } from "next/server"; + +const API_KEY = process.env.LIVEKIT_API_KEY; +const API_SECRET = process.env.LIVEKIT_API_SECRET; +const LIVEKIT_URL = process.env.LIVEKIT_URL; + +export type ConnectionDetails = { + serverUrl: string; + roomName: string; + participantName: string; + participantToken: string; +}; + +export async function GET() { + try { + // Generate participant token + const participantIdentity = `voice_assistant_user_${Math.round( + Math.random() * 10_000 + )}`; + const participantToken = await createParticipantToken( + { + identity: participantIdentity, + }, + "roomName" + ); + + if (LIVEKIT_URL === undefined) { + throw new Error("LIVEKIT_URL is not defined"); + } + + // Return connection details + const data: ConnectionDetails = { + serverUrl: LIVEKIT_URL, + roomName: "voice_assistant_room", + participantToken: participantToken, + participantName: participantIdentity, + }; + return NextResponse.json(data); + } catch (error) { + if (error instanceof Error) { + console.error(error); + + return new NextResponse(error.message, { status: 500 }); + } + } +} + +function createParticipantToken( + userInfo: AccessTokenOptions, + roomName: string +) { + const at = new AccessToken(API_KEY, API_SECRET, userInfo); + at.ttl = "5m"; + const grant: VideoGrant = { + room: roomName, + roomJoin: true, + canPublish: true, + canPublishData: true, + canSubscribe: true, + }; + at.addGrant(grant); + return at.toJwt(); +} diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index d3e3b95..d13cfbd 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -11,7 +11,7 @@ import { } from "@livekit/components-react"; import { useCallback, useState } from "react"; import { MediaDeviceFailure } from "livekit-client"; -import type { ConnectionDetails } from "./connection-details/route"; +import type { ConnectionDetails } from "./api/connection-details/route"; export default function Page() { const [connectionDetails, updateConnectionDetails] = useState< @@ -20,7 +20,8 @@ export default function Page() { const onConnectButtonClicked = useCallback(async () => { const url = new URL( - process.env.NEXT_PUBLIC_CONN_DETAILS_ENDPOINT ?? "/connection-details", + process.env.NEXT_PUBLIC_CONN_DETAILS_ENDPOINT ?? + "/api/connection-details", window.location.origin ); const response = await fetch(url.toString());