MCPcopy
hub / github.com/thesysdev/openui / Page

Function Page

examples/supabase-chat/src/app/page.tsx:14–86  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

12import { useEffect, useMemo, useState } from "react";
13
14export default function Page() {
15 // Incrementing this key remounts ChatProvider, which re-runs fetchThreadList.
16 // We bump it when a Realtime event signals that the thread list changed in
17 // another tab so the sidebar stays in sync without a full page reload.
18 const [threadListKey, setThreadListKey] = useState(0);
19
20 // Thread persistence stays server-backed (Supabase) via the same /api/threads
21 // REST contract the legacy `threadApiUrl` used — restStorage reproduces those
22 // conventions and keeps loadThread deserialization aligned with OpenAI format.
23 const storage = useMemo(
24 () => restStorage({ baseUrl: "/api/threads", messageFormat: openAIMessageFormat }),
25 [],
26 );
27 const llm = useMemo<ChatLLM>(
28 () => ({
29 send: ({ threadId, messages, signal }) =>
30 fetch("/api/chat", {
31 method: "POST",
32 headers: { "Content-Type": "application/json" },
33 body: JSON.stringify({
34 // Convert from OpenUI's internal format to OpenAI chat format
35 messages: openAIMessageFormat.toApi(messages),
36 threadId,
37 }),
38 signal,
39 }),
40 streamProtocol: openAIAdapter(),
41 }),
42 [],
43 );
44
45 useEffect(() => {
46 const supabase = createSupabaseBrowser();
47 let channel: RealtimeChannel | undefined;
48
49 const init = async () => {
50 // Ensure an anonymous session exists.
51 // Anonymous users get a stable UUID that persists across page refreshes
52 // and is used to scope threads via Row Level Security.
53 const {
54 data: { session },
55 } = await supabase.auth.getSession();
56 if (!session) {
57 await supabase.auth.signInAnonymously();
58 }
59
60 // Subscribe to Realtime changes on the threads table.
61 // This fires whenever any thread is created, updated, or deleted —
62 // including from another tab or device logged in with the same account.
63 channel = supabase
64 .channel("threads-realtime")
65 .on("postgres_changes", { event: "*", schema: "public", table: "threads" }, () => {
66 // Remount ChatProvider so the thread sidebar refreshes.
67 // Note: remounting clears the current in-progress conversation.
68 // For production, consider a more granular update strategy.
69 setThreadListKey((k) => k + 1);
70 })
71 .subscribe();

Callers

nothing calls this directly

Calls 5

createSupabaseBrowserFunction · 0.90
restStorageFunction · 0.85
openAIAdapterFunction · 0.85
initFunction · 0.85
toApiMethod · 0.80

Tested by

no test coverage detected