Supabase storage
Use a private Supabase bucket for user-namespaced attachments and short-lived signed URLs.
createSupabaseStorage() returns a user-bound StorageAdapterFactory.
import { createSupabaseStorage }
from '@mordn/chat-widget/server/supabase';
NEXT_PUBLIC_SUPABASE_URL="https://your-project.supabase.co"
SUPABASE_SERVICE_ROLE_KEY="..."
createChatHandler({
getUserId: getChatUserId,
model,
store,
storage: createSupabaseStorage(),
});
supabaseUrlstringDefault:
NEXT_PUBLIC_SUPABASE_URLProject URL.
serviceRoleKeystringDefault:
SUPABASE_SERVICE_ROLE_KEYServer-only service key.
bucketstringDefault:
chat-attachmentsPrivate bucket name.
signedUrlTtlSecondsnumberDefault:
3600Signed URL lifetime.
Objects use a bound-user namespace and random path segment. The adapter never
calls getPublicUrl; history reload creates fresh signed URLs.
Omitting storage disables uploads and the upload route returns 503. The
widget’s features.fileUpload flag should therefore be enabled only when a
storage adapter is mounted.