ysharma HF Staff commited on
Commit
b9c4cb0
Β·
verified Β·
1 Parent(s): 9c7a22f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +400 -372
app.py CHANGED
@@ -19,343 +19,112 @@ else:
19
  logger.warning("HF_TOKEN not found - running without authentication")
20
 
21
  DATASET_NAME = "ysharma/build-small-hackathon-registrations"
 
 
 
22
 
23
  HEADER_HTML = """
24
- <div style="
25
- background: linear-gradient(135deg, #f5ecd9 0%, #ebe0c4 50%, #dccfa8 100%);
26
- border-radius: 20px;
27
- padding: 0;
28
- margin-bottom: 24px;
29
- box-shadow: 0 10px 40px rgba(74, 49, 16, 0.15);
30
- overflow: hidden;
31
- border: 2px solid #8b6f47;
32
- ">
33
- <!-- Banner Placeholder (artwork coming soon) -->
34
- <div style="
35
- background: linear-gradient(135deg, #2d5016 0%, #4a7c2e 50%, #6b9039 100%);
36
- padding: 56px 32px;
37
- text-align: center;
38
- position: relative;
39
- color: #f5ecd9;
40
- border-bottom: 2px solid #8b6f47;
41
- ">
42
- <div style="
43
- font-size: 13px;
44
- letter-spacing: 4px;
45
- text-transform: uppercase;
46
- opacity: 0.85;
47
- margin-bottom: 12px;
48
- ">❋ Gradio &times; Hugging Face presents ❋</div>
49
- <h1 style="
50
- margin: 0 0 12px 0;
51
- font-size: 44px;
52
- font-weight: 800;
53
- letter-spacing: -1px;
54
- color: #f5ecd9;
55
- ">πŸͺ΅ Build Small Hackathon</h1>
56
- <div style="
57
- font-size: 20px;
58
- font-style: italic;
59
- margin-bottom: 8px;
60
- color: #e8dcc0;
61
- ">Making AI Fun Again</div>
62
- <div style="font-size: 16px; opacity: 0.85;">May 29 – June 8, 2026 Β· Online &amp; Global</div>
63
- <div style="
64
- margin-top: 24px;
65
- display: inline-block;
66
- background: rgba(245, 236, 217, 0.15);
67
- border: 1px dashed rgba(245, 236, 217, 0.5);
68
- border-radius: 8px;
69
- padding: 8px 16px;
70
- font-size: 13px;
71
- opacity: 0.85;
72
- ">πŸ—ΊοΈ event banner being illustrated Β· placeholder for now</div>
73
- </div>
74
 
75
- <!-- Content Section -->
76
- <div style="padding: 28px 32px;">
77
- <!-- Two Tracks -->
78
- <a href="https://huggingface.co/build-small-hackathon" target="_blank" style="text-decoration: none;">
79
- <div style="
80
- background: rgba(74, 124, 46, 0.08);
81
- border: 2px solid rgba(74, 124, 46, 0.35);
82
- border-radius: 14px;
83
- padding: 18px 22px;
84
- margin-bottom: 14px;
85
- transition: all 0.25s ease;
86
- "
87
- onmouseover="this.style.background='rgba(74, 124, 46, 0.15)'; this.style.transform='translateY(-2px)'"
88
- onmouseout="this.style.background='rgba(74, 124, 46, 0.08)'; this.style.transform='translateY(0)'"
89
- >
90
- <div style="text-align: center; color: #2d5016; font-weight: 700; letter-spacing: 2px; font-size: 12px; margin-bottom: 14px;">
91
- ❋ TWO TRACKS ❋
92
- </div>
93
- <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
94
- <div style="text-align: center;">
95
- <div style="font-size: 32px; margin-bottom: 6px;">🏑</div>
96
- <div style="color: #2d5016; font-weight: 700; font-size: 15px;">Backyard AI</div>
97
- <div style="color: #5d4a2e; font-size: 13px; line-height: 1.4; margin-top: 4px;">Solve a real problem for someone you know</div>
98
- </div>
99
- <div style="text-align: center;">
100
- <div style="font-size: 32px; margin-bottom: 6px;">πŸ„</div>
101
- <div style="color: #2d5016; font-weight: 700; font-size: 15px;">Thousand Token Wood</div>
102
- <div style="color: #5d4a2e; font-size: 13px; line-height: 1.4; margin-top: 4px;">Build something delightful and whimsical</div>
103
- </div>
104
- </div>
105
- <div style="text-align: center; margin-top: 14px; color: #6b4423; font-size: 12px;">
106
- Read the full chapter book β†’ huggingface.co/build-small-hackathon
107
- </div>
108
- </div>
109
- </a>
110
-
111
- <!-- Three Rules + Coming Soon row -->
112
- <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 14px;">
113
- <div style="
114
- background: rgba(139, 111, 71, 0.10);
115
- border: 1px solid rgba(139, 111, 71, 0.35);
116
- border-radius: 10px;
117
- padding: 14px 16px;
118
- ">
119
- <div style="color: #6b4423; font-weight: 700; font-size: 12px; letter-spacing: 1.5px; margin-bottom: 8px;">✦ THE 3 RULES</div>
120
- <div style="color: #3a2a14; font-size: 13px; line-height: 1.7;">
121
- 1. Models ≀ 32B parameters<br>
122
- 2. Built on Gradio + Spaces<br>
123
- 3. Demo video + social post
124
- </div>
125
  </div>
126
- <div style="
127
- background: rgba(201, 176, 114, 0.20);
128
- border: 1px solid rgba(201, 176, 114, 0.55);
129
- border-radius: 10px;
130
- padding: 14px 16px;
131
- ">
132
- <div style="color: #6b4423; font-weight: 700; font-size: 12px; letter-spacing: 1.5px; margin-bottom: 8px;">🎁 PRIZES &amp; CREDITS</div>
133
- <div style="color: #3a2a14; font-size: 13px; line-height: 1.7; font-style: italic;">
134
- Sponsor lineup, prize pool, and free API/compute credits announcing soon β€” sit tight, friend.
135
- </div>
136
  </div>
 
137
  </div>
138
-
139
- <!-- Discord Notice -->
140
- <div style="
141
- background: rgba(74, 124, 46, 0.10);
142
- border: 1px solid rgba(74, 124, 46, 0.35);
143
- border-radius: 10px;
144
- padding: 14px 18px;
145
- text-align: center;
146
- ">
147
- <p style="margin: 0; color: #2d5016; font-size: 14px; line-height: 1.6;">
148
- πŸ’¬ Join the <a href="https://discord.gg/92sEPT2Zhv" target="_blank" style="color: #4a7c2e; font-weight: 700; text-decoration: underline;">Gradio Discord</a>
149
- channel <code style="background: rgba(45, 80, 22, 0.12); padding: 2px 7px; border-radius: 4px; font-size: 12px; color: #2d5016;">build-small-hackathon-official</code>
150
- for office hours, AMAs, and support.
151
- </p>
152
  </div>
153
  </div>
154
  </div>
155
  """
