@@ -5,12 +5,61 @@ import { EXTERNAL_LINKS, IMAGE_PATHS } from '@/lib/constants';
55import { motion , useScroll , useTransform } from 'framer-motion' ;
66import { Sparkles } from 'lucide-react' ;
77import Image from 'next/image' ;
8+ import { useEffect , useRef , useState } from 'react' ;
89
910export default function HeroSection ( ) {
1011 const { scrollY } = useScroll ( ) ;
1112 const yText = useTransform ( scrollY , [ 0 , 500 ] , [ 0 , 150 ] ) ;
1213 const yImg = useTransform ( scrollY , [ 0 , 500 ] , [ 0 , - 80 ] ) ;
1314 const opacity = useTransform ( scrollY , [ 0 , 300 ] , [ 1 , 0 ] ) ;
15+ const devfolioContainerRef = useRef ( null ) ;
16+ const [ devfolioButtonVisible , setDevfolioButtonVisible ] = useState ( false ) ;
17+
18+ // Load Devfolio apply button SDK on this page
19+ useEffect ( ( ) => {
20+ const existing = document . querySelector (
21+ 'script[src="https://apply.devfolio.co/v2/sdk.js"]'
22+ ) ;
23+ const script = existing || document . createElement ( 'script' ) ;
24+ script . src = 'https://apply.devfolio.co/v2/sdk.js' ;
25+ script . async = true ;
26+ script . defer = true ;
27+
28+ if ( ! existing ) {
29+ document . body . appendChild ( script ) ;
30+ }
31+
32+ return ( ) => {
33+ if ( ! existing && script . parentNode ) {
34+ script . parentNode . removeChild ( script ) ;
35+ }
36+ } ;
37+ } , [ ] ) ;
38+
39+ // Detect when Devfolio widget renders and fall back to native button if it doesn't
40+ useEffect ( ( ) => {
41+ if ( ! devfolioContainerRef . current ) return undefined ;
42+
43+ const target = devfolioContainerRef . current ;
44+ const observer = new MutationObserver ( ( ) => {
45+ if ( target . childElementCount > 0 ) {
46+ setDevfolioButtonVisible ( true ) ;
47+ }
48+ } ) ;
49+
50+ observer . observe ( target , { childList : true } ) ;
51+
52+ const timeout = setTimeout ( ( ) => {
53+ if ( target . childElementCount > 0 ) {
54+ setDevfolioButtonVisible ( true ) ;
55+ }
56+ } , 2000 ) ;
57+
58+ return ( ) => {
59+ observer . disconnect ( ) ;
60+ clearTimeout ( timeout ) ;
61+ } ;
62+ } , [ ] ) ;
1463
1564 return (
1665 < section
@@ -100,21 +149,28 @@ export default function HeroSection() {
100149
101150 < div className = "grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-md" >
102151 < div className = "sm:col-span-2" >
103- < Button
104- variant = "devfolio"
105- size = "default"
106- className = "group w-full font-semibold gap-1.5"
107- onClick = { ( ) => window . open ( EXTERNAL_LINKS . devfolio , '_blank' ) }
108- >
109- < Image
110- src = "/images/devwhite-removebg-preview.png"
111- alt = "DEVFOLIO LOGO"
112- width = { 44 }
113- height = { 44 }
114- className = "object-contain"
152+ < div className = "w-full flex justify-center" >
153+ < div
154+ ref = { devfolioContainerRef }
155+ className = "apply-button"
156+ data-hackathon-slug = "opencode25"
157+ data-button-theme = "dark"
158+ style = { { height : '44px' , width : '312px' } }
159+ aria-label = "Apply with Devfolio"
115160 />
116- Apply with Devfolio
117- </ Button >
161+ { ! devfolioButtonVisible && (
162+ < Button
163+ variant = "devfolio"
164+ size = "default"
165+ className = "absolute w-[312px] h-[44px] font-semibold gap-1.5"
166+ onClick = { ( ) =>
167+ window . open ( EXTERNAL_LINKS . devfolio , '_blank' )
168+ }
169+ >
170+ Apply with Devfolio
171+ </ Button >
172+ ) }
173+ </ div >
118174 </ div >
119175
120176 < Button
0 commit comments