1<!DOCTYPE html><html lang="en"><head> 2 <meta charset="UTF-8"> 3 <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> 4 5 <!-- Static meta tags - always present for crawlers --> 6 <title>build_ | Protocol for startup cities</title> 7 <meta name="description" content="Join build_ - Connect with builders, discover projects, and collaborate in cities worldwide."> 8 <meta property="og:type" content="website"> 9 <meta property="og:url" content="https://buildcities.com"> 10
10<script>document.querySelector('meta[property="og:url"]').setAttribute('content', window.location.href);</script>
10 11 <meta property="og:title" content="build_ | Protocol for startup cities"> 12 <meta property="og:description" content="Join build_ - Connect with builders, discover projects, and collaborate in cities worldwide."> 13 <meta property="og:image" content="https://firebasestorage.googleapis.com/v0/b/buildcities-members-app.appspot.com/o/build-core-product%2Fbuild%204x.gif?alt=media&token=ee214a2b-a009-4aa0-9007-4cff2f073c47"> 14 <meta property="og:image:secure_url" content="https://firebasestorage.googleapis.com/v0/b/buildcities-members-app.appspot.com/o/build-core-product%2Fbuild%204x.gif?alt=media&token=ee214a2b-a009-4aa0-9007-4cff2f073c47"> 15 <meta property="og:image:width" content="1200"> 16 <meta property="og:image:height" content="630"> 17 <meta property="og:site_name" content="build_"> 18 <meta property="og:locale" content="en_US"> 19 <meta name="twitter:card" content="summary_large_image"> 20 <meta name="twitter:url" content="https://buildcities.com"> 21
21<script>document.querySelector('meta[name="twitter:url"]').setAttribute('content', window.location.href);</script>
21 22 <meta name="twitter:title" content="build_ | Protocol for startup cities"> 23 <meta name="twitter:description" content="Join build_ - Connect with builders, discover projects, and collaborate in cities worldwide."> 24 <meta name="twitter:image" content="https://firebasestorage.googleapis.com/v0/b/buildcities-members-app.appspot.com/o/build-core-product%2Fbuild%204x.gif?alt=media&token=ee214a2b-a009-4aa0-9007-4cff2f073c47"> 25 26
26<script> 27 (function() { 28 const path = window.location.pathname; 29 const baseUrl = window.location.origin; 30 const fullUrl = window.location.href; 31 const defaultImage = 'https://firebasestorage.googleapis.com/v0/b/buildcities-members-app.appspot.com/o/build-core-product%2Fbuild%204x.gif?alt=media&token=ee214a2b-a009-4aa0-9007-4cff2f073c47'; 32 const defaultTitle = 'build_ | Protocol for startup cities'; 33 const defaultDescription = 'Join build_ - Connect with builders, discover projects, and collaborate in cities worldwide.'; 34 35 // Update existing meta tag (tags already exist in HTML) 36 function updateMetaTag(property, content, isProperty) { 37 const tag = document.querySelector(isProperty ? 'meta[property="' + property + '"]' : 'meta[name="' + property + '"]'); 38 if (tag) tag.setAttribute('content', content); 39 } 40 41 // Event pages render the metadata image as their hero, and it is the LCP 42 // element. Preloading it from the head starts the download in parallel 43 // with the JS bundle instead of after the app renders and queries. 44 var preloadedHero = null; 45 function preloadHeroImage(url) { 46 if (!url || url === defaultImage || url === preloadedHero) return; 47 preloadedHero = url; 48 var link = document.createElement('link'); 49 link.rel = 'preload'; 50 link.as = 'image'; 51 link.href = url; 52 link.setAttribute('fetchpriority', 'high'); 53 document.head.appendChild(link); 54 } 55 56 function isEventPage(metaPath) { 57 return metaPath.indexOf('/event-calendar/') === 0; 58 } 59 60 // Update meta tags with fetched data 61 function updateMetaTags(data, fullUrl) { 62 const title = data?.title || 'build_'; 63 const description = data?.description || defaultDescription; 64 const image = data?.image || defaultImage; 65 const fullTitle = title.includes('|') ? title : title + ' | build_'; 66 67 document.title = fullTitle; 68 updateMetaTag('description', description, false); 69 updateMetaTag('og:url', fullUrl, true); 70 updateMetaTag('og:title', title, true); 71 updateMetaTag('og:description', description, true); 72 updateMetaTag('og:image', image, true); 73 updateMetaTag('og:image:secure_url', image, true); 74 updateMetaTag('twitter:url', fullUrl, false); 75 updateMetaTag('twitter:title', title, false); 76 updateMetaTag('twitter:description', description, false); 77 updateMetaTag('twitter:image', image, false); 78 } 79 80 // Set defaults immediately (use current page URL as default) 81 updateMetaTags({ title: defaultTitle, description: defaultDescription, image: defaultImage }, fullUrl); 82 83 function fetchMetadata(metaPath, metaUrl) { 84 var wantsHeroPreload = isEventPage(metaPath); 85 var params = 'path=' + encodeURIComponent(metaPath); 86 // Forward query params for video-call invite links (host, live, title for OG card) 87 if (metaPath === '/video-call') { 88 var sp = new URLSearchParams(window.location.search); 89 if (sp.get('host')) params += '&host=' + encodeURIComponent(sp.get('host')); 90 if (sp.get('live')) params += '&live=' + encodeURIComponent(sp.get('live')); 91 if (sp.get('title')) params += '&title=' + encodeURIComponent(sp.get('title')); 92 } 93 fetch(baseUrl + '/api/metadata?' + params) 94 .then(r => r.ok ? r.json() : null) 95 .then(data => { 96 if (!data || !data.title) return; 97 if (wantsHeroPreload) preloadHeroImage(data.image); 98 updateMetaTags(data, metaUrl); 99 }) 100 .catch(() => {}); 101 } 102 103 // On event pages this response feeds the hero image preload, so it is on 104 // the critical path. Elsewhere it only rewrites meta tags, so keep it on 105 // idle and out of the way of critical resources. 106 var scheduleIdle = window.requestIdleCallback || function(cb) { setTimeout(cb, 1); }; 107 if (isEventPage(path)) fetchMetadata(path, fullUrl); 108 scheduleIdle(function() { 109 if (!isEventPage(path)) fetchMetadata(path, fullUrl); 110 111 // Route changes 112 window.addEventListener('popstate', function() { 113 fetchMetadata(window.location.pathname, window.location.href); 114 }); 115 116 var origPush = history.pushState; 117 var origReplace = history.replaceState; 118 history.pushState = function() { origPush.apply(history, arguments); fetchMetadata(window.location.pathname, window.location.href); }; 119 history.replaceState = function() { origReplace.apply(history, arguments); fetchMetadata(window.location.pathname, window.location.href); }; 120 }); 121 })(); 122 </script>
122 123 124 <!-- Preconnect to image CDN origins for faster image loads --> 125 <link rel="preconnect" href="https://firebasestorage.googleapis.com"> 126 <link rel="preconnect" href="https://storage.googleapis.com"> 127 128 <!-- Google Fonts: preload to avoid render-blocking --> 129 <link rel="preconnect" href="https://fonts.googleapis.com"> 130 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 131 <link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&display=swap"> 132 <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&display=swap" media="print" onload="this.media='all'"> 133 <noscript> 134 <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&display=swap"> 135 </noscript> 136 137 <link rel="icon" type="image/svg" href="/favicon.svg"> 138
138<script type="module" crossorigin src="/assets/index-Cn8jK25t.js"></script>
138 139 <link rel="modulepreload" crossorigin href="/assets/vendor-shared-CkCIh-Sx.js"> 140 <link rel="modulepreload" crossorigin href="/assets/vendor-react-BoGG1wja.js"> 141 <link rel="modulepreload" crossorigin href="/assets/vendor-search-Bv9bACL5.js"> 142 <link rel="modulepreload" crossorigin href="/assets/vendor-ui-ClIxZ1gL.js"> 143 <link rel="modulepreload" crossorigin href="/assets/vendor-realtime-LfCGF1rg.js"> 144 <link rel="stylesheet" crossorigin href="/assets/index-CzvDOIWL.css"> 145 </head> 146 147 <body class="h-full bg-brandBackground"> 148 <div id="redwood-app"></div> 149 <!-- React app entry point - Vite handles this in both dev and production --> 150 </body> 151</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.