156
 
157
- DEADLINES_HTML = """
158
- <div style="
159
- background: #f5ecd9;
160
- border: 2px solid #8b6f47;
161
- border-radius: 16px;
162
- padding: 22px 24px;
163
- margin-bottom: 16px;
164
- box-shadow: 0 4px 12px rgba(74, 49, 16, 0.10);
165
- height: 100%;
166
- box-sizing: border-box;
167
- ">
168
- <div style="text-align: center; color: #6b4423; font-weight: 800; letter-spacing: 2px; font-size: 13px; margin-bottom: 16px;">
169
- ✦ TRAIL MAP β€” KEY DATES ✦
170
- </div>
171
- <div style="display: grid; gap: 10px; color: #3a2a14;">
172
- <div style="display: flex; align-items: center; gap: 10px;">
173
- <span style="font-size: 20px;">πŸ“…</span>
174
- <div><strong>Registration closes:</strong> Wed, May 27, 2026 Β· 23:59 UTC</div>
175
- </div>
176
- <div style="display: flex; align-items: center; gap: 10px;">
177
- <span style="font-size: 20px;">🎟️</span>
178
- <div><strong>Credits assigned:</strong> Thu, May 28, 2026</div>
179
- </div>
180
- <div style="display: flex; align-items: center; gap: 10px;">
181
- <span style="font-size: 20px;">πŸš€</span>
182
- <div><strong>Hack window opens:</strong> Fri, May 29, 2026</div>
183
  </div>
184
- <div style="display: flex; align-items: center; gap: 10px;">
185
- <span style="font-size: 20px;">🏁</span>
186
- <div><strong>Submissions due:</strong> Mon, June 8, 2026</div>
 
 
 
 
 
 
 
187
  </div>
188
- <div style="
189
- margin-top: 6px;
190
- background: rgba(178, 60, 50, 0.10);
191
- border: 1px solid rgba(178, 60, 50, 0.40);
192
- border-radius: 8px;
193
- padding: 10px 12px;
194
- color: #8b2e25;
195
- font-weight: 600;
196
- text-align: center;
197
- font-size: 13px;
198
- ">β›” No registrations accepted once the event starts. Lock it in before May 27!</div>
199
  </div>
200
  </div>
201
  """
202
 
