chore(studio + docs) improve project integrations (#45200)

## What kind of change does this PR introduce?

Docs update and UI copy improvement.

## What is the current behavior?

The GitHub integration working directory helper uses an inline tooltip
for examples. In the form layout, the tooltip alignment and inline code
wrapping can make the helper harder to scan.

The integration settings pages also mix markdown-rendered copy with JSX
copy, duplicate the integration cover image helper, and use slightly
different heading, spacing, and button copy patterns across GitHub,
Vercel, and AWS PrivateLink.

## What is the new behavior?

The GitHub working directory field now keeps the helper copy concise and
links to a dedicated docs section with examples for repository root and
nested `supabase/` directories.

The integration settings sections now use a more consistent JSX
structure and copy treatment across GitHub, Vercel, and AWS PrivateLink,
including shared cover imagery and matching explanatory section
hierarchy.

| Before | After |
| --- | --- |
| <img width="1838" height="696" alt="CleanShot 2026-04-24 at 14 35
32@2x"
src="https://github.com/user-attachments/assets/f9843018-fbf5-4c18-a0c3-1842b665f3fd"
/> | <img width="1842" height="700" alt="CleanShot 2026-04-24 at 14 30
21@2x-64E8726E-0B89-4C5A-8A47-CE1AA24F3D1A"
src="https://github.com/user-attachments/assets/bb017464-2b43-4dfe-94b8-a586aedea318"
/> |
| <img width="1884" height="1432" alt="CleanShot 2026-04-24 at 14 40
19@2x"
src="https://github.com/user-attachments/assets/b34e4573-cd7c-4588-83a0-0e1941019552"
/> | <img width="1844" height="1424" alt="CleanShot 2026-04-24 at 14 39
02@2x"
src="https://github.com/user-attachments/assets/4f82b01c-cb27-4f01-b2da-76b7f6e298a5"
/> |


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Clarified GitHub integration setup: provide a Working directory value,
how to compute it from the repo root (including "." for root), examples,
and updated “initialize” spelling.

* **Refactor**
* Simplified integration form descriptions (tooltips → inline text +
Learn more link).
* Reworked GitHub and Vercel integration content to use consistent
headings, layout, and shared image handling.
  * Reorganized integration settings rendering for clearer UI states.

* **Style**
  * Minor copy, casing, and button text/spacing adjustments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Danny White authored and GitHub committed 2026-04-24 15:41:59 +08:00
1 parent 8347877957
commit b37272cdd7
6 files changed
+268 -275

No files matched your search

@@ -13,13 +13,19 @@ In the Supabase Dashboard:
2. Under **GitHub Integration**, click **Authorize GitHub**.
3. You are redirected to a GitHub authorization page. Click **Authorize Supabase**.
4. You are redirected back to the Integrations page. Choose a GitHub repository to connect your project to.
5. Fill in the relative path to the Supabase directory from your repository root.
5. Set the **Working directory** field.
6. Configure the other options as needed to automate your GitHub connection.
7. Click **Enable integration**.
### Set the working directory
The working directory is the path from your repository root to the directory that contains the `supabase/` folder. Enter `.` when `supabase/` is at the repository root.
If `supabase/` is nested deeper in your repository, enter its parent directory instead. For example, if your layout is `apps/web/supabase/`, enter `apps/web`.
## Preparing your Git repository
You will be using the [Supabase CLI](/docs/guides/cli) to initialise your local `./supabase` directory:
You will be using the [Supabase CLI](/docs/guides/cli) to initialize your local `./supabase` directory:
<StepHikeCompact>
<StepHikeCompact.Step step={1}>
@@ -7,7 +7,7 @@ import { GenericSkeletonLoader } from 'ui-patterns'
import { IntegrationConnectionItem } from '../../Integrations/VercelGithub/IntegrationConnection'
import SidePanelVercelProjectLinker from './SidePanelVercelProjectLinker'
import { EmptyIntegrationConnection } from '@/components/interfaces/Integrations/VercelGithub/IntegrationPanels'
import { Markdown } from '@/components/interfaces/Markdown'
import { IntegrationImageHandler } from '@/components/interfaces/Settings/Integrations/IntegrationsSettings'
import { VercelSection } from '@/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection'
import {
ScaffoldContainer,
@@ -18,31 +18,124 @@ import {
ScaffoldSectionDetail,
ScaffoldTitle,
} from '@/components/layouts/Scaffold'
import { InlineLink } from '@/components/ui/InlineLink'
import NoPermission from '@/components/ui/NoPermission'
import { useGitHubAuthorizationQuery } from '@/data/integrations/github-authorization-query'
import { useGitHubConnectionDeleteMutation } from '@/data/integrations/github-connection-delete-mutation'
import { useGitHubConnectionsQuery } from '@/data/integrations/github-connections-query'
import {
useGitHubConnectionsQuery,
type GitHubConnection,
} from '@/data/integrations/github-connections-query'
import type { IntegrationProjectConnection } from '@/data/integrations/integrations.types'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import { BASE_PATH } from '@/lib/constants'
import {
GITHUB_INTEGRATION_INSTALLATION_URL,
GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL,
} from '@/lib/github'
import { useSidePanelsStateSnapshot } from '@/state/side-panels'
const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => {
return (
<img
className="border rounded-lg shadow w-full sm:w-48 mt-6 border-body"
src={`${BASE_PATH}/img/integrations/covers/${title}-cover.png`}
alt={`${title} cover`}
/>
)
type GitHubSectionProps = {
canCreateGitHubConnection: boolean
canReadGithubConnection: boolean
canUpdateGitHubConnection: boolean
connections?: GitHubConnection[]
isGitHubAuthorized: boolean
isLoadingPermissions: boolean
onAddGitHubConnection: () => void
onDeleteGitHubConnection: (connection: IntegrationProjectConnection) => void | Promise<void>
}
const GitHubSection = ({
canCreateGitHubConnection,
canReadGithubConnection,
canUpdateGitHubConnection,
connections,
isGitHubAuthorized,
isLoadingPermissions,
onAddGitHubConnection,
onDeleteGitHubConnection,
}: GitHubSectionProps) => (
<ScaffoldContainer>
<ScaffoldSection className="py-12">
<ScaffoldSectionDetail title="GitHub Connections">
<p>Connect any of your GitHub repositories to a project.</p>
<IntegrationImageHandler title="github" />
</ScaffoldSectionDetail>
<ScaffoldSectionContent>
{isLoadingPermissions ? (
<GenericSkeletonLoader />
) : !canReadGithubConnection ? (
<NoPermission resourceText="view this organization's GitHub connections" />
) : (
<div className="space-y-6">
<div className="space-y-1">
<h3 className="text-sm font-medium text-foreground">
How do GitHub connections work?
</h3>
<p className="text-sm text-foreground-light">
Connect a GitHub repository to a Supabase project. The GitHub app watches file,
branch, and pull request activity in your repository.
</p>
</div>
<div>
<ul className="flex flex-col gap-y-2">
{connections?.map((connection) => (
<IntegrationConnectionItem
key={connection.id}
disabled={!canUpdateGitHubConnection}
connection={{
id: String(connection.id),
added_by: {
id: String(connection.user?.id),
primary_email: connection.user?.primary_email ?? '',
username: connection.user?.username ?? '',
},
foreign_project_id: String(connection.repository.id),
supabase_project_ref: connection.project.ref,
organization_integration_id: 'unused',
inserted_at: connection.inserted_at,
updated_at: connection.updated_at,
metadata: {
name: connection.repository.name,
} as IntegrationProjectConnection['metadata'],
}}
type="GitHub"
onDeleteConnection={onDeleteGitHubConnection}
/>
))}
</ul>
<EmptyIntegrationConnection
onClick={onAddGitHubConnection}
showNode={false}
disabled={!canCreateGitHubConnection}
>
Add new project connection
</EmptyIntegrationConnection>
</div>
{isGitHubAuthorized && (
<p className="text-sm text-foreground-light">
You are authorized with the Supabase GitHub App. You can configure your{' '}
<InlineLink href={GITHUB_INTEGRATION_INSTALLATION_URL}>
GitHub App installations and repository access
</InlineLink>
, or{' '}
<InlineLink href={GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL}>
revoke your authorization
</InlineLink>
.
</p>
)}
</div>
)}
</ScaffoldSectionContent>
</ScaffoldSection>
</ScaffoldContainer>
)
export const IntegrationSettings = () => {
const router = useRouter()
const { data: org } = useSelectedOrganizationQuery()
@@ -69,11 +162,9 @@ export const IntegrationSettings = () => {
},
})
const sidePanelsStateSnapshot = useSidePanelsStateSnapshot()
const onAddGitHubConnection = useCallback(() => {
router.push('/project/_/settings/integrations')
}, [sidePanelsStateSnapshot])
}, [router])
const onDeleteGitHubConnection = useCallback(
async (connection: IntegrationProjectConnection) => {
@@ -90,99 +181,21 @@ export const IntegrationSettings = () => {
[deleteGitHubConnection, org?.id]
)
/**
* GitHub markdown content
*/
const GitHubTitle = `GitHub Connections`
const GitHubDetailsSection = `
Connect any of your GitHub repositories to a project.
`
const GitHubContentSectionTop = `
### How will GitHub connections work?
You will be able to connect a GitHub repository to a Supabase project.
The GitHub app will watch for changes in your repository such as file changes, branch changes as well as pull request activity.
`
const GitHubContentSectionBottom = gitHubAuthorization
? `You are authorized with Supabase GitHub App. You can configure your GitHub App installations and repository access [here](${GITHUB_INTEGRATION_INSTALLATION_URL}). You can revoke your authorization [here](${GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL}).`
: ''
const GitHubSection = () => (
<ScaffoldContainer>
<ScaffoldSection>
<ScaffoldSectionDetail title={GitHubTitle}>
<Markdown content={GitHubDetailsSection} />
<IntegrationImageHandler title="github" />
</ScaffoldSectionDetail>
<ScaffoldSectionContent>
{isLoadingPermissions ? (
<GenericSkeletonLoader />
) : !canReadGithubConnection ? (
<NoPermission resourceText="view this organization's GitHub connections" />
) : (
<>
<Markdown content={GitHubContentSectionTop} />
<ul className="flex flex-col gap-y-2">
{connections?.map((connection) => (
<IntegrationConnectionItem
key={connection.id}
disabled={!canUpdateGitHubConnection}
connection={{
id: String(connection.id),
added_by: {
id: String(connection.user?.id),
primary_email: connection.user?.primary_email ?? '',
username: connection.user?.username ?? '',
},
foreign_project_id: String(connection.repository.id),
supabase_project_ref: connection.project.ref,
organization_integration_id: 'unused',
inserted_at: connection.inserted_at,
updated_at: connection.updated_at,
metadata: {
name: connection.repository.name,
} as any,
}}
type="GitHub"
onDeleteConnection={onDeleteGitHubConnection}
/>
))}
</ul>
<EmptyIntegrationConnection
onClick={onAddGitHubConnection}
showNode={false}
disabled={!canCreateGitHubConnection}
>
Add new project connection
</EmptyIntegrationConnection>
{GitHubContentSectionBottom && (
<Markdown
extLinks
content={GitHubContentSectionBottom}
className="text-foreground-lighter"
/>
)}
</>
)}
</ScaffoldSectionContent>
</ScaffoldSection>
</ScaffoldContainer>
)
return (
<>
<ScaffoldContainerLegacy>
<ScaffoldTitle>Integrations</ScaffoldTitle>
</ScaffoldContainerLegacy>
<GitHubSection />
<GitHubSection
canCreateGitHubConnection={canCreateGitHubConnection}
canReadGithubConnection={canReadGithubConnection}
canUpdateGitHubConnection={canUpdateGitHubConnection}
connections={connections}
isGitHubAuthorized={Boolean(gitHubAuthorization)}
isLoadingPermissions={isLoadingPermissions}
onAddGitHubConnection={onAddGitHubConnection}
onDeleteGitHubConnection={onDeleteGitHubConnection}
/>
{showVercelIntegration && (
<>
<ScaffoldDivider />
@@ -15,6 +15,7 @@ import {
import { ResourceList } from '@/components/ui/Resource/ResourceList'
import { UpgradeToPro } from '@/components/ui/UpgradeToPro'
import { useAWSAccountDeleteMutation } from '@/data/aws-accounts/aws-account-delete-mutation'
import type { AWSAccount } from '@/data/aws-accounts/aws-accounts-query'
import { useAWSAccountsQuery } from '@/data/aws-accounts/aws-accounts-query'
import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
@@ -24,7 +25,7 @@ export const AWSPrivateLinkSection = () => {
const { data: project } = useSelectedProjectQuery()
const { data: accounts } = useAWSAccountsQuery({ projectRef: project?.ref })
const [selectedAccount, setSelectedAccount] = useState<any>(null)
const [selectedAccount, setSelectedAccount] = useState<AWSAccount>()
const [showForm, setShowForm] = useState(false)
const [showDeleteModal, setShowDeleteModal] = useState(false)
@@ -32,7 +33,7 @@ export const AWSPrivateLinkSection = () => {
onSuccess: () => {
toast.success('Account will be deleted shortly')
setShowDeleteModal(false)
setSelectedAccount(null)
setSelectedAccount(undefined)
},
})
@@ -40,16 +41,16 @@ export const AWSPrivateLinkSection = () => {
const promptPlanUpgrade = IS_PLATFORM && !hasPrivateLinkAccess
const onAddAccount = () => {
setSelectedAccount(null)
setSelectedAccount(undefined)
setShowForm(true)
}
const onEditAccount = (account: any) => {
const onEditAccount = (account: AWSAccount) => {
setSelectedAccount(account)
setShowForm(true)
}
const onDeleteAccount = (account: any) => {
const onDeleteAccount = (account: AWSAccount) => {
setSelectedAccount(account)
setShowDeleteModal(true)
}
@@ -70,31 +71,31 @@ export const AWSPrivateLinkSection = () => {
</ScaffoldSectionDetail>
<ScaffoldSectionContent>
<div className="space-y-6">
<div>
<h5 className="text-foreground mb-2">
How does the AWS PrivateLink integration work?
</h5>
<p className="text-foreground-light text-sm mb-6">
Connecting to AWS PrivateLink allows you to create a private connection between
your AWS VPC and your Supabase project.
</p>
<div className="space-y-4">
<div className="space-y-1">
<h3 className="text-sm font-medium text-foreground">
How does the AWS PrivateLink integration work?
</h3>
<p className="text-sm text-foreground-light">
Connecting to AWS PrivateLink allows you to create a private connection between
your AWS VPC and your Supabase project.
</p>
</div>
{promptPlanUpgrade && (
<div className="mb-6">
<UpgradeToPro
layout="vertical"
primaryText="Only available on Team or Enterprise Plan and above"
secondaryText="Connect your AWS VPC privately to your Supabase project using AWS PrivateLink."
buttonText="Upgrade to Team"
source="aws-privatelink-integration"
/>
</div>
<UpgradeToPro
layout="vertical"
primaryText="Only available on Team or Enterprise Plan and above"
secondaryText="Connect your AWS VPC privately to your Supabase project using AWS PrivateLink."
buttonText="Upgrade to Team"
source="aws-privatelink-integration"
/>
)}
</div>
<div className={cn(promptPlanUpgrade && 'opacity-25 pointer-events-none')}>
<div className="flex items-center justify-between mb-3">
<h3 className="text-foreground text-sm">AWS Accounts</h3>
<Button type={promptPlanUpgrade ? 'default' : 'primary'} onClick={onAddAccount}>
Add Account
<h3 className="text-sm font-medium text-foreground">AWS Accounts</h3>
<Button type="default" onClick={onAddAccount}>
Add account
</Button>
</div>
{(accounts?.length ?? 0) > 0 ? (
@@ -30,7 +30,6 @@ import {
import { Admonition } from 'ui-patterns/admonition'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { InfoTooltip } from 'ui-patterns/info-tooltip'
import * as z from 'zod'
import { InlineLink } from '@/components/ui/InlineLink'
@@ -461,7 +460,7 @@ export const GitHubIntegrationConnectionForm = ({
render={({ field }) => (
<FormItemLayout
layout="flex-row-reverse"
label="GitHub Repository"
label="GitHub repository"
description={
connection
? 'Change the connected repository'
@@ -489,7 +488,7 @@ export const GitHubIntegrationConnectionForm = ({
>
{selectedRepository || connection
? selectedRepository?.name || connection?.repository.name
: 'Choose GitHub Repository'}
: 'Choose GitHub repository'}
</Button>
</FormControl_Shadcn_>
</PopoverTrigger_Shadcn_>
@@ -584,29 +583,16 @@ export const GitHubIntegrationConnectionForm = ({
layout="flex-row-reverse"
label="Working directory"
description={
<span>
Relative path to the directory that contains your{' '}
<code className="text-code-inline !break-keep">supabase</code> folder{' '}
<span className="inline-flex align-middle [&>button]:ml-1 [&>button]:-translate-y-[2px]">
<InfoTooltip side="bottom" className="w-72">
<p>Examples:</p>
<ul className="list-disc pl-4 space-y-1">
<li>
<code className="text-code-inline">.</code> if repository root
contains <code className="text-code-inline">supabase/</code>
</li>
<li>
<code className="text-code-inline">apps/web</code> if{' '}
<code className="text-code-inline">supabase/</code> is nested
at{' '}
<code className="text-code-inline !break-keep">
apps/web/supabase/
</code>
</li>
</ul>
</InfoTooltip>
</span>
</span>
<>
Relative path to the directory containing your{' '}
<code className="text-code-inline whitespace-nowrap">supabase/</code>{' '}
folder.{' '}
<InlineLink
href={`${DOCS_URL}/guides/deployment/branching/github-integration#set-the-working-directory`}
>
Learn more
</InlineLink>
</>
}
>
<FormControl_Shadcn_>
@@ -1,8 +1,9 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { IS_PLATFORM, useParams } from 'common'
import { useParams } from 'common'
import { useMemo } from 'react'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
import { IntegrationImageHandler } from '../IntegrationsSettings'
import { GitHubIntegrationConnectionForm } from './GitHubIntegrationConnectionForm'
import {
ScaffoldContainer,
@@ -14,17 +15,6 @@ import NoPermission from '@/components/ui/NoPermission'
import { useGitHubConnectionsQuery } from '@/data/integrations/github-connections-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import { BASE_PATH } from '@/lib/constants'
const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => {
return (
<img
className="border rounded-lg shadow w-full sm:w-48 mt-6 border-body"
src={`${BASE_PATH}/img/integrations/covers/${title}-cover.png`}
alt={`${title} cover`}
/>
)
}
export const GitHubSection = () => {
const { ref: projectRef } = useParams()
@@ -59,13 +49,19 @@ export const GitHubSection = () => {
<NoPermission resourceText="view this organization's GitHub connections" />
) : (
<div className="space-y-6">
<h5 className="text-foreground mb-2">How does the GitHub integration work?</h5>
<p className="text-foreground-light text-sm mb-6">
Connecting to GitHub allows you to sync preview branches with a chosen GitHub
branch, keep your production branch in sync, and automatically create preview
branches for every pull request.
</p>
<GitHubIntegrationConnectionForm connection={existingConnection} />
<div className="space-y-1">
<h3 className="text-sm font-medium text-foreground">
How does the GitHub integration work?
</h3>
<p className="text-sm text-foreground-light">
Connecting to GitHub allows you to sync preview branches with a chosen GitHub
branch, keep your production branch in sync, and automatically create preview
branches for every pull request.
</p>
</div>
<div>
<GitHubIntegrationConnectionForm connection={existingConnection} />
</div>
</div>
)}
</ScaffoldSectionContent>
@@ -14,13 +14,13 @@ import {
IntegrationConnectionHeader,
IntegrationInstallation,
} from '@/components/interfaces/Integrations/VercelGithub/IntegrationPanels'
import { Markdown } from '@/components/interfaces/Markdown'
import {
ScaffoldContainer,
ScaffoldSection,
ScaffoldSectionContent,
ScaffoldSectionDetail,
} from '@/components/layouts/Scaffold'
import { InlineLink } from '@/components/ui/InlineLink'
import NoPermission from '@/components/ui/NoPermission'
import { useOrgIntegrationsQuery } from '@/data/integrations/integrations-query-org-only'
import { useIntegrationsVercelInstalledConnectionDeleteMutation } from '@/data/integrations/integrations-vercel-installed-connection-delete-mutation'
@@ -119,31 +119,8 @@ export const VercelSection = ({ isProjectScoped }: { isProjectScoped: boolean })
[deleteVercelConnection, org?.slug]
)
// Markdown Content
const VercelTitle = `Vercel Integration`
const VercelDetailsSection = `
Connect your Vercel teams to your Supabase organization.
`
const VercelContentSectionTop = `
### How does the Vercel integration work?
Supabase will keep your environment variables up to date in each of the projects you assign to a Supabase project.
You can also link multiple Vercel Projects to the same Supabase project.
`
const VercelContentSectionBottom =
vercelProjectCount > 0 && vercelIntegration !== undefined
? `
Your Vercel connection has access to ${vercelProjectCount} Vercel Projects.
You can change the scope of the access for Supabase by configuring
[here](${getIntegrationConfigurationUrl(vercelIntegration)}).
`
: ''
const integrationUrl =
process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod'
? 'https://vercel.com/integrations/supabase'
@@ -167,7 +144,7 @@ You can change the scope of the access for Supabase by configuring
<ScaffoldContainer>
<ScaffoldSection className="py-12">
<ScaffoldSectionDetail title={VercelTitle}>
<Markdown content={VercelDetailsSection} />
<p>Connect your Vercel teams to your Supabase organization.</p>
<IntegrationImageHandler title="vercel" />
</ScaffoldSectionDetail>
<ScaffoldSectionContent>
@@ -176,87 +153,101 @@ You can change the scope of the access for Supabase by configuring
) : !canReadVercelConnection ? (
<NoPermission resourceText="view this organization's Vercel connections" />
) : (
<>
<Markdown content={VercelContentSectionTop} />
{vercelIntegration ? (
<div key={vercelIntegration.id}>
<IntegrationInstallation title={'Vercel'} integration={vercelIntegration} />
{connections.length > 0 ? (
<>
<div className="space-y-6">
<div className="space-y-1">
<h3 className="text-sm font-medium text-foreground">
How does the Vercel integration work?
</h3>
<p className="text-sm text-foreground-light">
Supabase will keep your environment variables up to date in each of the projects
you assign to a Supabase project. You can also link multiple Vercel projects to
the same Supabase project.
</p>
</div>
<div>
{vercelIntegration ? (
<div key={vercelIntegration.id}>
<IntegrationInstallation title={'Vercel'} integration={vercelIntegration} />
{connections.length > 0 ? (
<>
<IntegrationConnectionHeader
title={ConnectionHeaderTitle}
markdown={`Repository connections for Vercel`}
/>
<ul className="flex flex-col">
{connections.map((connection) => (
<div
key={connection.id}
className={cn(
isProjectScoped && 'relative flex flex-col -gap-[1px] [&>li]:pb-0'
)}
>
<IntegrationConnectionItem
connection={connection}
disabled={isBranch || !canUpdateVercelConnection}
type={'Vercel' as IntegrationName}
onDeleteConnection={onDeleteVercelConnection}
className={cn(isProjectScoped && '!rounded-b-none !mb-0')}
/>
{isProjectScoped ? (
<div className="relative pl-8 ml-6 border-l border-muted pb-6">
<div className="border-b border-l border-r rounded-b-lg">
<VercelIntegrationConnectionForm
connection={connection}
integration={vercelIntegration}
disabled={isBranch || !canUpdateVercelConnection}
/>
</div>
</div>
) : null}
</div>
))}
</ul>
</>
) : (
<IntegrationConnectionHeader
title={ConnectionHeaderTitle}
className="pb-0"
markdown={`Repository connections for Vercel`}
/>
<ul className="flex flex-col">
{connections.map((connection) => (
<div
key={connection.id}
className={cn(
isProjectScoped && 'relative flex flex-col -gap-[1px] [&>li]:pb-0'
)}
>
<IntegrationConnectionItem
connection={connection}
disabled={isBranch || !canUpdateVercelConnection}
type={'Vercel' as IntegrationName}
onDeleteConnection={onDeleteVercelConnection}
className={cn(isProjectScoped && '!rounded-b-none !mb-0')}
/>
{isProjectScoped ? (
<div className="relative pl-8 ml-6 border-l border-muted pb-6">
<div className="border-b border-l border-r rounded-b-lg">
<VercelIntegrationConnectionForm
connection={connection}
integration={vercelIntegration}
disabled={isBranch || !canUpdateVercelConnection}
/>
</div>
</div>
) : null}
</div>
))}
</ul>
</>
) : (
<IntegrationConnectionHeader
title={ConnectionHeaderTitle}
className="pb-0"
markdown={`Repository connections for Vercel`}
/>
)}
<EmptyIntegrationConnection
disabled={isBranch || !canCreateVercelConnection}
onClick={() => onAddVercelConnection(vercelIntegration.id)}
>
Add new project connection
</EmptyIntegrationConnection>
</div>
) : (
<div>
<Button
icon={<ExternalLink />}
asChild={!isBranch}
type="default"
disabled={isBranch}
>
{isBranch ? (
<p>Install Vercel Integration</p>
) : (
<Link href={integrationUrl} target="_blank" rel="noreferrer">
Install Vercel Integration
</Link>
)}
</Button>
</div>
<EmptyIntegrationConnection
disabled={isBranch || !canCreateVercelConnection}
onClick={() => onAddVercelConnection(vercelIntegration.id)}
>
Add new project connection
</EmptyIntegrationConnection>
</div>
) : (
<div>
<Button
icon={<ExternalLink />}
asChild={!isBranch}
type="default"
disabled={isBranch}
>
{isBranch ? (
<p>Install Vercel Integration</p>
) : (
<Link href={integrationUrl} target="_blank" rel="noreferrer">
Install Vercel Integration
</Link>
)}
</Button>
</div>
)}
</div>
{vercelProjectCount > 0 && vercelIntegration !== undefined && (
<p className="text-sm text-foreground-light">
Your Vercel connection can access {vercelProjectCount} Vercel projects. To change
which projects Supabase may use, open your organization’s{' '}
<InlineLink href={getIntegrationConfigurationUrl(vercelIntegration)}>
Vercel integration settings
</InlineLink>
.
</p>
)}
{VercelContentSectionBottom && (
<Markdown
extLinks
content={VercelContentSectionBottom}
className="text-foreground-lighter"
/>
)}
</>
</div>
)}
</ScaffoldSectionContent>
</ScaffoldSection>