@@ -17,15 +17,19 @@ import { SSOLoginForm } from "./login/SSOLoginForm";
1717import { useAuthProviderDescriptions } from "./data/auth-providers/auth-provider-descriptions-query" ;
1818import { SetupPending } from "./login/SetupPending" ;
1919import { useNeedsSetup } from "./dedicated-setup/use-needs-setup" ;
20+ import { useInstallationConfiguration } from "./data/installation/installation-config-query" ;
2021import { AuthProviderDescription } from "@gitpod/public-api/lib/gitpod/v1/authprovider_pb" ;
2122import { Button , ButtonProps } from "@podkit/buttons/Button" ;
2223import { cn } from "@podkit/lib/cn" ;
2324import { userClient } from "./service/public-api" ;
2425import { ProductLogo } from "./components/ProductLogo" ;
2526import { useIsDataOps } from "./data/featureflag-query" ;
26- import GitpodClassicCard from "./images/gitpod-classic-card.png" ;
2727import { LoadingState } from "@podkit/loading/LoadingState" ;
2828import { isGitpodIo } from "./utils" ;
29+ import { trackEvent } from "./Analytics" ;
30+ import { useToast } from "./components/toasts/Toasts" ;
31+ import onaWordmark from "./images/ona-wordmark.svg" ;
32+ import onaApplication from "./images/ona-application.webp" ;
2933
3034export function markLoggedIn ( ) {
3135 document . cookie = GitpodCookie . generateCookie ( window . location . hostname ) ;
@@ -64,7 +68,8 @@ export const Login: FC<LoginProps> = ({ onLoggedIn }) => {
6468 const [ hostFromContext , setHostFromContext ] = useState < string | undefined > ( ) ;
6569 const [ repoPathname , setRepoPathname ] = useState < string | undefined > ( ) ;
6670
67- const enterprise = ! ! authProviders . data && authProviders . data . length === 0 ;
71+ const { data : installationConfig } = useInstallationConfiguration ( ) ;
72+ const enterprise = ! ! installationConfig ?. isDedicatedInstallation ;
6873
6974 useEffect ( ( ) => {
7075 try {
@@ -93,9 +98,15 @@ export const Login: FC<LoginProps> = ({ onLoggedIn }) => {
9398 return (
9499 < div
95100 id = "login-container"
96- className = { cn ( "z-50 flex flex-col-reverse lg:flex-row w-full min-h-screen" , {
97- "bg-[#FDF1E7] dark:bg-[#23211e]" : ! enterprise ,
98- } ) }
101+ className = "z-50 flex flex-col-reverse lg:flex-row w-full min-h-screen"
102+ style = {
103+ ! enterprise
104+ ? {
105+ background :
106+ "linear-gradient(390deg, #1F1329 0%, #333A75 20%, #556CA8 50%, #90A898 60%, #90A898 70%, #E2B15C 90%, #BEA462 100%)" ,
107+ }
108+ : undefined
109+ }
99110 >
100111 { enterprise ? (
101112 < EnterpriseLoginWrapper
@@ -147,7 +158,7 @@ const PAYGLoginWrapper: FC<LoginWrapperProps> = ({ providerFromContext, repoPath
147158 < div
148159 id = "login-section"
149160 // for some reason, min-h-dvh does not work, so we need tailwind's arbitrary values
150- className = "w-full min-h-[100dvh] lg:w-2/3 flex flex-col justify-center items-center bg-[#FDF1E7] dark:bg-[#23211e] p-2"
161+ className = "w-full min-h-[100dvh] lg:w-full flex flex-col justify-center items-center p-2"
151162 >
152163 < div
153164 id = "login-section-column"
@@ -212,6 +223,9 @@ const LoginContent = ({
212223 const authProviders = useAuthProviderDescriptions ( ) ;
213224 const [ errorMessage , setErrorMessage ] = useState < string | undefined > ( undefined ) ;
214225
226+ const { data : installationConfig } = useInstallationConfiguration ( ) ;
227+ const enterprise = ! ! installationConfig ?. isDedicatedInstallation ;
228+
215229 const updateUser = useCallback ( async ( ) => {
216230 await getGitpodService ( ) . reconnect ( ) ;
217231 const { user } = await userClient . getAuthenticatedUser ( { } ) ;
@@ -314,32 +328,127 @@ const LoginContent = ({
314328 < SSOLoginForm onSuccess = { authorizeSuccessful } />
315329 </ div >
316330 { errorMessage && < ErrorMessage imgSrc = { exclamation } message = { errorMessage } /> }
331+
332+ { /* Gitpod Classic sunset notice - only show for non-enterprise */ }
333+ { ! enterprise && (
334+ < div className = "mt-6 text-center text-sm" >
335+ < p className = "text-pk-content-primary" >
336+ Gitpod classic is sunsetting fall 2025.{ " " }
337+ < a
338+ href = "https://app.gitpod.io"
339+ target = "_blank"
340+ rel = "noopener noreferrer"
341+ className = "gp-link hover:text-gray-600"
342+ >
343+ Try the new Gitpod
344+ </ a > { " " }
345+ now (hosted compute & SWE agents coming soon )
346+ </ p >
347+ </ div >
348+ ) }
317349 </ div >
318350 ) ;
319351} ;
320352
321353const RightProductDescriptionPanel = ( ) => {
322- return (
323- < div className = "w-full lg:w-1/3 flex flex-col md:justify-center p-4 lg:p-10 lg:pb-2 md:min-h-screen" >
354+ const [ email , setEmail ] = useState ( "" ) ;
355+ const [ isSubmitted , setIsSubmitted ] = useState ( false ) ;
356+ const { toast } = useToast ( ) ;
357+
358+ const handleEmailSubmit = ( e : React . FormEvent ) => {
359+ e . preventDefault ( ) ;
360+ if ( ! email . trim ( ) ) return ;
361+
362+ trackEvent ( "waitlist_joined" , { email : email , feature : "Ona" } ) ;
363+
364+ setIsSubmitted ( true ) ;
365+
366+ toast (
324367 < div >
325- < div className = "justify-center md:justify-start mb-6 md:mb-8" >
326- < h2 className = "text-2xl font-medium mb-2 dark:text-white inline-flex items-center gap-x-2" >
327- Gitpod Classic
368+ < div className = "font-medium" > You're on the waitlist</ div >
369+ < div className = "text-sm opacity-80" > We'll reach out to you soon.</ div >
370+ </ div > ,
371+ ) ;
372+ } ;
373+
374+ return (
375+ < div className = "w-full lg:max-w-lg 2xl:max-w-[600px] flex flex-col justify-center px-4 lg:px-4 md:min-h-screen my-auto" >
376+ < div className = "rounded-lg flex flex-col gap-6 text-white h-full py-4 lg:py-6 max-w-lg mx-auto w-full" >
377+ < div className = "relative bg-white/10 backdrop-blur-sm rounded-lg pt-4 px-4 -mt-2" >
378+ < div className = "flex justify-center pt-4 mb-4" >
379+ < img src = { onaWordmark } alt = "ONA" className = "w-36" draggable = "false" />
380+ </ div >
381+ < div className = "relative overflow-hidden" >
382+ < img
383+ src = { onaApplication }
384+ alt = "Ona application preview"
385+ className = "w-full h-auto rounded-lg shadow-lg translate-y-8"
386+ draggable = "false"
387+ />
388+ </ div >
389+ </ div >
390+
391+ < div className = "flex flex-col gap-4 flex-1" >
392+ < h2 className = "text-white text-xl font-bold leading-tight text-center max-w-sm mx-auto" >
393+ Meet Ona - the privacy-first software engineering agent.
328394 </ h2 >
329- < p className = "text-pk-content-secondary mb-2" >
330- Automated, standardized development environments hosted by us in Gitpod’s infrastructure. Users
331- who joined before October 1, 2024 on non-Enterprise plans are considered Gitpod Classic users.
332- </ p >
333395
334- < p className = "text-pk-content-secondary mb-2" >
335- Gitpod Classic is sunsetting fall 2025.{ " " }
336- < a className = "gp-link font-bold" href = "https://app.gitpod.io" target = "_blank" rel = "noreferrer" >
337- Try the new Gitpod
338- </ a > { " " }
339- now (hosted compute coming soon).
340- </ p >
396+ < div className = "space-y-3 mt-4" >
397+ < p className = "text-white/70 text-base" >
398+ Delegate software tasks to Ona. It writes code, runs tests, and opens a pull request. Or
399+ jump in to inspect output or pair program in your IDE.
400+ </ p >
401+ < p className = "text-white/70 text-base mt-2" >
402+ Ona runs inside your infrastructure (VPC), with full audit trails, zero data exposure, and
403+ support for any LLM.
404+ </ p >
405+ </ div >
406+
407+ < div className = "mt-4" >
408+ { ! isSubmitted ? (
409+ < form onSubmit = { handleEmailSubmit } className = "space-y-3" >
410+ < div className = "flex gap-2" >
411+ < input
412+ type = "email"
413+ value = { email }
414+ onChange = { ( e ) => setEmail ( e . target . value ) }
415+ placeholder = "Enter your work email"
416+ className = "flex-1 px-4 py-2.5 rounded-lg bg-white/10 backdrop-blur-sm border border-white/20 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/30 text-sm"
417+ required
418+ />
419+ < button
420+ type = "submit"
421+ className = "bg-white text-gray-900 font-medium py-2.5 px-4 rounded-lg hover:bg-gray-100 transition-colors text-sm inline-flex items-center justify-center gap-2"
422+ >
423+ Request access
424+ < span className = "font-bold" > →</ span >
425+ </ button >
426+ </ div >
427+ < p className = "text-xs text-white/70" >
428+ By submitting this, you agree to our{ " " }
429+ < a
430+ href = "https://www.gitpod.io/privacy/"
431+ target = "_blank"
432+ rel = "noopener noreferrer"
433+ className = "underline hover:text-white"
434+ >
435+ privacy policy
436+ </ a >
437+ </ p >
438+ </ form >
439+ ) : (
440+ < a
441+ href = "https://www.gitpod.io/solutions/ai"
442+ target = "_blank"
443+ rel = "noopener noreferrer"
444+ className = "w-full bg-white/20 backdrop-blur-sm text-white font-medium py-2.5 px-4 rounded-lg hover:bg-white/30 transition-colors border border-white/20 inline-flex items-center justify-center gap-2 text-sm"
445+ >
446+ Learn more
447+ < span className = "font-bold" > →</ span >
448+ </ a >
449+ ) }
450+ </ div >
341451 </ div >
342- < img src = { GitpodClassicCard } alt = "Gitpod Classic" className = "w-full" />
343452 </ div >
344453 </ div >
345454 ) ;
0 commit comments