203
- COUNTER = """
204
- <!DOCTYPE html>
205
- <html lang="en">
206
- <head>
207
- <meta charset="UTF-8">
208
- <style>
209
- * { margin: 0; padding: 0; box-sizing: border-box; }
210
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: transparent; }
211
- .countdown-container {
212
- background: linear-gradient(135deg, #2d5016 0%, #1f3a0f 100%);
213
- border: 2px solid #8b6f47;
214
- border-radius: 16px;
215
- padding: 24px 22px;
216
- box-shadow: 0 4px 12px rgba(74, 49, 16, 0.20);
217
- text-align: center;
218
- color: #f5ecd9;
219
- height: 100%;
220
- box-sizing: border-box;
221
- }
222
- .title {
223
- font-size: 14px;
224
- font-weight: 800;
225
- letter-spacing: 2px;
226
- text-transform: uppercase;
227
- color: #f5ecd9;
228
- margin-bottom: 4px;
229
- }
230
- .subtitle {
231
- font-size: 13px;
232
- color: #c9b072;
233
- margin-bottom: 20px;
234
- font-style: italic;
235
- }
236
- .countdown {
237
- display: flex;
238
- justify-content: space-around;
239
- align-items: center;
240
- gap: 10px;
241
- flex-wrap: wrap;
242
- }
243
- .time-unit {
244
- display: flex;
245
- flex-direction: column;
246
- align-items: center;
247
- min-width: 70px;
248
- }
249
- .circle { position: relative; width: 78px; height: 78px; margin-bottom: 6px; }
250
- .circle svg { width: 100%; height: 100%; transform: rotate(-90deg); }
251
- .circle-bg { fill: none; stroke: rgba(245, 236, 217, 0.15); stroke-width: 5; }
252
- .circle-progress {
253
- fill: none;
254
- stroke: #c9b072;
255
- stroke-width: 5;
256
- stroke-linecap: round;
257
- stroke-dasharray: 220;
258
- stroke-dashoffset: 220;
259
- transition: stroke-dashoffset 0.3s ease;
260
- }
261
- .number {
262
- position: absolute; top: 50%; left: 50%;
263
- transform: translate(-50%, -50%);
264
- font-size: 22px; font-weight: 700;
265
- color: #f5ecd9;
266
- font-family: 'Courier New', monospace;
267
- }
268
- .label {
269
- font-size: 10px;
270
- font-weight: 700;
271
- color: #c9b072;
272
- text-transform: uppercase;
273
- letter-spacing: 1.5px;
274
- }
275
- @media (max-width: 480px) {
276
- .countdown { gap: 6px; }
277
- .circle { width: 62px; height: 62px; }
278
- .number { font-size: 18px; }
279
- }
280
- </style>
281
- </head>
282
- <body>
283
- <div class="countdown-container">
284
- <div class="title">πŸ•οΈ Hack window opens in</div>
285
- <div class="subtitle">May 29, 2026 Β· 00:00 UTC</div>
286
- <div class="countdown">
287
- <div class="time-unit">
288
- <div class="circle">
289
- <svg><circle class="circle-bg" cx="39" cy="39" r="35"></circle><circle class="circle-progress" cx="39" cy="39" r="35" id="days-progress"></circle></svg>
290
- <div class="number" id="days">00</div>
291
- </div>
292
- <div class="label">Days</div>
293
- </div>
294
- <div class="time-unit">
295
- <div class="circle">
296
- <svg><circle class="circle-bg" cx="39" cy="39" r="35"></circle><circle class="circle-progress" cx="39" cy="39" r="35" id="hours-progress"></circle></svg>
297
- <div class="number" id="hours">00</div>
298
- </div>
299
- <div class="label">Hours</div>
300
- </div>
301
- <div class="time-unit">
302
- <div class="circle">
303
- <svg><circle class="circle-bg" cx="39" cy="39" r="35"></circle><circle class="circle-progress" cx="39" cy="39" r="35" id="minutes-progress"></circle></svg>
304
- <div class="number" id="minutes">00</div>
305
- </div>
306
- <div class="label">Minutes</div>
307
- </div>
308
- <div class="time-unit">
309
- <div class="circle">
310
- <svg><circle class="circle-bg" cx="39" cy="39" r="35"></circle><circle class="circle-progress" cx="39" cy="39" r="35" id="seconds-progress"></circle></svg>
311
- <div class="number" id="seconds">00</div>
312
- </div>
313
- <div class="label">Seconds</div>
314
- </div>
315
- </div>
316
- </div>
317
- <script>
318
- // Hack window opens May 29, 2026 at 00:00 UTC (month is 0-indexed: 4 = May)
319
- const targetDate = new Date(Date.UTC(2026, 4, 29, 0, 0, 0));
320
- function updateCountdown() {
321
- const now = new Date();
322
- const difference = targetDate.getTime() - now.getTime();
323
- if (difference > 0) {
324
- const days = Math.floor(difference / (1000 * 60 * 60 * 24));
325
- const hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
326
- const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
327
- const seconds = Math.floor((difference % (1000 * 60)) / 1000);
328
- document.getElementById('days').textContent = days.toString().padStart(2, '0');
329
- document.getElementById('hours').textContent = hours.toString().padStart(2, '0');
330
- document.getElementById('minutes').textContent = minutes.toString().padStart(2, '0');
331
- document.getElementById('seconds').textContent = seconds.toString().padStart(2, '0');
332
- updateProgress('days-progress', days, 365);
333
- updateProgress('hours-progress', hours, 24);
334
- updateProgress('minutes-progress', minutes, 60);
335
- updateProgress('seconds-progress', seconds, 60);
336
- } else {
337
- document.getElementById('days').textContent = '00';
338
- document.getElementById('hours').textContent = '00';
339
- document.getElementById('minutes').textContent = '00';
340
- document.getElementById('seconds').textContent = '00';
341
- updateProgress('days-progress', 0, 365);
342
- updateProgress('hours-progress', 0, 24);
343
- updateProgress('minutes-progress', 0, 60);
344
- updateProgress('seconds-progress', 0, 60);
345
- }
346
- }
347
- function updateProgress(elementId, current, max) {
348
- const circle = document.getElementById(elementId);
349
- const circumference = 220;
350
- const progress = (current / max) * circumference;
351
- const offset = circumference - progress;
352
- circle.style.strokeDashoffset = offset;
353
  }
354
- updateCountdown();
355
- setInterval(updateCountdown, 1000);
356
- </script>
357
- </body>
358
- </html>
 
 
 
 
 
 
 
359
  """
360
 
361
 
@@ -507,7 +276,7 @@ def verify_registration(email, hf_username):
507
  if isinstance(prev, str):
508
  prev = prev.strip("[]'\"").replace("'", "")
509
 
510
- quests = registration.get('bonus_quests', '') if hasattr(registration, 'get') else registration['bonus_quests']
511
  if isinstance(quests, str):
512
  quests = quests.strip("[]'\"").replace("'", "")
513
  quests_str = quests if quests else "_None selected_"
@@ -543,7 +312,7 @@ def verify_registration(email, hf_username):
543
  - 🎟️ API & compute credits will be assigned on **Thu, May 28, 2026**
544
  - πŸš€ Hack window opens **Fri, May 29, 2026**
545
  - 🏁 Submissions due **Mon, June 8, 2026**
546
- - πŸ’¬ Join the Gradio Discord channel `build-small-hackathon-official`: https://discord.gg/92sEPT2Zhv
547
  - πŸ“§ Watch your email for important updates
548
  """
549
  logger.info(f"Verification successful for {email}")
@@ -615,9 +384,8 @@ def submit_registration(full_name, email, hf_username, gradio_usage,
615
 
616
  Thank you, **{full_name}**! Your spot is locked in.
617
 
618
- 🎟️ API & compute credits will be assigned on **Thu, May 28, 2026**.<br>
619
- πŸš€ Hack window opens **Fri, May 29, 2026** Β· submissions due **Mon, June 8, 2026**.<br>
620
- πŸ’¬ Join the Gradio Discord channel `build-small-hackathon-official` for office hours, AMAs, and support: https://discord.gg/92sEPT2Zhv<br>
621
  πŸ“§ Watch your email for credits and updates.
622
 
623
  **See you in the woods! πŸ„πŸͺ΅**"""
