Connect() — supabase Function Reference
Architecture documentation for the Connect() function in Connect.tsx from the supabase codebase.
Entity Profile
Dependency Diagram
graph TD 7a580dbf_0dd5_87fe_b7f0_afad9b0cdd6f["Connect()"] 5d5315d4_34ce_e96b_4aa1_ea6d63eea71d["getContentFilePath()"] 7a580dbf_0dd5_87fe_b7f0_afad9b0cdd6f -->|calls| 5d5315d4_34ce_e96b_4aa1_ea6d63eea71d 8f857c80_b8a5_cc93_9656_f0b4af5b7195["inferConnectTabFromParentKey()"] 7a580dbf_0dd5_87fe_b7f0_afad9b0cdd6f -->|calls| 8f857c80_b8a5_cc93_9656_f0b4af5b7195 style 7a580dbf_0dd5_87fe_b7f0_afad9b0cdd6f fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
apps/studio/components/interfaces/Connect/Connect.tsx lines 39–501
export const Connect = () => {
const router = useRouter()
const { ref: projectRef } = useParams()
const {
projectConnectionShowAppFrameworks: showAppFrameworks,
projectConnectionShowMobileFrameworks: showMobileFrameworks,
projectConnectionShowOrms: showOrms,
} = useIsFeatureEnabled([
'project_connection:show_app_frameworks',
'project_connection:show_mobile_frameworks',
'project_connection:show_orms',
])
const connectionTypes = CONNECTION_TYPES.filter(({ key }) => {
if (key === 'frameworks') {
return showAppFrameworks
}
if (key === 'mobiles') {
return showMobileFrameworks
}
if (key === 'orms') {
return showOrms
}
return true
})
// helper to get the connection type object
function getConnectionObjectForTab(tab: string | null) {
switch (tab) {
case 'frameworks':
return FRAMEWORKS
case 'mobiles':
return MOBILES
case 'orms':
return ORMS
default:
return FRAMEWORKS
}
}
const [open, setOpen] = useQueryState('showConnect', parseAsBoolean.withDefault(false))
const [tab, setTab] = useQueryState('connectTab', parseAsString.withDefault('direct'))
const [queryFramework, setQueryFramework] = useQueryState('framework', parseAsString)
const [queryUsing, setQueryUsing] = useQueryState('using', parseAsString)
const [queryWith, setQueryWith] = useQueryState('with', parseAsString)
const [_, setQueryType] = useQueryState('type', parseAsString)
const [__, setQuerySource] = useQueryState('source', parseAsString)
const [___, setQueryMethod] = useQueryState('method', parseAsString)
const [connectionObject, setConnectionObject] = useState<ConnectionType[]>(FRAMEWORKS)
const [selectedParent, setSelectedParent] = useState(connectionObject[0].key) // aka nextjs
const [selectedChild, setSelectedChild] = useState(
connectionObject.find((item) => item.key === selectedParent)?.children[0]?.key ?? ''
)
const [selectedGrandchild, setSelectedGrandchild] = useState(
connectionObject
.find((item) => item.key === selectedParent)
?.children.find((child) => child.key === selectedChild)?.children[0]?.key || ''
)
const { data: settings } = useProjectSettingsV2Query({ projectRef }, { enabled: open })
const { can: canReadAPIKeys } = useAsyncCheckPermissions(
PermissionAction.READ,
'service_api_keys'
)
const handleParentChange = (value: string) => {
setSelectedParent(value)
setQueryFramework(value)
const parent = connectionObject.find((item) => item.key === value)
const firstChild = parent?.children?.[0]
if (firstChild) {
setSelectedChild(firstChild.key)
setQueryUsing(firstChild.key)
const firstGrandchild = firstChild.children?.[0]
if (firstGrandchild) {
setSelectedGrandchild(firstGrandchild.key)
setQueryWith(firstGrandchild.key)
} else {
setSelectedGrandchild('')
setQueryWith(null)
}
} else {
setSelectedChild('')
setQueryUsing(null)
setSelectedGrandchild('')
setQueryWith(null)
}
}
const handleChildChange = (value: string) => {
setSelectedChild(value)
setQueryUsing(value)
const parent = connectionObject.find((item) => item.key === selectedParent)
const child = parent?.children.find((child) => child.key === value)
const firstGrandchild = child?.children?.[0]
if (firstGrandchild) {
setSelectedGrandchild(firstGrandchild.key)
setQueryWith(firstGrandchild.key)
} else {
setSelectedGrandchild('')
setQueryWith(null)
}
}
const handleGrandchildChange = (value: string) => {
setSelectedGrandchild(value)
if (value) {
setQueryWith(value)
} else {
setQueryWith(null)
}
}
// reset the parent/child/grandchild when the connection type (tab) changes
function handleConnectionTypeChange(connections: ConnectionType[]) {
setSelectedParent(connections[0].key)
if (connections[0]?.children.length > 0) {
setSelectedChild(connections[0].children[0].key)
if (connections[0].children[0]?.children.length > 0) {
setSelectedGrandchild(connections[0].children[0].children[0].key)
} else {
setSelectedGrandchild('')
}
} else {
setSelectedChild('')
setSelectedGrandchild('')
}
}
function handleConnectionType(type: string) {
setTab(type)
if (type === 'frameworks') {
setConnectionObject(FRAMEWORKS)
handleConnectionTypeChange(FRAMEWORKS)
}
if (type === 'mobiles') {
setConnectionObject(MOBILES)
handleConnectionTypeChange(MOBILES)
}
if (type === 'orms') {
setConnectionObject(ORMS)
handleConnectionTypeChange(ORMS)
}
}
const getChildOptions = () => {
const parent = connectionObject.find((item) => item.key === selectedParent)
if (parent && parent.children.length > 0) {
return parent.children
}
return []
}
const getGrandchildrenOptions = () => {
const parent = connectionObject.find((item) => item.key === selectedParent)
const subCategory = parent?.children.find((child) => child.key === selectedChild)
if (subCategory && subCategory.children.length > 0) {
return subCategory.children
}
return []
}
const { data: apiKeys } = useAPIKeysQuery({ projectRef }, { enabled: canReadAPIKeys })
const { anonKey, publishableKey } = canReadAPIKeys
? getKeys(apiKeys)
: { anonKey: null, publishableKey: null }
const projectKeys = useMemo(() => {
const protocol = settings?.app_config?.protocol ?? 'https'
const endpoint = settings?.app_config?.endpoint ?? ''
const apiHost = canReadAPIKeys ? `${protocol}://${endpoint ?? '-'}` : ''
return {
apiUrl: apiHost ?? null,
anonKey: anonKey?.api_key ?? null,
publishableKey: publishableKey?.api_key ?? null,
}
}, [
settings?.app_config?.protocol,
settings?.app_config?.endpoint,
canReadAPIKeys,
anonKey?.api_key,
publishableKey?.api_key,
])
const filePath = getContentFilePath({
connectionObject,
selectedParent,
selectedChild,
selectedGrandchild,
})
const resetQueryStates = () => {
setQueryFramework(null)
setQueryUsing(null)
setQueryWith(null)
setQueryType(null)
setQuerySource(null)
setQueryMethod(null)
}
const handleDialogChange = (dialogOpen: boolean) => {
if (!dialogOpen) {
setTab(null)
resetQueryStates()
}
setOpen(dialogOpen)
}
useEffect(() => {
if (!open) return
const noConnectTabInUrl = typeof router.query.connectTab === 'undefined'
const hasQuery = queryFramework || queryUsing || queryWith
const inferred = inferConnectTabFromParentKey(queryFramework)
if (noConnectTabInUrl && hasQuery && inferred) {
setTab(inferred)
if (inferred === 'frameworks') setConnectionObject(FRAMEWORKS)
if (inferred === 'mobiles') setConnectionObject(MOBILES)
if (inferred === 'orms') setConnectionObject(ORMS)
}
}, [open, router.query.connectTab, queryFramework, queryUsing, queryWith, setTab])
useEffect(() => {
if (!open) return
const newConnectionObject = getConnectionObjectForTab(tab)
setConnectionObject(newConnectionObject)
const parent =
newConnectionObject.find((item) => item.key === queryFramework) ?? newConnectionObject[0]
setSelectedParent(parent?.key ?? '')
if (queryFramework) {
if (parent?.key !== queryFramework) setQueryFramework(parent?.key ?? null)
}
const child =
parent?.children.find((child) => child.key === queryUsing) ?? parent?.children?.[0]
setSelectedChild(child?.key ?? '')
if (queryUsing) {
if (child?.key !== queryUsing) setQueryUsing(child?.key ?? null)
}
const grandchild =
child?.children.find((child) => child.key === queryWith) ?? child?.children?.[0]
setSelectedGrandchild(grandchild?.key ?? '')
if (queryWith) {
if (grandchild?.key !== queryWith) setQueryWith(grandchild?.key ?? null)
}
}, [
open,
tab,
queryFramework,
setQueryFramework,
queryUsing,
setQueryUsing,
queryWith,
setQueryWith,
])
return (
<Dialog open={open} onOpenChange={handleDialogChange}>
<DialogContent className={cn('sm:max-w-5xl p-0 rounded-lg')} centered={false}>
<DialogHeader className={cn('text-left', DIALOG_PADDING_X)}>
<DialogTitle>
Connect to your project
{connectionTypes.length === 1 ? ` via ${connectionTypes[0].label.toLowerCase()}` : null}
</DialogTitle>
<DialogDescription>
Get the connection strings and environment variables for your app.
</DialogDescription>
</DialogHeader>
<Tabs_Shadcn_
value={tab}
onValueChange={(value) => {
resetQueryStates()
handleConnectionType(value)
}}
>
{connectionTypes.length > 1 ? (
<TabsList_Shadcn_ className={cn('flex overflow-x-scroll gap-x-4', DIALOG_PADDING_X)}>
{connectionTypes.map((type) => (
<TabsTrigger_Shadcn_ key={type.key} value={type.key} className="px-0">
{type.label}
</TabsTrigger_Shadcn_>
))}
</TabsList_Shadcn_>
) : (
<DialogSectionSeparator />
)}
{connectionTypes.map((type) => {
const hasChildOptions =
(connectionObject.find((parent) => parent.key === selectedParent)?.children.length ||
0) > 0
const hasGrandChildOptions =
(connectionObject
.find((parent) => parent.key === selectedParent)
?.children.find((child) => child.key === selectedChild)?.children.length || 0) > 0
if (type.key === 'direct') {
return (
<TabsContent_Shadcn_
key="direct"
value="direct"
className={cn('!mt-0', 'p-0', 'flex flex-col gap-6')}
>
<div className={DIALOG_PADDING_Y}>
<DatabaseConnectionString />
</div>
</TabsContent_Shadcn_>
)
}
if (type.key === 'mcp') {
return (
<TabsContent_Shadcn_
key="mcp"
value="mcp"
className={cn(DIALOG_PADDING_X, DIALOG_PADDING_Y, '!mt-0')}
>
<McpTabContent projectKeys={projectKeys} />
</TabsContent_Shadcn_>
)
}
if (type.key === 'api-keys') {
return (
<TabsContent_Shadcn_
key="api-keys"
value="api-keys"
className={cn(DIALOG_PADDING_X, DIALOG_PADDING_Y, '!mt-0')}
>
<ApiKeysTabContent projectKeys={projectKeys} />
</TabsContent_Shadcn_>
)
}
const connectionTabMap: Record<
string,
'App Frameworks' | 'Mobile Frameworks' | 'ORMs'
> = {
frameworks: 'App Frameworks',
mobiles: 'Mobile Frameworks',
orms: 'ORMs',
}
const connectionTab = connectionTabMap[type.key] || 'App Frameworks'
const selectedFrameworkOrTool =
connectionObject.find((item) => item.key === selectedParent)?.label || ''
return (
<TabsContent_Shadcn_
key={`content-${type.key}`}
value={type.key}
className={cn(DIALOG_PADDING_X, DIALOG_PADDING_Y, '!mt-0')}
>
<div className="flex flex-col md:flex-row gap-2 justify-between">
<div className="flex flex-col md:flex-row items-stretch md:items-center gap-2 md:gap-3">
<ConnectDropdown
state={selectedParent}
updateState={handleParentChange}
label={
connectionObject === FRAMEWORKS || connectionObject === MOBILES
? 'Framework'
: 'Tool'
}
items={connectionObject}
/>
{selectedParent && hasChildOptions && (
<ConnectDropdown
state={selectedChild}
updateState={handleChildChange}
label="Using"
items={getChildOptions()}
/>
)}
{selectedChild && hasGrandChildOptions && (
<ConnectDropdown
state={selectedGrandchild}
updateState={handleGrandchildChange}
label="With"
items={getGrandchildrenOptions()}
/>
)}
</div>
{connectionObject.find((item) => item.key === selectedParent)?.guideLink && (
<Button asChild type="default" icon={<ExternalLink strokeWidth={1.5} />}>
<a
target="_blank"
rel="noreferrer"
href={
connectionObject.find((item) => item.key === selectedParent)?.guideLink ||
''
}
>
{connectionObject.find((item) => item.key === selectedParent)?.label} guide
</a>
</Button>
)}
</div>
<p className="text-xs text-foreground-lighter my-3">
Add the following files below to your application
</p>
<ConnectTabContent
projectKeys={projectKeys}
filePath={filePath}
connectionTab={connectionTab}
selectedFrameworkOrTool={selectedFrameworkOrTool}
className="rounded-b-none"
/>
{IS_PLATFORM && (
<Panel.Notice
className="border border-t-0 rounded-lg rounded-t-none"
badgeLabel="Changelog"
title="New publishable and secret API keys"
description={
<>
<p>
View your publishable and secret API keys from the project{' '}
<Link href={`/project/${projectRef}/settings/api-keys`}>
API settings page
</Link>
</p>
<p>
To learn more about the new API keys, read the{' '}
<a
href="https://supabase.com/docs/guides/api/api-keys"
target="_blank"
rel="noreferrer"
>
documentation
</a>
</p>
</>
}
href={`${BASE_PATH}/project/${projectRef}/settings/api-keys`}
buttonText="View API keys"
/>
)}
</TabsContent_Shadcn_>
)
})}
</Tabs_Shadcn_>
</DialogContent>
</Dialog>
)
}
Domain
Subdomains
Source
Frequently Asked Questions
What does Connect() do?
Connect() is a function in the supabase codebase.
What does Connect() call?
Connect() calls 2 function(s): getContentFilePath, inferConnectTabFromParentKey.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free