1<!doctype html> 2<html lang="en"> 3<head> 4 <meta charset="utf-8" /> 5
5<script>(function(){try{var h=location.hostname;if(h==="worldcup.dashmote.com"||h==="wc26party.com"||h==="www.wc26party.com"||h==="dashmote-worldcup.web.app"){location.replace("https://watchpartyradar.com"+location.pathname+location.search+location.hash);}}catch(e){}})();</script>
5 6 <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 <title>Submit a Watch Party | World Cup Watch Party Radar</title> 8 <meta name="description" content="Know a bar, pub or fan zone showing the 2026 World Cup? Submit it to the World Cup Watch Party Radar and help fans find it." /> 9 <meta name="robots" content="noindex, follow" /> 10 <link rel="canonical" href="https://watchpartyradar.com/submit/" /> 11 <link rel="icon" type="image/png" href="/icon.png" sizes="any" /> 12 <link rel="apple-touch-icon" href="/apple-touch-icon.png" /> 13 <link rel="preconnect" href="https://fonts.googleapis.com" /> 14 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> 15 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@600;700&display=swap" rel="stylesheet" /> 16 <style> 17 :root { --navy:#040433; --blue:#0e49b5; --muted:#747488; --border:#e8e8f0; --bg:#ffffff; --bg-soft:#f7f7fb; } 18 * { box-sizing:border-box; margin:0; padding:0; } 19 body { font-family:"Inter",system-ui,sans-serif; color:var(--navy); background:var(--bg); -webkit-font-smoothing:antialiased; } 20 .top { height:60px; display:flex; align-items:center; padding:0 1.1rem; border-bottom:1px solid var(--border); gap:.6rem; } 21 .wordmark { font-family:"Space Grotesk",sans-serif; font-weight:700; font-size:1.05rem; color:var(--navy); text-decoration:none; } 22 .wordmark span { color:var(--blue); } 23 .crumb { color:var(--muted); font-size:.85rem; } 24 main { max-width:640px; margin:0 auto; padding:1.6rem 1.1rem 4rem; } 25 h1 { font-family:"Space Grotesk",sans-serif; font-size:1.45rem; letter-spacing:-.02em; margin-bottom:.5rem; } 26 .lead { color:var(--muted); font-size:.95rem; line-height:1.55; margin-bottom:1.6rem; } 27 form { display:flex; flex-direction:column; gap:1rem; } 28 label { font-size:.8rem; font-weight:600; letter-spacing:.02em; display:block; margin-bottom:.3rem; } 29 label .req { color:var(--blue); } 30 input, textarea, select { 31 width:100%; font:inherit; font-size:.95rem; color:var(--navy); 32 padding:.65rem .8rem; border:1px solid var(--border); border-radius:10px; background:var(--bg); 33 } 34 input:focus, textarea:focus, select:focus { outline:2px solid var(--blue); outline-offset:1px; border-color:var(--blue); } 35 textarea { min-height:110px; resize:vertical; } 36 .hint { font-size:.76rem; color:var(--muted); margin-top:.3rem; line-height:1.4; } 37 .row2 { display:grid; grid-template-columns:1fr 1fr; gap:1rem; } 38 @media (max-width:520px){ .row2 { grid-template-columns:1fr; } } 39 button[type=submit] { 40 font-family:"Space Grotesk",sans-serif; font-weight:700; font-size:.95rem; color:#fff; 41 background:var(--blue); border:none; border-radius:10px; padding:.8rem 1.4rem; cursor:pointer; margin-top:.4rem; 42 } 43 button[type=submit]:hover { background:#0c3e9e; } 44 button[disabled] { opacity:.6; cursor:wait; } 45 .ok, .err { display:none; padding:1rem 1.1rem; border-radius:12px; font-size:.92rem; line-height:1.5; margin-top:1rem; } 46 .ok { background:#eef7f0; border:1px solid #bfe3c8; color:#11502a; } 47 .err { background:#fdf0ef; border:1px solid #f3c9c5; color:#7c2d26; } 48 .err a { color:var(--blue); } 49 .back { display:inline-block; margin-top:1.4rem; color:var(--blue); font-size:.88rem; text-decoration:none; } 50 .back:hover { text-decoration:underline; } 51 </style> 52</head> 53<body> 54 <header class="top"> 55 <a class="wordmark" href="/">Dashmote<span>.</span></a> 56 <span class="crumb">World Cup Watch Party Radar / Submit a watch party</span> 57 </header> 58 <main> 59 <h1>Submit a watch party</h1> 60 <p class="lead">Know a bar, pub, brewery or fan zone showing the 2026 World Cup that is not on the radar yet? 61 Tell us about it. We verify every submission against its source before it goes live, venues with a public 62 post or website announcement get listed fastest.</p> 63 64 <form id="f" novalidate> 65 <div> 66 <label for="venue">Venue name <span class="req">*</span></label> 67 <input id="venue" name="venue" required maxlength="180" placeholder="e.g. Cafe De Zon" /> 68 </div> 69 <div class="row2"> 70 <div> 71 <label for="city">City <span class="req">*</span></label> 72 <input id="city" name="city" required maxlength="90" placeholder="e.g. Amsterdam" /> 73 </div> 74 <div> 75 <label for="country">Country</label> 76 <input id="country" name="country" maxlength="60" placeholder="e.g. Netherlands" /> 77 </div> 78 </div> 79 <div> 80 <label for="address">Address or Google Maps link</label> 81 <input id="address" name="address" maxlength="300" placeholder="Street + number, or a maps.google.com link" /> 82 </div> 83 <div> 84 <label for="details">What is happening there?</label> 85 <textarea id="details" name="details" maxlength="1800" 86 placeholder="e.g. Shows every match on 4 big screens, beer garden, hosts an official fan zone for the group stage..."></textarea> 87 </div> 88 <div> 89 <label for="source_url">Source link <span class="req">*</span></label> 90 <input id="source_url" name="source_url" type="url" required maxlength="450" placeholder="An Instagram post, Facebook event or website page announcing it" /> 91 <p class="hint">The public post or page that proves the venue is showing matches. This is what we verify.</p> 92 </div> 93 <div class="row2"> 94 <div> 95 <label for="photo_url">Photo link</label> 96 <input id="photo_url" name="photo_url" type="url" maxlength="450" pattern="https://.*" title="Photo links must start with https://" placeholder="A photo of the venue (optional)" /> 97 </div> 98 <div> 99 <label for="team">Team it supports</label> 100 <input id="team" name="team" maxlength="60" placeholder="e.g. Netherlands (optional)" /> 101 </div> 102 </div> 103 <div> 104 <label for="email">Your email</label> 105 <input id="email" name="email" type="email" maxlength="120" placeholder="Optional, in case we have a question" /> 106 </div> 107 <button type="submit" id="go">Submit watch party</button> 108 <p class="ok" id="busy" role="status" style="display:none">Submitting…</p> 109 <p class="ok" id="ok" role="status">Thank you! Your watch party was submitted. We verify every venue against its source, 110 if it checks out it will appear on the radar in the next refresh.</p> 111 <p class="err" id="err" role="alert">That did not go through. Please retry in a moment, or email it to 112 <a href="mailto:[email protected]?subject=World%20Cup%20watch%20party%20submission">[email protected]</a>.</p> 113 </form> 114 <a class="back" href="/">← Back to the radar</a> 115 </main> 116 117 <!-- Firebase App Check (reCAPTCHA Enterprise): mints an attestation token so 118 only real browsers can write to the submissions collection. The token is 119 attached to the Firestore REST POST below; spam bots hitting the endpoint 120 directly have no valid token and are rejected once enforcement is on. --> 121
121<script type="module"> 122 import { initializeApp } from "https://www.gstatic.com/firebasejs/10.13.2/firebase-app.js"; 123 import { initializeAppCheck, ReCaptchaEnterpriseProvider, getToken } 124 from "https://www.gstatic.com/firebasejs/10.13.2/firebase-app-check.js"; 125 try { 126 const app = initializeApp({ 127 apiKey: "AIzaSyBYtSoVor_xtodvsY8Cycpf8JpoVfksWcI", 128 projectId: "dashmote-worldcup", 129 appId: "1:414042519427:web:4329a82695908f405368b6" 130 }); 131 const appCheck = initializeAppCheck(app, { 132 provider: new ReCaptchaEnterpriseProvider("6LeyWRItAAAAAB3QTCi73yefH6RtXxiGKj890GMy"), 133 isTokenAutoRefreshEnabled: true 134 }); 135 window.__appCheckToken = async function () { 136 try { return (await getToken(appCheck, false)).token; } catch (e) { return null; } 137 }; 138 } catch (e) { /* SDK/load failure: fall through, submit without a token */ } 139 </script>
139 140 141
141<script> 142 (function () { 143 var ENDPOINT = "https://firestore.googleapis.com/v1/projects/dashmote-worldcup/databases/(default)/documents/submissions?key=AIzaSyBYtSoVor_xtodvsY8Cycpf8JpoVfksWcI"; 144 var f = document.getElementById("f"); 145 var ok = document.getElementById("ok"); 146 var err = document.getElementById("err"); 147 var go = document.getElementById("go"); 148 var busy = document.getElementById("busy"); 149 f.addEventListener("submit", function (e) { 150 e.preventDefault(); 151 ok.style.display = "none"; err.style.display = "none"; 152 if (!f.reportValidity()) return; 153 busy.style.display = "block"; 154 var val = function (id) { return (document.getElementById(id).value || "").trim(); }; 155 var fields = { 156 venue: { stringValue: val("venue") }, 157 city: { stringValue: val("city") }, 158 source_url: { stringValue: val("source_url") }, 159 ts: { stringValue: new Date().toISOString() }, 160 page: { stringValue: "submit-v1" } 161 }; 162 var opt = { details: "details", country: "country", address: "address", photo_url: "photo_url", team: "team", email: "email" }; 163 for (var k in opt) { var v = val(opt[k]); if (v) fields[k] = { stringValue: v }; } 164 go.disabled = true; go.setAttribute("aria-busy", "true"); f.setAttribute("aria-busy", "true"); 165 var done = function () { 166 go.disabled = false; go.removeAttribute("aria-busy"); f.removeAttribute("aria-busy"); 167 busy.style.display = "none"; 168 }; 169 // Get an App Check token first (best-effort), then POST with it attached. 170 var tokenP = window.__appCheckToken ? window.__appCheckToken() : Promise.resolve(null); 171 tokenP.then(function (token) { 172 var headers = { "Content-Type": "application/json" }; 173 if (token) headers["X-Firebase-AppCheck"] = token; 174 return fetch(ENDPOINT, { 175 method: "POST", 176 headers: headers, 177 body: JSON.stringify({ fields: fields }) 178 }); 179 }).then(function (r) { 180 done(); 181 if (r.ok) { ok.style.display = "block"; f.reset(); } 182 else { err.style.display = "block"; } 183 }).catch(function () { 184 done(); 185 err.style.display = "block"; 186 }); 187 }); 188 })(); 189 </script>
189 190</body> 191</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.