@@ -648,43 +416,308 @@ else:
648
 
649
  custom_css = """
650
  .gradio-container {
651
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
653
  #submit-btn {
654
  background: linear-gradient(135deg, #4a7c2e 0%, #2d5016 100%) !important;
655
- border: 2px solid #6b4423 !important;
656
  color: #f5ecd9 !important;
657
  font-weight: 700 !important;
658
- font-size: 18px !important;
659
- padding: 16px 32px !important;
660
- border-radius: 12px !important;
661
- box-shadow: 0 4px 12px rgba(74, 49, 16, 0.20) !important;
662
  transition: all 0.25s ease !important;
663
  }
664
  #submit-btn:hover {
665
- transform: translateY(-2px) !important;
666
- box-shadow: 0 6px 20px rgba(74, 49, 16, 0.30) !important;
667
  background: linear-gradient(135deg, #5a8c3e 0%, #3d6020 100%) !important;
668
  }
669
- #submit-btn:active {
670
- transform: translateY(0) !important;
671
- }
672
  #verify-btn {
673
  background: #6b4423 !important;
674
- border: 2px solid #c9b072 !important;
675
  color: #f5ecd9 !important;
676
  font-weight: 700 !important;
677
- font-size: 16px !important;
678
- padding: 12px 24px !important;
679
  border-radius: 8px !important;
680
- box-shadow: 0 3px 10px rgba(74, 49, 16, 0.25) !important;
681
  transition: all 0.25s ease !important;
682
  }
683
  #verify-btn:hover {
684
- transform: translateY(-2px) !important;
685
- box-shadow: 0 5px 15px rgba(74, 49, 16, 0.35) !important;
686
  background: #7d5430 !important;
687
  }
 
 
 
 
 
 
 
688
  """
689
 
690
 
@@ -695,20 +728,14 @@ with gr.Blocks(
695
  ) as demo:
696
 
697
  gr.HTML(HEADER_HTML)
698
-
699
- with gr.Row(equal_height=True):
700
- with gr.Column(scale=1):
701
- gr.HTML(DEADLINES_HTML)
702
- with gr.Column(scale=1):
703
- gr.HTML(COUNTER)
704
-
705
- gr.Markdown("---")
706
 
707
  with gr.Tabs():
708
  with gr.Tab("πŸ“ Register"):
709
  with gr.Row():
710
  with gr.Column():
