@@ -44,7 +44,7 @@ import {
4444} from "~/v3/vercel/vercelProjectIntegrationSchema" ;
4545import { type VercelCustomEnvironment } from "~/models/vercelIntegration.server" ;
4646import { type VercelOnboardingData } from "~/presenters/v3/VercelSettingsPresenter.server" ;
47- import { vercelAppInstallPath , v3ProjectSettingsPath , githubAppInstallPath , vercelResourcePath } from "~/utils/pathBuilder" ;
47+ import { vercelAppInstallPath , v3ProjectSettingsIntegrationsPath , githubAppInstallPath , vercelResourcePath } from "~/utils/pathBuilder" ;
4848import type { loader } from "~/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel" ;
4949import { useEffect , useState , useCallback , useRef } from "react" ;
5050import { usePostHogTracking } from "~/hooks/usePostHog" ;
@@ -102,6 +102,7 @@ export function VercelOnboardingModal({
102102 hasOrgIntegration,
103103 nextUrl,
104104 onDataReload,
105+ vercelManageAccessUrl,
105106} : {
106107 isOpen : boolean ;
107108 onClose : ( ) => void ;
@@ -114,6 +115,7 @@ export function VercelOnboardingModal({
114115 hasOrgIntegration : boolean ;
115116 nextUrl ?: string ;
116117 onDataReload ?: ( vercelStagingEnvironment ?: string ) => void ;
118+ vercelManageAccessUrl ?: string ;
117119} ) {
118120 const { capture, startSessionRecording } = usePostHogTracking ( ) ;
119121 const navigation = useNavigation ( ) ;
@@ -122,7 +124,8 @@ export function VercelOnboardingModal({
122124 const completeOnboardingFetcher = useFetcher ( ) ;
123125 const { Form : CompleteOnboardingForm } = completeOnboardingFetcher ;
124126 const [ searchParams ] = useSearchParams ( ) ;
125- const fromMarketplaceContext = searchParams . get ( "origin" ) === "marketplace" ;
127+ const origin = searchParams . get ( "origin" ) ;
128+ const fromMarketplaceContext = origin === "marketplace" ;
126129
127130 const availableProjects = onboardingData ?. availableProjects || [ ] ;
128131 const hasProjectSelected = onboardingData ?. hasProjectSelected ?? false ;
@@ -543,8 +546,15 @@ export function VercelOnboardingModal({
543546
544547 if ( ! isGitHubConnectedForOnboarding ) {
545548 setState ( "github-connection" ) ;
549+ capture ( "vercel onboarding github step viewed" , {
550+ origin : fromMarketplaceContext ? "marketplace" : "dashboard" ,
551+ step : "github-connection" ,
552+ organization_slug : organizationSlug ,
553+ project_slug : projectSlug ,
554+ github_app_installed : gitHubAppInstallations . length > 0 ,
555+ } ) ;
546556 }
547- } , [ vercelStagingEnvironment , pullEnvVarsBeforeBuild , atomicBuilds , discoverEnvVars , syncEnvVarsMapping , nextUrl , fromMarketplaceContext , isGitHubConnectedForOnboarding , completeOnboardingFetcher , actionUrl , trackOnboarding ] ) ;
557+ } , [ vercelStagingEnvironment , pullEnvVarsBeforeBuild , atomicBuilds , discoverEnvVars , syncEnvVarsMapping , nextUrl , fromMarketplaceContext , isGitHubConnectedForOnboarding , completeOnboardingFetcher , actionUrl , trackOnboarding , capture , organizationSlug , projectSlug , gitHubAppInstallations . length ] ) ;
548558
549559 const handleFinishOnboarding = useCallback ( ( e : React . FormEvent < HTMLFormElement > ) => {
550560 e . preventDefault ( ) ;
@@ -639,7 +649,7 @@ export function VercelOnboardingModal({
639649 onClose ( ) ;
640650 }
641651 } } >
642- < DialogContent className = "max-w-lg" >
652+ < DialogContent className = "max-w-lg" onInteractOutside = { ( e ) => e . preventDefault ( ) } >
643653 < DialogHeader >
644654 < div className = "flex items-center gap-2" >
645655 < VercelLogo className = "size-5" />
@@ -727,14 +737,25 @@ export function VercelOnboardingModal({
727737
728738 < FormButtons
729739 confirmButton = {
730- < Button
731- variant = "primary/medium"
732- onClick = { handleProjectSelection }
733- disabled = { ! selectedVercelProject || fetcher . state !== "idle" }
734- LeadingIcon = { fetcher . state !== "idle" ? SpinnerWhite : undefined }
735- >
736- { fetcher . state !== "idle" ? "Connecting..." : "Connect Project" }
737- </ Button >
740+ < div className = "flex items-center gap-2" >
741+ { vercelManageAccessUrl && ! origin && (
742+ < LinkButton
743+ to = { vercelManageAccessUrl }
744+ variant = "tertiary/medium"
745+ target = "_self"
746+ >
747+ Manage access
748+ </ LinkButton >
749+ ) }
750+ < Button
751+ variant = "primary/medium"
752+ onClick = { handleProjectSelection }
753+ disabled = { ! selectedVercelProject || fetcher . state !== "idle" }
754+ LeadingIcon = { fetcher . state !== "idle" ? SpinnerWhite : undefined }
755+ >
756+ { fetcher . state !== "idle" ? "Connecting..." : "Connect Project" }
757+ </ Button >
758+ </ div >
738759 }
739760 cancelButton = {
740761 < Button
@@ -813,6 +834,7 @@ export function VercelOnboardingModal({
813834 < Header3 > Pull Environment Variables</ Header3 >
814835 < Paragraph className = "text-sm" >
815836 Select which environment variables to pull from Vercel now. This is a one-time pull.
837+ Later on environment variables can be pulled before each build.
816838 </ Paragraph >
817839
818840 < div className = "flex gap-4 text-sm" >
@@ -1057,7 +1079,7 @@ export function VercelOnboardingModal({
10571079 </ Callout >
10581080
10591081 { ( ( ) => {
1060- const baseSettingsPath = v3ProjectSettingsPath (
1082+ const baseSettingsPath = v3ProjectSettingsIntegrationsPath (
10611083 { slug : organizationSlug } ,
10621084 { slug : projectSlug } ,
10631085 { slug : environmentSlug }
@@ -1081,6 +1103,7 @@ export function VercelOnboardingModal({
10811103 ) }
10821104 variant = "secondary/medium"
10831105 LeadingIcon = { OctoKitty }
1106+ onClick = { ( ) => trackOnboarding ( "vercel onboarding github app install clicked" ) }
10841107 >
10851108 Install GitHub app
10861109 </ LinkButton >
@@ -1110,6 +1133,7 @@ export function VercelOnboardingModal({
11101133 < Button
11111134 variant = "primary/medium"
11121135 onClick = { ( ) => {
1136+ trackOnboarding ( "vercel onboarding github completed" ) ;
11131137 setState ( "completed" ) ;
11141138 const validUrl = safeRedirectUrl ( nextUrl ) ;
11151139 if ( validUrl ) {
@@ -1123,6 +1147,7 @@ export function VercelOnboardingModal({
11231147 < Button
11241148 variant = "tertiary/medium"
11251149 onClick = { ( ) => {
1150+ trackOnboarding ( "vercel onboarding github skipped" ) ;
11261151 setState ( "completed" ) ;
11271152 if ( fromMarketplaceContext && nextUrl ) {
11281153 const validUrl = safeRedirectUrl ( nextUrl ) ;
@@ -1141,6 +1166,7 @@ export function VercelOnboardingModal({
11411166 < Button
11421167 variant = "tertiary/medium"
11431168 onClick = { ( ) => {
1169+ trackOnboarding ( "vercel onboarding github skipped" ) ;
11441170 setState ( "completed" ) ;
11451171 } }
11461172 >
0 commit comments