"""Nalandadata — contact / data-licensing lead form. A Gradio Space that captures licensing enquiries and appends each one as a row to the PRIVATE Nalandadata/leads dataset. Auth: reads a write-scoped token from the Space secret HF_WRITE_TOKEN. """ import os import io import csv import datetime import gradio as gr from huggingface_hub import HfApi, hf_hub_download LEADS_REPO = "Nalandadata/leads" LEADS_FILE = "leads.csv" TOKEN = os.environ.get("HF_WRITE_TOKEN") # set as a Space secret SITE = "https://nalandadata.ai/?utm_source=huggingface&utm_medium=contact_space&utm_campaign=lead_form" DATASETS = [ "NalandaJEENEETBench", "nalanda-image-qa", "DrishtiTable", "Other / custom data", ] COLUMNS = ["timestamp", "name", "email", "organization", "role", "use_case", "datasets_of_interest", "message", "source"] api = HfApi(token=TOKEN) def _valid_email(e): return isinstance(e, str) and "@" in e and "." in e.split("@")[-1] and len(e) >= 6 def submit(name, email, organization, role, use_case, datasets, message): if not name or not name.strip(): return gr.update(value="⚠️ Please enter your name.", visible=True) if not _valid_email(email): return gr.update(value="⚠️ Please enter a valid work email.", visible=True) if not organization or not organization.strip(): return gr.update(value="⚠️ Please enter your organization.", visible=True) if not TOKEN: return gr.update( value="⚠️ The form is not yet configured (missing write token). " "Please email info@nalandadata.ai directly.", visible=True) row = { "timestamp": datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds"), "name": name.strip(), "email": email.strip(), "organization": organization.strip(), "role": (role or "").strip(), "use_case": (use_case or "").strip(), "datasets_of_interest": "|".join(datasets or []), "message": (message or "").strip().replace("\r", " ").replace("\n", " "), "source": "contact-space", } try: # download current leads.csv, append, re-upload try: path = hf_hub_download(LEADS_REPO, LEADS_FILE, repo_type="dataset", token=TOKEN) with open(path, encoding="utf-8") as f: existing = f.read() except Exception: existing = ",".join(COLUMNS) + "\n" buf = io.StringIO() buf.write(existing if existing.endswith("\n") else existing + "\n") w = csv.writer(buf) w.writerow([row[c] for c in COLUMNS]) data = buf.getvalue().encode("utf-8") api.upload_file( path_or_fileobj=data, path_in_repo=LEADS_FILE, repo_id=LEADS_REPO, repo_type="dataset", commit_message=f"New lead: {row['organization']} ({row['timestamp']})", ) except Exception as e: return gr.update( value=f"⚠️ Couldn't record your enquiry automatically ({type(e).__name__}). " f"Please email info@nalandadata.ai and we'll respond quickly.", visible=True) return gr.update( value=(f"✅ **Thank you, {row['name']}!** Your enquiry has been received.\n\n" f"We'll reply to **{row['email']}** shortly. " f"In the meantime, explore more at [nalandadata.ai]({SITE})."), visible=True) # Theme aligned to Nalandadata/nalanda-live-demos (dark + gold) THEME_CSS = """ :root{ --bg:#0c0c0e; --panel:#141417; --panel2:#1b1b20; --line:#2a2a31; --ink:#ece7da; --sub:#9d958a; --gold:#d8b65a; --gold2:#f0d488; --ok:#7bd88f; --err:#e08a8a; } .gradio-container, .gradio-container *{ font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif !important; -webkit-font-smoothing:antialiased; } .gradio-container{ max-width:860px !important; margin:0 auto !important; background:radial-gradient(1200px 600px at 50% -10%, #16161b 0%, var(--bg) 60%) !important; color:var(--ink) !important; } /* surrounding chrome */ body, gradio-app{ background:var(--bg) !important; } #nd-hero{ text-align:center; padding:34px 16px 6px; } #nd-hero .brand{ font-size:13px; letter-spacing:.32em; text-transform:uppercase; color:var(--gold); font-weight:600; } #nd-hero h1{ font-size:30px; font-weight:700; letter-spacing:-.01em; margin:8px 0 6px; color:var(--ink); } #nd-hero p{ color:var(--sub); font-size:14.5px; line-height:1.55; max-width:560px; margin:0 auto; } /* form card */ .gradio-container .block, .gradio-container .form{ background:var(--panel) !important; border:1px solid var(--line) !important; border-radius:14px !important; } .gradio-container label span, .gradio-container .gr-box label span{ color:var(--sub) !important; font-weight:600 !important; font-size:13px !important; } .gradio-container input[type=text], .gradio-container textarea, .gradio-container input:not([type=checkbox]){ background:var(--panel2) !important; border:1px solid var(--line) !important; color:var(--ink) !important; border-radius:10px !important; font-size:15px !important; } .gradio-container input:focus, .gradio-container textarea:focus{ outline:none !important; border-color:var(--gold) !important; box-shadow:none !important; } /* checkboxes */ .gradio-container .gr-check-radio, .gradio-container [data-testid="checkbox-group"] label{ color:var(--ink) !important; } .gradio-container input[type=checkbox]:checked{ accent-color:var(--gold) !important; } /* primary button -> gold gradient */ .gradio-container button.primary, .gradio-container .primary{ background:linear-gradient(180deg,var(--gold2),var(--gold)) !important; color:#1a1407 !important; border:none !important; font-weight:700 !important; border-radius:10px !important; } .gradio-container button.primary:hover{ filter:brightness(1.05); } /* result markdown */ #nd-result, #nd-result *{ color:var(--ink) !important; } #nd-result a{ color:var(--gold) !important; } #nd-footer{ text-align:center; margin-top:18px; font-size:12.5px; color:var(--sub); } #nd-footer a{ color:var(--gold); text-decoration:none; font-weight:500; } #nd-footer a:hover{ text-decoration:underline; } """ INTRO = """
Nalandadata

Work with us

We license verified, curriculum-aligned Indian STEM data for AI training, post-training, and evaluation — JEE/NEET reasoning, scientific multimodal QA, and annotated document tables. Tell us what you're building and we'll get back to you with access and licensing options.

""" with gr.Blocks(title="Contact Nalandadata", css=THEME_CSS, theme=gr.themes.Base( primary_hue="yellow", secondary_hue="stone", neutral_hue="stone", font=["-apple-system", "BlinkMacSystemFont", "Segoe UI", "sans-serif"], )) as demo: gr.HTML(INTRO) with gr.Row(): with gr.Column(): name = gr.Textbox(label="Name *", placeholder="Your full name") email = gr.Textbox(label="Work email *", placeholder="you@company.com") organization = gr.Textbox(label="Organization *", placeholder="Company / institution") role = gr.Textbox(label="Role (optional)", placeholder="e.g. ML Lead, Researcher") with gr.Column(): datasets = gr.CheckboxGroup(DATASETS, label="Datasets of interest") use_case = gr.Textbox(label="Use case", placeholder="How do you plan to use the data/models?") message = gr.Textbox(label="Message", lines=3, placeholder="Anything else we should know?") submit_btn = gr.Button("Send enquiry", variant="primary") result = gr.Markdown(visible=False, elem_id="nd-result") submit_btn.click( submit, inputs=[name, email, organization, role, use_case, datasets, message], outputs=result, ) gr.HTML( f'' ) if __name__ == "__main__": demo.launch()