| """ICML 2026 Open Reproductions β Certificate Generator |
| ======================================================= |
| 1. Sign in with Hugging Face (OAuth). |
| 2. Eligibility is checked against the frozen challenge verdicts: every |
| participant with at least one claim judged `verified` qualifies |
| (baked into eligible.json at challenge close β 267 participants). |
| 3. The display name is editable; the certificate renders (HTML -> PNG via the |
| shared renderer Space) with the participant's verified-claim stats. |
| """ |
|
|
| import inspect |
| import json |
| import os |
| import tempfile |
| import urllib.parse |
|
|
| import gradio as gr |
| from gradio_client import Client, handle_file |
|
|
| RENDERER_SPACE = "https://ysharma-hackathon-certificate-html-to-image.hf.space/" |
| DISCUSSIONS_URL = "https://huggingface.co/spaces/ICML-2026-agent-repro/challenge/discussions" |
|
|
| _HERE = os.path.dirname(__file__) |
| with open(os.path.join(_HERE, "certificate_template.html"), encoding="utf-8") as f: |
| TEMPLATE = f.read() |
| with open(os.path.join(_HERE, "eligible.json"), encoding="utf-8") as f: |
| ELIGIBLE = json.load(f) |
|
|
| _client = None |
|
|
|
|
| def get_renderer(): |
| global _client |
| if _client is None: |
| params = inspect.signature(Client.__init__).parameters |
| kwargs = {} |
| token = os.getenv("HF_TOKEN") |
| if token: |
| kwargs["hf_token" if "hf_token" in params else "token"] = token |
| _client = Client(RENDERER_SPACE, **kwargs) |
| return _client |
|
|
|
|
| def plural(n, word): |
| return f"{n} {word}" + ("" if n == 1 else "s") |
|
|
|
|
| def stats_line(rec): |
| return (f"{plural(rec['verified_claims'], 'claim')} verified across " |
| f"{plural(rec['verified_papers'], 'paper')}") |
|
|
|
|
| def on_load(profile: gr.OAuthProfile | None): |
| if profile is None: |
| return (gr.update(visible=False), gr.update(visible=False), |
| "### π Sign in with Hugging Face to check your eligibility.", "") |
| rec = ELIGIBLE.get(profile.username.lower()) |
| if rec is None: |
| return (gr.update(visible=False), gr.update(visible=True), |
| f"### Sorry @{profile.username} β no verified logbook found.\n" |
| "Certificates go to participants with at least one claim judged " |
| "**verified** by the Logbook Judge before the Aug 2 deadline. " |
| f"If you believe this is an error, please open a thread in the " |
| f"[challenge discussions]({DISCUSSIONS_URL}).", "") |
| return (gr.update(visible=True), gr.update(visible=False), |
| f"### π Congratulations @{profile.username} β you qualify!\n" |
| f"Your record: **{stats_line(rec)}** ({plural(rec['logbooks'], 'logbook')} judged). " |
| "Adjust how your name should appear, then generate your certificate.", |
| profile.name or profile.username) |
|
|
|
|
| def linkedin_url(name): |
| p = { |
| "startTask": "CERTIFICATION_NAME", |
| "name": "ICML 2026 Open Reproductions β Certificate of Participation", |
| "organizationName": "Hugging Face", |
| "issueYear": "2026", "issueMonth": "8", |
| "certUrl": "https://huggingface.co/spaces/ICML-2026-agent-repro/certificate-generator", |
| } |
| return "https://www.linkedin.com/profile/add?" + urllib.parse.urlencode(p) |
|
|
|
|
| def create_certificate(display_name, profile: gr.OAuthProfile | None): |
| if profile is None: |
| return None, "β Please sign in first.", gr.update(visible=False) |
| rec = ELIGIBLE.get(profile.username.lower()) |
| if rec is None: |
| return None, "β No verified logbook found for your account.", gr.update(visible=False) |
| name = (display_name or "").strip() or profile.name or profile.username |
| html = TEMPLATE.replace("{participant_name}", name).replace("{stats_line}", stats_line(rec)) |
| with tempfile.NamedTemporaryFile("w", delete=False, suffix=".html", encoding="utf-8") as f: |
| f.write(html) |
| path = f.name |
| try: |
| image_path = get_renderer().predict(html_file=handle_file(path), api_name="/predict")[0] |
| except Exception as e: |
| return None, f"β Rendering failed: {e}. Please try again in a minute.", gr.update(visible=False) |
| btn = (f'<a href="{linkedin_url(name)}" target="_blank" ' |
| f'style="display:inline-block;background:#0a66c2;color:#fff;font-weight:700;' |
| f'padding:10px 22px;border-radius:8px;text-decoration:none">Add to LinkedIn profile β</a>') |
| return image_path, "π Your certificate is ready β download it below.", gr.update(value=btn, visible=True) |
|
|
|
|
| THEME = gr.themes.Base( |
| primary_hue=gr.themes.colors.orange, |
| neutral_hue=gr.themes.colors.stone, |
| ) |
|
|
| CSS = """ |
| .gradio-container { |
| background-color: #fdfcf9 !important; |
| background-image: |
| linear-gradient(rgba(31,41,55,.045) 1px, transparent 1px), |
| linear-gradient(90deg, rgba(31,41,55,.045) 1px, transparent 1px); |
| background-size: 26px 26px; |
| } |
| #hero h1 { font-family: ui-serif, "Iowan Old Style", Georgia, serif; } |
| """ |
|
|
| with gr.Blocks(title="ICML 2026 Open Reproductions β Certificates", theme=THEME, css=CSS) as demo: |
| gr.Markdown("# π ICML 2026 Open Reproductions β Certificate of Participation", elem_id="hero") |
| gr.Markdown( |
| "Every participant with **at least one claim judged `verified`** in the challenge " |
| "(July 15 β August 2, 2026) can generate their certificate here." |
| ) |
| login = gr.LoginButton() |
| status = gr.Markdown() |
| with gr.Column(visible=False) as main_box: |
| name_box = gr.Textbox(label="Name on the certificate") |
| gen_btn = gr.Button("Generate my certificate π", variant="primary") |
| cert_image = gr.Image(label="Your certificate", type="filepath", interactive=False) |
| note = gr.Markdown() |
| linkedin = gr.HTML(visible=False) |
| with gr.Column(visible=False) as contact_box: |
| pass |
|
|
| demo.load(on_load, inputs=None, outputs=[main_box, contact_box, status, name_box]) |
| gen_btn.click(create_certificate, inputs=[name_box], outputs=[cert_image, note, linkedin]) |
|
|
| demo.launch() |
|
|