Skip to content

Commit 8c4ebc7

Browse files
committed
feat: initially take apart the agent-starter-react project and hack it into roughly the shape I want
1 parent 6b2237e commit 8c4ebc7

File tree

6 files changed

+452
-151
lines changed

6 files changed

+452
-151
lines changed

app/(app)/embed/page.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { headers } from 'next/headers';
2+
import EmbedAgentClient from '@/components/embed-agent-client';
3+
import { getAppConfig, getOrigin } from '@/lib/utils';
4+
5+
export default async function Embed() {
6+
const hdrs = await headers();
7+
const origin = getOrigin(hdrs);
8+
9+
// FIXME: what is this appConfig thing used for? Do I need it for the embed?
10+
const appConfig = await getAppConfig(origin);
11+
12+
return (
13+
<EmbedAgentClient appConfig={appConfig} />
14+
);
15+
}

app/(app)/layout.tsx

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,32 @@ export default async function AppLayout({ children }: AppLayoutProps) {
1212

1313
return (
1414
<>
15-
<header className="fixed top-0 left-0 z-50 hidden w-full flex-row justify-between p-6 md:flex">
16-
<a
17-
target="_blank"
18-
rel="noopener noreferrer"
19-
href="https://livekit.io"
20-
className="scale-100 transition-transform duration-300 hover:scale-110"
21-
>
22-
<img src={logo} alt={`${companyName} Logo`} className="block size-6 dark:hidden" />
23-
<img
24-
src={logoDark ?? logo}
25-
alt={`${companyName} Logo`}
26-
className="hidden size-6 dark:block"
27-
/>
28-
</a>
29-
<span className="text-foreground font-mono text-xs font-bold tracking-wider uppercase">
30-
Built with{' '}
31-
<a
32-
target="_blank"
33-
rel="noopener noreferrer"
34-
href="https://docs.livekit.io/agents"
35-
className="underline underline-offset-4"
36-
>
37-
LiveKit Agents
38-
</a>
39-
</span>
40-
</header>
15+
{/* <header className="fixed top-0 left-0 z-50 hidden w-full flex-row justify-between p-6 md:flex"> */}
16+
{/* <a */}
17+
{/* target="_blank" */}
18+
{/* rel="noopener noreferrer" */}
19+
{/* href="https://livekit.io" */}
20+
{/* className="scale-100 transition-transform duration-300 hover:scale-110" */}
21+
{/* > */}
22+
{/* <img src={logo} alt={`${companyName} Logo`} className="block size-6 dark:hidden" /> */}
23+
{/* <img */}
24+
{/* src={logoDark ?? logo} */}
25+
{/* alt={`${companyName} Logo`} */}
26+
{/* className="hidden size-6 dark:block" */}
27+
{/* /> */}
28+
{/* </a> */}
29+
{/* <span className="text-foreground font-mono text-xs font-bold tracking-wider uppercase"> */}
30+
{/* Built with{' '} */}
31+
{/* <a */}
32+
{/* target="_blank" */}
33+
{/* rel="noopener noreferrer" */}
34+
{/* href="https://docs.livekit.io/agents" */}
35+
{/* className="underline underline-offset-4" */}
36+
{/* > */}
37+
{/* LiveKit Agents */}
38+
{/* </a> */}
39+
{/* </span> */}
40+
{/* </header> */}
4141
{children}
4242
</>
4343
);

app/(app)/page.tsx

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,96 @@
1-
import { headers } from 'next/headers';
2-
import { App } from '@/components/app';
3-
import { getAppConfig, getOrigin } from '@/lib/utils';
1+
import { ApertureIcon, PhoneIcon, EnvelopeIcon } from '@phosphor-icons/react/dist/ssr';
2+
3+
function Logo() {
4+
return (
5+
<div className="flex items-center gap-3">
6+
<ApertureIcon className="block size-6" />
7+
<span className="text-foreground font-mono text-sm font-bold tracking-wider uppercase -mb-0.25">
8+
ACME Co
9+
</span>
10+
</div>
11+
);
12+
}
413

514
export default async function Page() {
6-
const hdrs = await headers();
7-
const origin = getOrigin(hdrs);
8-
const appConfig = await getAppConfig(origin);
15+
return (
16+
<div>
17+
{/* Dummy app header */}
18+
<header className="fixed top-0 left-0 z-50 h-18 w-full flex flex-row justify-center p-6 bg-bg3">
19+
<div className="w-full px-2 max-w-4xl flex justify-between">
20+
<Logo />
21+
<div className="hidden md:flex items-center gap-8">
22+
{["Home", "Product", "Contact"].map(label => (
23+
<span
24+
key={label}
25+
className="text-foreground font-mono text-sm font-bold tracking-wider uppercase hover:text-fgAccent hover:underline select-none"
26+
>
27+
{label}
28+
</span>
29+
))}
30+
</div>
31+
</div>
32+
</header>
33+
34+
{/* Dummy app contents */}
35+
<div className="mx-auto my-auto mt-18 pt-4 px-2 max-w-4xl flex flex-col gap-4">
36+
<div className="h-[320px] border border-dashed border-fg4" />
37+
<div className="flex gap-4">
38+
<div className="h-[320px] border border-dashed border-fg4 grow shrink" />
39+
<div className="h-[320px] border border-dashed border-fg4 grow shrink" />
40+
<div className="h-[320px] border border-dashed border-fg4 grow shrink" />
41+
</div>
42+
<div className="h-[320px] border border-dashed border-fg4" />
43+
44+
<div className="flex justify-between gap-8 border-t border-t-seperator1 py-8">
45+
<div>
46+
<Logo />
47+
</div>
48+
49+
<div className="flex gap-8">
50+
<div className="flex flex-col gap-4 min-w-[120px]">
51+
<span className="font-mono text-xs font-semibold uppercase tracking-widest text-fg3">Product</span>
52+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">Camera</span>
53+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">Aperture</span>
54+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">Light Box</span>
55+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">Backdrop</span>
56+
</div>
57+
<div className="flex flex-col gap-4 min-w-[120px]">
58+
<span className="font-mono text-xs font-semibold uppercase tracking-widest text-fg3">Resources</span>
59+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">Camera</span>
60+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">Aperture</span>
61+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">Light Box</span>
62+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">Backdrop</span>
63+
</div>
64+
65+
<div className="flex flex-col gap-4">
66+
<span className="font-mono text-xs font-semibold uppercase tracking-widest text-fg3">Support</span>
67+
68+
{/* Inline livekit embed */}
69+
<div className="h-[64px]">
70+
<iframe
71+
className="w-[330px]"
72+
src="/embed"
73+
/>
74+
</div>
975

10-
return <App appConfig={appConfig} />;
76+
<div className="flex gap-4 justify-between">
77+
<div className="flex items-center gap-2">
78+
<PhoneIcon size={20} />
79+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">
80+
555-123-4567
81+
</span>
82+
</div>
83+
<div className="flex items-center gap-2">
84+
<EnvelopeIcon size={20} />
85+
<span className="flex gap-2 items-baseline text-sm cursor-pointer hover:underline">
86+
87+
</span>
88+
</div>
89+
</div>
90+
</div>
91+
</div>
92+
</div>
93+
</div>
94+
</div>
95+
);
1196
}

components/app.tsx renamed to components/embed-agent-client.tsx

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ interface AppProps {
1818
appConfig: AppConfig;
1919
}
2020

21-
export function App({ appConfig }: AppProps) {
21+
function EmbedAgentClient({ appConfig }: AppProps) {
2222
const room = useMemo(() => new Room(), []);
2323
const [sessionStarted, setSessionStarted] = useState(false);
2424
const { connectionDetails, refreshConnectionDetails } = useConnectionDetails();
@@ -43,19 +43,29 @@ export function App({ appConfig }: AppProps) {
4343
}, [room, refreshConnectionDetails]);
4444

4545
useEffect(() => {
46-
if (sessionStarted && room.state === 'disconnected' && connectionDetails) {
47-
Promise.all([
48-
room.localParticipant.setMicrophoneEnabled(true, undefined, {
49-
preConnectBuffer: appConfig.isPreConnectBufferEnabled,
50-
}),
51-
room.connect(connectionDetails.serverUrl, connectionDetails.participantToken),
52-
]).catch((error) => {
53-
toastAlert({
54-
title: 'There was an error connecting to the agent',
55-
description: `${error.name}: ${error.message}`,
56-
});
57-
});
46+
if (!sessionStarted) {
47+
return;
48+
}
49+
if (room.state !== 'disconnected') {
50+
return;
51+
}
52+
if (!connectionDetails) {
53+
return;
5854
}
55+
56+
Promise.all([
57+
room.localParticipant.setMicrophoneEnabled(true, undefined, {
58+
preConnectBuffer: appConfig.isPreConnectBufferEnabled,
59+
}),
60+
room.connect(connectionDetails.serverUrl, connectionDetails.participantToken),
61+
]).catch((error) => {
62+
console.error('Error connecting to agent:', error);
63+
toastAlert({
64+
title: 'There was an error connecting to the agent',
65+
description: `${error.name}: ${error.message}`,
66+
});
67+
});
68+
5969
return () => {
6070
room.disconnect();
6171
};
@@ -64,7 +74,9 @@ export function App({ appConfig }: AppProps) {
6474
const { startButtonText } = appConfig;
6575

6676
return (
67-
<>
77+
// FIXME: something is wrong spacing wise here, without the margin of 1px around the outside,
78+
// the border gets cut off the edge of the screen?
79+
<div className="relative h-16 bg-background rounded-[31px] border px-3 h-16 drop-shadow-md/3">
6880
<MotionWelcome
6981
key="welcome"
7082
startButtonText={startButtonText}
@@ -78,7 +90,9 @@ export function App({ appConfig }: AppProps) {
7890
<RoomContext.Provider value={room}>
7991
<RoomAudioRenderer />
8092
<StartAudio label="Start Audio" />
93+
8194
{/* --- */}
95+
8296
<MotionSessionView
8397
key="session-view"
8498
appConfig={appConfig}
@@ -95,6 +109,7 @@ export function App({ appConfig }: AppProps) {
95109
</RoomContext.Provider>
96110

97111
<Toaster />
98-
</>
112+
</div>
99113
);
100114
}
115+
export default EmbedAgentClient;

0 commit comments

Comments
 (0)