711
- gr.Markdown("## ❋ 1. Personal Information")
712
  full_name = gr.Textbox(
713
  label="Full Name *",
714
  placeholder="Your full name as you'd like it on certificates",
@@ -716,7 +743,7 @@ with gr.Blocks(
716
  )
717
  email = gr.Textbox(
718
  label="Email Address *",
719
- placeholder="Primary contact email (we'll send updates and credits info here)",
720
  max_lines=1,
721
  )
722
  hf_username = gr.Textbox(
@@ -737,7 +764,7 @@ with gr.Blocks(
737
  )
738
 
739
  with gr.Column():
740
- gr.Markdown("## ❋ 2. Hackathon Participation")
741
  track_interest = gr.Radio(
742
  label="Which track interests you most? *",
743
  choices=[
@@ -784,7 +811,7 @@ with gr.Blocks(
784
 
785
  with gr.Row():
786
  with gr.Column():
787
- gr.Markdown("## ❋ 3. Build Small Specifics")
788
  planned_small_model = gr.Textbox(
789
  label="Which small model are you planning to use? (optional)",
790
  placeholder="e.g. Llama-3.2-3B, Qwen2.5-7B, gemma-2-2b-it, SmolLM-1.7B...",
@@ -801,18 +828,18 @@ with gr.Blocks(
801
  "πŸ“‘ Sharing is Caring β€” share an agent trace",
802
  "πŸ““ Field Notes β€” write a blog post / report",
803
  ],
804
- info="Pick as many as you'd like. You can change your mind during the event β€” this is just signal for us.",
805
  )
806
 
807
  with gr.Column():
808
- gr.Markdown("## ❋ 4. Project Idea (optional)")
809
  project_description = gr.Textbox(
810
  label="What are you most excited to build?",
811
  placeholder="A neighbor's recipe-translator? A whimsical mushroom-identifier? Tell us in a sentence or two.",
812
  lines=4,
813
  )
814
 
815
- gr.Markdown("## ❋ 5. Acknowledgment")
816
  acknowledgment = gr.Checkbox(
817
  label="I'm in. *",
818
  info=(
@@ -873,11 +900,8 @@ with gr.Blocks(
873
 
874
  with gr.Tab("πŸ” Verify Registration"):
875
  gr.Markdown("""
876
- ## Check Your Registration Status
877
-
878
- Enter your email address and Hugging Face username to verify your registration and view your details.
879
-
880
- **Note:** Both email and username must match exactly for security purposes.
881
  """)
882
  with gr.Row():
883
  with gr.Column():
@@ -898,16 +922,14 @@ with gr.Blocks(
898
  elem_id="verify-btn",
899
  )
900
  with gr.Column():
901
- gr.Markdown("""
902
- ### Need Help?
903
-
904
- - Make sure you enter the **exact** email and username you used during registration
905
- - Both fields are **case-insensitive** but must match your registration
906
- - If you can't find your registration and registration is still open (before May 27, 23:59 UTC), try registering again
907
- - Once registration closes, no new entries can be added
908
 
909
  **Support:**
910
- - Discord: https://discord.gg/92sEPT2Zhv (channel `build-small-hackathon-official`)
911
  - Email: gradio-team@huggingface.co
912
  """)
913
  verify_output = gr.Markdown()
@@ -917,11 +939,17 @@ with gr.Blocks(
917
  outputs=verify_output,
918
  )
919
 
920
- gr.Markdown("""
921
- ---
922
- ✦ **Questions?** Join the Gradio [Discord](https://discord.gg/92sEPT2Zhv) channel `build-small-hackathon-official` or email gradio-team@huggingface.co ✦
 
 
 
923
  """)
924
 
 
 
 
925
 
926
  if __name__ == "__main__":
927
  demo.launch(allowed_paths=["."])
 
19
  logger.warning("HF_TOKEN not found - running without authentication")
20
 
21
  DATASET_NAME = "ysharma/build-small-hackathon-registrations"
22
+ DISCORD_INVITE = "https://discord.gg/YHECTft87Z"
23
+ DISCORD_CHANNEL = "build-small-hackathon-official"
24
+
25
 
26
  HEADER_HTML = """
27
+ <div class="bsh-banner">
28
+ <h1>πŸͺ΅ Build Small Hackathon</h1>
29
+ <div class="tagline">Making AI Fun Again</div>
30
+ <div class="meta">May 29 – June 8, 2026 Β· Online &amp; Global</div>
31
+ <div class="placeholder">πŸ—ΊοΈ event artwork being illustrated Β· placeholder for now</div>
32
+ </div>
33
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
+ INFO_ROW_HTML = """
36
+ <div class="bsh-info-row">
37
+ <div class="bsh-card">
38
+ <div class="bsh-title">❋ Two Tracks</div>
39
+ <div class="bsh-content">
40
+ <div class="bsh-track">
41
+ <span class="bsh-emoji">🏑</span>
42
+ <span class="bsh-track-name">Backyard AI</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  </div>
44
+ <div class="bsh-track-desc">Solve a real problem for someone you know</div>
45
+ <div class="bsh-track">
46
+ <span class="bsh-emoji">πŸ„</span>
47
+ <span class="bsh-track-name">Thousand Token Wood</span>
 
 
 
 
 
 
48
  </div>
49
+ <div class="bsh-track-desc">Build something delightful and whimsical</div>
50
  </div>
51
+ </div>
52
+ <div class="bsh-card">
53
+ <div class="bsh-title">✦ Three Rules</div>
54
+ <ol class="bsh-rules">
55
+ <li>Models ≀ 32B parameters</li>
56
+ <li>Built on Gradio + Spaces</li>
57
+ <li>Demo video + social post</li>
58
+ </ol>
59
+ </div>
60
+ <div class="bsh-card">
61
+ <div class="bsh-title">🎁 Prizes &amp; Credits</div>
62
+ <div class="bsh-content">
63
+ <div class="bsh-soon"><em>Sponsor lineup, prize pool, and free API/compute credits announcing soon β€” sit tight, friend.</em></div>
64
+ <div class="bsh-link">β†’ <a href="https://huggingface.co/build-small-hackathon" target="_blank">Read the chapter book</a></div>
65
  </div>
66
  </div>
67
  </div>
68
  """
69
 
70
+ DATES_ROW_HTML = """
71
+ <div class="bsh-dates-row">
72
+ <div class="bsh-dates">
73
+ <div class="bsh-title">✦ Trail Map · Key Dates</div>
74
+ <div class="bsh-dates-grid">
75
+ <div>πŸ“… <b>Reg closes:</b> Wed, May 27 Β· 23:59 UTC</div>
76
+ <div>🎟️ <b>Credits:</b> Thu, May 28</div>
77
+ <div>πŸš€ <b>Hack opens:</b> Fri, May 29</div>
78
+ <div>🏁 <b>Submit by:</b> Mon, June 8</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  </div>
80
+ <div class="bsh-warn">β›” No registrations accepted once the event starts. Lock it in before May 27!</div>
81
+ </div>
82
+ <div class="bsh-counter">
83
+ <div class="bsh-counter-title">πŸ•οΈ Hack opens in</div>
84
+ <div class="bsh-counter-target">May 29, 2026 Β· 00:00 UTC</div>
85
+ <div class="bsh-nums">
86
+ <div class="bsh-unit"><span class="bsh-num" id="bsh-days">--</span><span class="bsh-lbl">Days</span></div>
87
+ <div class="bsh-unit"><span class="bsh-num" id="bsh-hours">--</span><span class="bsh-lbl">Hrs</span></div>
88
+ <div class="bsh-unit"><span class="bsh-num" id="bsh-mins">--</span><span class="bsh-lbl">Min</span></div>
89
+ <div class="bsh-unit"><span class="bsh-num" id="bsh-secs">--</span><span class="bsh-lbl">Sec</span></div>
90
  </div>
 
 
 
 
 
 
 
 
 
 
 
91
  </div>
92
  </div>
93
  """
94
 
95
+ DISCORD_RIBBON_HTML = f"""
96
+ <div class="bsh-discord">
97
+ πŸ’¬ Join the <a href="{DISCORD_INVITE}" target="_blank">Gradio Discord</a> Β· channel <code>{DISCORD_CHANNEL}</code> Β· office hours, AMAs, and support.
98
+ </div>
99
+ """
100
+
101
+ COUNTDOWN_JS = """
102
+ () => {
103
+ const targetDate = new Date(Date.UTC(2026, 4, 29, 0, 0, 0));
104
+ function update() {
105
+ const now = new Date();
106
+ const diff = targetDate - now;
107
+ let d, h, m, s;
108
+ if (diff <= 0) {
109
+ d = h = m = s = 0;
110
+ } else {
111
+ d = Math.floor(diff / 86400000);
112
+ h = Math.floor((diff % 86400000) / 3600000);
113
+ m = Math.floor((diff % 3600000) / 60000);
114
+ s = Math.floor((diff % 60000) / 1000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  }
116
+ const set = (id, v) => {
117
+ const el = document.getElementById(id);
118
+ if (el) el.textContent = String(v).padStart(2, '0');
119
+ };
120
+ set('bsh-days', d);
121
+ set('bsh-hours', h);
122
+ set('bsh-mins', m);
123
+ set('bsh-secs', s);
124
+ }
125
+ update();
126
+ setInterval(update, 1000);
127
+ }
128
  """
129
 
130
 
 
276
  if isinstance(prev, str):
277
  prev = prev.strip("[]'\"").replace("'", "")
278
 
279
+ quests = registration['bonus_quests'] if 'bonus_quests' in registration.index else ''
280
  if isinstance(quests, str):
281
  quests = quests.strip("[]'\"").replace("'", "")
282
  quests_str = quests if quests else "_None selected_"
 
312
  - 🎟️ API & compute credits will be assigned on **Thu, May 28, 2026**
313
  - πŸš€ Hack window opens **Fri, May 29, 2026**
314
  - 🏁 Submissions due **Mon, June 8, 2026**
315
+ - πŸ’¬ Join the Gradio Discord channel `{DISCORD_CHANNEL}`: {DISCORD_INVITE}
316
  - πŸ“§ Watch your email for important updates
317
  """
318
  logger.info(f"Verification successful for {email}")
 
384
 
385
  Thank you, **{full_name}**! Your spot is locked in.
386
 
387
+ 🎟️ Credits assigned **Thu, May 28** Β· πŸš€ Hack opens **Fri, May 29** Β· 🏁 Submissions due **Mon, Jun 8**.<br>
388
+ πŸ’¬ Join the Gradio Discord channel `{DISCORD_CHANNEL}`: {DISCORD_INVITE}<br>
 
389
  πŸ“§ Watch your email for credits and updates.
390
 
391
  **See you in the woods! πŸ„πŸͺ΅**"""
 
416
 
417
  custom_css = """
418
  .gradio-container {
419
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
420
+ /* Brand color tokens β€” light mode defaults */
421
+ --bsh-card-bg: #fbf6e8;
422
+ --bsh-card-border: rgba(139, 111, 71, 0.30);
423
+ --bsh-text: #2a1d0a;
424
+ --bsh-text-soft: #6b4423;
425
+ --bsh-accent: #4a7c2e;
426
+ --bsh-accent-deep: #2d5016;
427
+ --bsh-banner-text: #f5ecd9;
428
+ --bsh-warn: #8b2e25;
429
+ --bsh-warn-bg: rgba(178, 60, 50, 0.10);
430
+ --bsh-warn-border: rgba(178, 60, 50, 0.40);
431
+ --bsh-counter-bg: linear-gradient(135deg, #2d5016 0%, #1f3a0f 100%);
432
+ --bsh-counter-num: #f5ecd9;
433
+ --bsh-counter-label: #c9b072;
434
+ --bsh-banner-bg: linear-gradient(135deg, #2d5016 0%, #4a7c2e 50%, #6b9039 100%);
435
+ --bsh-discord-bg: rgba(74, 124, 46, 0.08);
436
+ --bsh-link: #4a7c2e;
437
+ }
438
+ .dark .gradio-container,
439
+ body.dark .gradio-container,
440
+ .gradio-container.dark {
441
+ /* Brand color tokens β€” dark mode overrides */
442
+ --bsh-card-bg: #1f1a12;
443
+ --bsh-card-border: rgba(201, 176, 114, 0.35);
444
+ --bsh-text: #ede1c3;
445
+ --bsh-text-soft: #c9b072;
446
+ --bsh-accent: #9bc466;
447
+ --bsh-accent-deep: #6b9039;
448
+ --bsh-banner-text: #f5ecd9;
449
+ --bsh-warn: #ff9b8e;
450
+ --bsh-warn-bg: rgba(255, 122, 110, 0.12);
451
+ --bsh-warn-border: rgba(255, 122, 110, 0.40);
452
+ --bsh-counter-bg: linear-gradient(135deg, #1a2e0d 0%, #0c1606 100%);
453
+ --bsh-counter-num: #f5ecd9;
454
+ --bsh-counter-label: #c9b072;
455
+ --bsh-banner-bg: linear-gradient(135deg, #1a2e0d 0%, #2d5016 60%, #4a7c2e 100%);
456
+ --bsh-discord-bg: rgba(155, 196, 102, 0.08);
457
+ --bsh-link: #9bc466;
458
+ }
459
+
460
+ /* Banner */
461
+ .bsh-banner {
462
+ background: var(--bsh-banner-bg);
463
+ color: var(--bsh-banner-text);
464
+ border-radius: 14px;
465
+ padding: 20px 22px;
466
+ margin: 0 0 12px 0;
467
+ text-align: center;
468
+ border: 1px solid var(--bsh-card-border);
469
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
470
+ }
471
+ .bsh-banner h1 {
472
+ margin: 0 0 4px 0 !important;
473
+ font-size: 28px !important;
474
+ font-weight: 800 !important;
475
+ letter-spacing: -0.5px !important;
476
+ color: var(--bsh-banner-text) !important;
477
+ line-height: 1.15 !important;
478
+ }
479
+ .bsh-banner .tagline {
480
+ font-size: 16px;
481
+ font-style: italic;
482
+ opacity: 0.92;
483
+ margin-bottom: 4px;
484
+ }
485
+ .bsh-banner .meta {
486
+ font-size: 14px;
487
+ opacity: 0.85;
488
+ }
489
+ .bsh-banner .placeholder {
490
+ margin-top: 12px;
491
+ display: inline-block;
492
+ background: rgba(245, 236, 217, 0.12);
493
+ border: 1px dashed rgba(245, 236, 217, 0.40);
494
+ border-radius: 6px;
495
+ padding: 4px 12px;
496
+ font-size: 11px;
497
+ opacity: 0.80;
498
+ letter-spacing: 0.3px;
499
+ }
500
+
501
+ /* Three-card info row */
502
+ .bsh-info-row {
503
+ display: grid;
504
+ grid-template-columns: 1fr 1fr 1fr;
505
+ gap: 10px;
506
+ margin-bottom: 12px;
507
+ }
508
+ .bsh-card {
509
+ background: var(--bsh-card-bg);
510
+ border: 1px solid var(--bsh-card-border);
511
+ border-radius: 10px;
512
+ padding: 12px 14px;
513
+ color: var(--bsh-text);
514
  }
515
+ .bsh-title {
516
+ color: var(--bsh-text-soft);
517
+ font-size: 11px;
518
+ font-weight: 800;
519
+ letter-spacing: 1.5px;
520
+ text-transform: uppercase;
521
+ margin-bottom: 8px;
522
+ }
523
+ .bsh-content {
524
+ font-size: 13.5px;
525
+ line-height: 1.55;
526
+ color: var(--bsh-text);
527
+ }
528
+ .bsh-track {
529
+ display: flex;
530
+ align-items: baseline;
531
+ gap: 8px;
532
+ margin-top: 4px;
533
+ }
534
+ .bsh-emoji { font-size: 16px; line-height: 1; }
535
+ .bsh-track-name {
536
+ font-weight: 700;
537
+ color: var(--bsh-accent);
538
+ font-size: 13.5px;
539
+ }
540
+ .bsh-track-desc {
541
+ font-size: 12px;
542
+ opacity: 0.82;
543
+ color: var(--bsh-text);
544
+ padding-left: 24px;
545
+ margin-bottom: 4px;
546
+ line-height: 1.4;
547
+ }
548
+ .bsh-rules {
549
+ margin: 0 !important;
550
+ padding-left: 18px !important;
551
+ color: var(--bsh-text);
552
+ }
553
+ .bsh-rules li {
554
+ font-size: 13.5px;
555
+ line-height: 1.7;
556
+ color: var(--bsh-text);
557
+ }
558
+ .bsh-soon {
559
+ font-size: 13px;
560
+ line-height: 1.55;
561
+ color: var(--bsh-text);
562
+ opacity: 0.92;
563
+ }
564
+ .bsh-link {
565
+ margin-top: 6px;
566
+ font-size: 12px;
567
+ }
568
+ .bsh-link a {
569
+ color: var(--bsh-link);
570
+ font-weight: 600;
571
+ text-decoration: underline;
572
+ }
573
+
574
+ /* Dates + countdown row */
575
+ .bsh-dates-row {
576
+ display: grid;
577
+ grid-template-columns: 1.6fr 1fr;
578
+ gap: 10px;
579
+ margin-bottom: 14px;
580
+ }
581
+ .bsh-dates {
582
+ background: var(--bsh-card-bg);
583
+ border: 1px solid var(--bsh-card-border);
584
+ border-radius: 10px;
585
+ padding: 12px 14px;
586
+ color: var(--bsh-text);
587
+ }
588
+ .bsh-dates-grid {
589
+ display: grid;
590
+ grid-template-columns: 1fr 1fr;
591
+ gap: 6px 14px;
592
+ font-size: 13px;
593
+ color: var(--bsh-text);
594
+ }
595
+ .bsh-dates-grid b { color: var(--bsh-accent); font-weight: 700; }
596
+ .bsh-warn {
597
+ margin-top: 10px;
598
+ background: var(--bsh-warn-bg);
599
+ border: 1px solid var(--bsh-warn-border);
600
+ border-radius: 6px;
601
+ padding: 6px 10px;
602
+ color: var(--bsh-warn);
603
+ font-size: 12px;
604
+ font-weight: 600;
605
+ text-align: center;
606
+ }
607
+ .bsh-counter {
608
+ background: var(--bsh-counter-bg);
609
+ border: 1px solid var(--bsh-card-border);
610
+ border-radius: 10px;
611
+ padding: 12px 14px;
612
+ color: var(--bsh-counter-num);
613
+ text-align: center;
614
+ display: flex;
615
+ flex-direction: column;
616
+ justify-content: center;
617
+ }
618
+ .bsh-counter-title {
619
+ color: var(--bsh-counter-num);
620
+ font-size: 11px;
621
+ letter-spacing: 1.5px;
622
+ font-weight: 800;
623
+ text-transform: uppercase;
624
+ margin-bottom: 2px;
625
+ }
626
+ .bsh-counter-target {
627
+ color: var(--bsh-counter-label);
628
+ font-size: 11px;
629
+ font-style: italic;
630
+ margin-bottom: 8px;
631
+ opacity: 0.85;
632
+ }
633
+ .bsh-nums {
634
+ display: grid;
635
+ grid-template-columns: 1fr 1fr 1fr 1fr;
636
+ gap: 4px;
637
+ }
638
+ .bsh-unit {
639
+ display: flex;
640
+ flex-direction: column;
641
+ align-items: center;
642
+ }
643
+ .bsh-num {
644
+ font-family: 'Courier New', monospace;
645
+ font-size: 22px;
646
+ font-weight: 700;
647
+ color: var(--bsh-counter-num);
648
+ line-height: 1;
649
+ }
650
+ .bsh-lbl {
651
+ font-size: 9px;
652
+ letter-spacing: 1px;
653
+ color: var(--bsh-counter-label);
654
+ margin-top: 4px;
655
+ text-transform: uppercase;
656
+ }
657
+
658
+ /* Discord ribbon */
659
+ .bsh-discord {
660
+ margin-top: 14px;
661
+ background: var(--bsh-discord-bg);
662
+ border: 1px solid var(--bsh-card-border);
663
+ border-radius: 8px;
664
+ padding: 10px 14px;
665
+ text-align: center;
666
+ color: var(--bsh-text);
667
+ font-size: 13px;
668
+ }
669
+ .bsh-discord a {
670
+ color: var(--bsh-link);
671
+ font-weight: 700;
672
+ text-decoration: underline;
673
+ }
674
+ .bsh-discord code {
675
+ background: var(--bsh-discord-bg);
676
+ border: 1px solid var(--bsh-card-border);
677
+ padding: 1px 6px;
678
+ border-radius: 4px;
679
+ font-size: 11.5px;
680
+ color: var(--bsh-text);
681
+ }
682
+
683
+ /* Buttons */
684
  #submit-btn {
685
  background: linear-gradient(135deg, #4a7c2e 0%, #2d5016 100%) !important;
686
+ border: 1px solid #6b4423 !important;
687
  color: #f5ecd9 !important;
688
  font-weight: 700 !important;
689
+ font-size: 16px !important;
690
+ padding: 12px 24px !important;
691
+ border-radius: 10px !important;
692
+ box-shadow: 0 3px 10px rgba(74, 49, 16, 0.18) !important;
693
  transition: all 0.25s ease !important;
694
  }
695
  #submit-btn:hover {
696
+ transform: translateY(-1px) !important;
697
+ box-shadow: 0 5px 14px rgba(74, 49, 16, 0.28) !important;
698
  background: linear-gradient(135deg, #5a8c3e 0%, #3d6020 100%) !important;
699
  }
 
 
 
700
  #verify-btn {
701
  background: #6b4423 !important;
702
+ border: 1px solid #c9b072 !important;
703
  color: #f5ecd9 !important;
704
  font-weight: 700 !important;
705
+ font-size: 14px !important;
706
+ padding: 10px 20px !important;
707
  border-radius: 8px !important;
 
708
  transition: all 0.25s ease !important;
709
  }
710
  #verify-btn:hover {
711
+ transform: translateY(-1px) !important;
 
712
  background: #7d5430 !important;
713
  }
714
+
715
+ /* Responsive */
716
+ @media (max-width: 760px) {
717
+ .bsh-info-row { grid-template-columns: 1fr; }
718
+ .bsh-dates-row { grid-template-columns: 1fr; }
719
+ .bsh-banner h1 { font-size: 24px !important; }
720
+ }
721
  """
722
 
723
 
 
728
  ) as demo:
729
 
730
  gr.HTML(HEADER_HTML)
731
+ gr.HTML(INFO_ROW_HTML)
732
+ gr.HTML(DATES_ROW_HTML)
 
 
 
 
 
 
733
 
734
  with gr.Tabs():
735
  with gr.Tab("πŸ“ Register"):
736
  with gr.Row():
737
  with gr.Column():
738
+ gr.Markdown("### ❋ 1. Personal Information")
739
  full_name = gr.Textbox(
740
  label="Full Name *",
741
  placeholder="Your full name as you'd like it on certificates",
 
743
  )
744
  email = gr.Textbox(
745
  label="Email Address *",
746
+ placeholder="Primary contact email β€” we'll send updates and credits info here",
747
  max_lines=1,
748
  )
749
  hf_username = gr.Textbox(
 
764
  )
765
 
766
  with gr.Column():
767
+ gr.Markdown("### ❋ 2. Hackathon Participation")
768
  track_interest = gr.Radio(
769
  label="Which track interests you most? *",
770
  choices=[
 
811
 
812
  with gr.Row():
813
  with gr.Column():
814
+ gr.Markdown("### ❋ 3. Build Small Specifics")
815
  planned_small_model = gr.Textbox(
816
  label="Which small model are you planning to use? (optional)",
817
  placeholder="e.g. Llama-3.2-3B, Qwen2.5-7B, gemma-2-2b-it, SmolLM-1.7B...",
 
828
  "πŸ“‘ Sharing is Caring β€” share an agent trace",
829
  "πŸ““ Field Notes β€” write a blog post / report",
830
  ],
831
+ info="Pick as many as you'd like. Just signal for us β€” you can change your mind during the event.",
832
  )
833
 
834
  with gr.Column():
835
+ gr.Markdown("### ❋ 4. Project Idea (optional)")
836
  project_description = gr.Textbox(
837
  label="What are you most excited to build?",
838
  placeholder="A neighbor's recipe-translator? A whimsical mushroom-identifier? Tell us in a sentence or two.",
839
  lines=4,
840
  )
841
 
842
+ gr.Markdown("### ❋ 5. Acknowledgment")
843
  acknowledgment = gr.Checkbox(
844
  label="I'm in. *",
845
  info=(
 
900
 
901
  with gr.Tab("πŸ” Verify Registration"):
902
  gr.Markdown("""
903
+ ### Check Your Registration Status
904
+ Enter your email address and Hugging Face username to verify your registration and view your details. Both must match exactly (case-insensitive) for security purposes.
 
 
 
905
  """)
906
  with gr.Row():
907
  with gr.Column():
 
922
  elem_id="verify-btn",
923
  )
924
  with gr.Column():
925
+ gr.Markdown(f"""
926
+ **Need Help?**
927
+ - Use the **exact** email and username you registered with
928
+ - Both fields are case-insensitive but must match
929
+ - Registration is open until **Wed, May 27, 2026 Β· 23:59 UTC** β€” once it closes, no new entries can be added
 
 
930
 
931
  **Support:**
932
+ - Discord: [{DISCORD_INVITE}]({DISCORD_INVITE}) (channel `{DISCORD_CHANNEL}`)
933
  - Email: gradio-team@huggingface.co
934
  """)
935
  verify_output = gr.Markdown()
 
939
  outputs=verify_output,
940
  )
941
 
942
+ gr.HTML(DISCORD_RIBBON_HTML)
943
+
944
+ gr.Markdown(f"""
945
+ <div style="text-align: center; font-size: 12px; opacity: 0.75; margin-top: 8px;">
946
+ ✦ Questions? Email gradio-team@huggingface.co ✦
947
+ </div>
948
  """)
949
 
950
+ # Hook up the countdown JS β€” runs once on page load, then ticks every second
951
+ demo.load(fn=lambda: None, inputs=None, outputs=None, js=COUNTDOWN_JS)
952
+
953
 
954
  if __name__ == "__main__":
955
  demo.launch(allowed_paths=["."])