1<!doctype html> 2<html lang="en"> 3<head> 4 <!-- Vercel skips a build when the LAST commit does not touch web/ (ignored build step), so a web/ change merged under a docs commit never deploys; ship web/ changes as the tip commit. --> 5 <meta charset="utf-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 <title>truelike - the daily game for your true friends | daily question app for friend groups</title> 8 <link rel="canonical" href="https://truelike.com/" /> 9 <meta name="description" content="free iPhone + Android app: one question a day for your private friend circle. everyone answers, then it all reveals at once. no strangers, no public feed, 13+." /> 10 11 <!-- og + twitter cards. Shows nice preview when the link is pasted into iMessage / WhatsApp / DM. --> 12 <meta property="og:title" content="truelike - the daily game for your true friends" /> 13 <meta property="og:description" content="free iPhone + Android app: one question a day for your private friend circle. everyone answers, then it all reveals at once. no strangers, no public feed, 13+." /> 14 <meta property="og:type" content="website" /> 15 <meta property="og:image" content="https://truelike.com/og.png" /> 16 <meta property="og:url" content="https://truelike.com/" /> 17 <meta property="og:site_name" content="truelike" /> 18 <meta property="og:locale" content="en_US" /> 19 <meta property="og:image:width" content="1200" /> 20 <meta property="og:image:height" content="630" /> 21 <meta property="og:image:alt" content="truelike, the daily game for your true friends" /> 22 <meta name="twitter:card" content="summary_large_image" /> 23 <meta name="twitter:title" content="truelike - the daily game for your true friends" /> 24 <meta name="twitter:description" content="free iPhone + Android app: one question a day for your private friend circle. everyone answers, then it all reveals at once. no strangers, no public feed, 13+." /> 25 <meta name="twitter:image" content="https://truelike.com/og.png" /> 26 27 <!-- FAQPage structured data: must match the visible "questions people ask" section word for word. --> 28
28<script type="application/ld+json"> 29 { 30 "@context": "https://schema.org", 31 "@type": "FAQPage", 32 "mainEntity": [ 33 { 34 "@type": "Question", 35 "name": "what is truelike?", 36 "acceptedAnswer": { 37 "@type": "Answer", 38 "text": "truelike is a free app for you and your close friends. every day your private circle gets one question, everyone answers, and then all the answers are revealed together. it's the daily game for your true friends." 39 } 40 }, 41 { 42 "@type": "Question", 43 "name": "how does it work?", 44 "acceptedAnswer": { 45 "@type": "Answer", 46 "text": "start a circle and invite your friends, up to 12 people in all. one question drops each day and everyone answers on their own. answers stay hidden until the reveal, which takes at least 2 people, and then you all see them together." 47 } 48 }, 49 { 50 "@type": "Question", 51 "name": "is truelike free?", 52 "acceptedAnswer": { 53 "@type": "Answer", 54 "text": "yes. truelike is free on iPhone and Android, with no ads and no in-app purchases." 55 } 56 }, 57 { 58 "@type": "Question", 59 "name": "what ages is truelike for?", 60 "acceptedAnswer": { 61 "@type": "Answer", 62 "text": "truelike is for ages 13 and up. you need to be 13 or older to sign up." 63 } 64 }, 65 { 66 "@type": "Question", 67 "name": "do my friends need the app?", 68 "acceptedAnswer": { 69 "@type": "Answer", 70 "text": "no. a friend with your invite link can answer today's question in their browser, with no app and no account, and see the reveal there once 2 or more people have answered. the app is for answering every day and getting a notification when your circle reveals." 71 } 72 }, 73 { 74 "@type": "Question", 75 "name": "who can see my answers?", 76 "acceptedAnswer": { 77 "@type": "Answer", 78 "text": "only the people in your circle. there's no public feed, no followers and no strangers. anyone who opens your circle's invite link can join in, so keep it in your friend group." 79 } 80 }, 81 { 82 "@type": "Question", 83 "name": "what kinds of questions are there?", 84 "acceptedAnswer": { 85 "@type": "Answer", 86 "text": "rounds rotate between pick one, hot take, most likely to, two truths and a lie, guess who said it, and open questions you answer in your own words." 87 } 88 }, 89 { 90 "@type": "Question", 91 "name": "does it work on iPhone and Android?", 92 "acceptedAnswer": { 93 "@type": "Answer", 94 "text": "yes. get truelike free on the App Store for iPhone or on Google Play for Android." 95 } 96 } 97 ] 98 } 99 </script>
99 100 101 <!-- Entity data: Organization + WebSite + MobileApplication. No aggregateRating until there are real store ratings to cite. --> 102
102<script type="application/ld+json"> 103{ 104 "@context": "https://schema.org", 105 "@graph": [ 106 { 107 "@type": "Organization", 108 "@id": "https://truelike.com/#org", 109 "name": "truelike", 110 "url": "https://truelike.com/", 111 "logo": "https://truelike.com/og.png", 112 "sameAs": [ 113 "https://apps.apple.com/app/id6771850307", 114 "https://play.google.com/store/apps/details?id=com.truelike.app" 115 ] 116 }, 117 { 118 "@type": "WebSite", 119 "@id": "https://truelike.com/#website", 120 "name": "truelike", 121 "url": "https://truelike.com/", 122 "publisher": { 123 "@id": "https://truelike.com/#org" 124 } 125 }, 126 { 127 "@type": "MobileApplication", 128 "@id": "https://truelike.com/#app", 129 "name": "truelike", 130 "operatingSystem": "iOS, Android", 131 "applicationCategory": "SocialNetworkingApplication", 132 "description": "truelike is a free app for you and your close friends. every day your private circle gets one question, everyone answers, and then all the answers are revealed together. it's the daily game for your true friends.", 133 "url": "https://truelike.com/", 134 "contentRating": "13+", 135 "offers": { 136 "@type": "Offer", 137 "price": "0", 138 "priceCurrency": "USD" 139 }, 140 "installUrl": [ 141 "https://apps.apple.com/app/id6771850307", 142 "https://play.google.com/store/apps/details?id=com.truelike.app" 143 ], 144 "downloadUrl": [ 145 "https://apps.apple.com/app/id6771850307", 146 "https://play.google.com/store/apps/details?id=com.truelike.app" 147 ], 148 "publisher": { 149 "@id": "https://truelike.com/#org" 150 } 151 } 152 ] 153} 154 </script>
154 155 156 <!-- Termly cookie consent banner (must load before other scripts so autoBlock can gate them) --> 157
157<script src="https://app.termly.io/resource-blocker/cfeb2592-4db0-4a8a-b85c-7242f6f5891c?autoBlock=on"></script>
157 158 <!-- PostHog product analytics - gated by Termly autoBlock; person_profiles:'identified_only' avoids creating profiles for anonymous visitors --> 159
159<script> 160 !function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once unregister identify setPersonProperties group resetGroups reset get_distinct_id getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys captureException opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing set_config debug".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]); 161 posthog.init('phc_wyTWQtyiaWx6QmhmPxvfSHn7DUJirK9YjdTNkpcd94A3', { 162 api_host: 'https://us.i.posthog.com', 163 person_profiles: 'identified_only', 164 // Local and preview hosts never report: dev verification runs polluted prod analytics (09-28). 165 opt_out_capturing_by_default: !/(^|\.)truelike\.com$/.test(location.hostname) 166 }); 167 </script>
167 168 <link rel="preconnect" href="https://fonts.googleapis.com"> 169 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 170 <link href="https://fonts.googleapis.com/css2?family=Bagel+Fat+One&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"> 171
171<script src="https://cdn.tailwindcss.com"></script>
171 172
172<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2/dist/umd/supabase.min.js"></script>
172 173 <style> 174 body { 175 font-family: 'Inter', system-ui, sans-serif; 176 background: #00bfff; 177 color: #001a33; 178 min-height: 100vh; 179 position: relative; 180 overflow-x: hidden; 181 } 182 body::before { 183 content: ""; 184 position: fixed; 185 inset: 0; 186 background-image: 187 radial-gradient(circle at 0% 0%, rgba(255, 255, 0, 0.18), transparent 40%), 188 radial-gradient(circle at 100% 100%, rgba(163, 230, 53, 0.20), transparent 40%); 189 pointer-events: none; 190 z-index: 0; 191 } 192 .wordmark, .display { 193 font-family: 'Bagel Fat One', system-ui, sans-serif; 194 letter-spacing: -0.01em; 195 line-height: 0.95; 196 } 197 .lime { color: #a3e635; } 198 .lime-bg { background: #a3e635; } 199 /* Orange text (was #fb923c) - darkened to #c2410c so it passes 200 WCAG AA on white (5.6:1) and reads clearly on the cyan background 201 too. The brighter #fb923c is kept for solid orange backgrounds 202 and dots, where the contrast equation is reversed. */ 203 .orange { color: #c2410c; } 204 .orange-bg { background: #fb923c; } 205 .yellow-bg { background: #fde047; } 206 .cyan-bg { background: #00bfff; } 207 .sticker { 208 background: #fff; 209 border: 3px solid #001a33; 210 box-shadow: 5px 5px 0 #001a33; 211 } 212 .sticker-yellow { 213 background: #fde047; 214 border: 3px solid #001a33; 215 box-shadow: 5px 5px 0 #001a33; 216 } 217 .sticker-lime { 218 background: #a3e635; 219 border: 3px solid #001a33; 220 box-shadow: 5px 5px 0 #001a33; 221 } 222 .cta-btn { 223 background: #fde047; 224 color: #001a33; 225 border: 4px solid #001a33; 226 box-shadow: 6px 6px 0 #001a33; 227 transition: transform 0.12s ease, box-shadow 0.12s ease; 228 font-weight: 800; 229 } 230 .cta-btn:hover { 231 transform: translate(-2px, -2px) rotate(-1deg); 232 box-shadow: 8px 8px 0 #001a33; 233 } 234 .cta-btn:active { 235 transform: translate(3px, 3px); 236 box-shadow: 1px 1px 0 #001a33; 237 } 238 .store-btn { 239 background: #fff; 240 color: #001a33; 241 border: 3px solid #001a33; 242 box-shadow: 4px 4px 0 #001a33; 243 transition: transform 0.12s ease, box-shadow 0.12s ease; 244 font-weight: 800; 245 display: inline-block; 246 } 247 .store-btn:hover { 248 transform: translate(-2px, -2px); 249 box-shadow: 6px 6px 0 #001a33; 250 } 251 .store-btn:active { 252 transform: translate(2px, 2px); 253 box-shadow: 1px 1px 0 #001a33; 254 } 255 .cta-btn:disabled { 256 opacity: 0.6; 257 cursor: not-allowed; 258 transform: none; 259 box-shadow: 3px 3px 0 #001a33; 260 } 261 .phone-frame { 262 background: #001a33; 263 border-radius: 38px; 264 padding: 10px; 265 border: 4px solid #001a33; 266 box-shadow: 10px 10px 0 #fde047; 267 transform: rotate(2deg); 268 } 269 .phone-screen { 270 background: #fff; 271 border-radius: 30px; 272 overflow: hidden; 273 aspect-ratio: 9 / 19.5; 274 } 275 .selected { 276 background: #fb923c; 277 color: #001a33; 278 border-color: #001a33; 279 transform: rotate(-2deg) scale(1.05); 280 } 281 .input-pop { 282 background: #fff; 283 border: 4px solid #001a33; 284 color: #001a33; 285 font-weight: 600; 286 } 287 .input-pop::placeholder { color: #6b7c8a; } 288 .input-pop:focus { 289 outline: none; 290 box-shadow: 4px 4px 0 #001a33; 291 transform: translate(-2px, -2px); 292 } 293 .tilt-left { transform: rotate(-2deg); } 294 .tilt-right { transform: rotate(2deg); } 295 .tilt-tiny { transform: rotate(-1deg); } 296 .pulse-orange { 297 animation: pulse-orange 1.5s ease-in-out infinite; 298 } 299 @keyframes pulse-orange { 300 0%, 100% { transform: scale(1); } 301 50% { transform: scale(1.2); } 302 } 303 304 /* Play section option cards */ 305 .option-card { 306 background: #fff; 307 border: 3px solid #001a33; 308 box-shadow: 4px 4px 0 #001a33; 309 transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease; 310 cursor: pointer; 311 user-select: none; 312 } 313 .option-card:hover:not(.voted) { 314 transform: translate(-2px, -2px); 315 box-shadow: 6px 6px 0 #001a33; 316 } 317 .option-card:active:not(.voted) { 318 transform: translate(2px, 2px); 319 box-shadow: 1px 1px 0 #001a33; 320 } 321 .option-card.my-pick { 322 background: #fb923c; 323 transform: rotate(-1deg) scale(1.03); 324 } 325 .option-card.voted { 326 cursor: default; 327 } 328 .option-card.voted:hover { 329 transform: none; 330 } 331 .bar-fill { 332 height: 100%; 333 background: #a3e635; 334 border-radius: 3px; 335 transition: width 0.6s ease; 336 } 337 .bar-fill.my-pick-bar { 338 background: #fb923c; 339 }
340 @keyframes pop-in { 341 0% { transform: scale(0.85); opacity: 0; } 342 60% { transform: scale(1.05); } 343 100% { transform: scale(1); opacity: 1; } 344 } 345 .pop-in { animation: pop-in 0.35s ease forwards; } 346 </style> 347</head> 348<body> 349 <!-- Nav --> 350 <header class="max-w-6xl mx-auto px-6 py-6 flex items-center justify-between relative z-10"> 351 <div class="wordmark text-4xl text-white">truelike</div> 352 <a href="#download" class="sticker px-4 py-2 rounded-full text-sm font-extrabold tilt-tiny">get the app â</a> 353 </header> 354 355 <!-- Hero --> 356 <section class="max-w-6xl mx-auto px-6 pt-8 pb-16 md:pt-16 md:pb-24 grid md:grid-cols-2 gap-12 items-center relative z-10"> 357 <div> 358 <span class="sticker-yellow inline-flex items-center gap-2 text-xs font-extrabold uppercase tracking-wider px-3 py-2 rounded-full tilt-left"> 359 <span class="w-2 h-2 rounded-full bg-orange-500 pulse-orange"></span> 360 out now · free · 13+ 361 </span> 362 <h1 class="display text-5xl md:text-7xl mt-6 text-white" style="text-shadow: 4px 4px 0 #001a33;"> 363 the daily game<br />for your<br /><span class="lime">true friends</span> 364 </h1> 365 <p class="text-lg md:text-xl mt-6 max-w-md font-semibold text-white"> 366 one question a day with your closest friends - find out how alike (or different) you really are. 367 </p> 368 <div class="sticker-lime tilt-right inline-block mt-4 px-3 py-1.5 rounded-full text-sm font-extrabold"> 369 no strangers. no dms. just your circle. 370 </div> 371 372 <div class="mt-8 flex flex-col sm:flex-row gap-3 max-w-md"> 373 <a data-store="app_store" data-placement="hero" href="https://apps.apple.com/app/id6771850307" class="cta-btn px-6 py-4 rounded-2xl text-center whitespace-nowrap">ð± download on App Store</a> 374 <a data-store="play_store" data-placement="hero" href="https://play.google.com/store/apps/details?id=com.truelike.app" class="cta-btn px-6 py-4 rounded-2xl text-center whitespace-nowrap">ð¤ get it on Google Play</a> 375 </div> 376 <p class="mt-3 text-sm font-extrabold text-white" style="text-shadow: 2px 2px 0 #001a33;"> 377 free - start a circle and get your friends in 378 </p> 379 </div> 380 381 <!-- App screenshot: the reveal moment. 382 Composited from the App Store screenshot set (store-screenshots/composited/04-reveal.png) - already 383 has the navy phone bezel + brutalist offset and a marketing caption built in 384 ("everyone's answers, all at once."). Replaces the previous CSS phone-mock that showed a 385 hand-rolled pick-one round; the real screenshot keeps the landing in sync with the actual app 386 build instead of having to update HTML mocks when the UI changes. --> 387 <div class="flex justify-center"> 388 <img 389 src="/landing-app-reveal.png" 390 alt="truelike app - the reveal moment: everyone's answers shown at once" 391 class="max-w-xs w-full rounded-3xl" 392 style="transform: rotate(2deg); box-shadow: 10px 10px 0 #001a33;" 393 /> 394 </div> 395 </section> 396 397 <!-- Daily public Play section --> 398 <section class="max-w-3xl mx-auto px-6 py-12 relative z-10"> 399 <div class="sticker rounded-3xl p-8 md:p-10"> 400 <div class="flex items-center gap-3 mb-2"> 401 <span class="sticker-yellow text-xs font-extrabold uppercase tracking-wider px-2 py-1 rounded-full inline-flex items-center gap-1.5"> 402 <span class="w-2 h-2 rounded-full bg-orange-500 pulse-orange inline-block"></span> 403 live · today's question 404 </span> 405 </div> 406 407 <div id="play-loading" class="text-center py-8 text-stone-400 font-bold">loading today's questionâ¦</div> 408 409 <div id="play-content" class="hidden"> 410 <div class="display text-3xl md:text-4xl mt-4 leading-tight" id="play-prompt-text"></div> 411 <p class="mt-3 text-sm font-semibold text-stone-600">pick one - see how everyone else answers</p> 412 413 <div id="play-options" class="grid grid-cols-2 gap-3 mt-6"></div> 414 415 <div id="play-results" class="hidden mt-6 space-y-3 pop-in"> 416 <p class="text-xs uppercase tracking-wider font-extrabold text-stone-500 mb-4">here's how everyone voted today</p> 417 <div id="play-bars"></div> 418 <p class="mt-4 text-sm font-bold text-stone-600">
419 <span id="play-vote-count"></span> votes today 420 </p> 421 </div> 422 423 <div id="play-cta" class="hidden mt-8 pt-6 border-t-2 border-[#001a33] pop-in"> 424 <p class="display text-2xl">want truelike with <span class="orange">your</span> friends?</p> 425 <p class="text-sm font-semibold mt-2 text-stone-700">a new question every day - pick one, hot takes, most likely to and more. friends only, named answers.</p> 426 <div class="mt-4 flex flex-col sm:flex-row gap-3"> 427 <a data-store="app_store" data-placement="play" href="https://apps.apple.com/app/id6771850307" class="store-btn px-5 py-3 rounded-xl text-center text-sm whitespace-nowrap">ð± download on App Store</a> 428 <a data-store="play_store" data-placement="play" href="https://play.google.com/store/apps/details?id=com.truelike.app" class="store-btn px-5 py-3 rounded-xl text-center text-sm whitespace-nowrap">ð¤ get it on Google Play</a> 429 </div> 430 </div> 431 </div> 432 433 <div id="play-error" class="hidden py-6 text-center text-stone-400 font-bold text-sm"> 434 no question today - check back tomorrow 435 </div> 436 </div> 437 </section> 438 439 <!-- How it works --> 440 <section class="max-w-6xl mx-auto px-6 py-16 md:py-24 relative z-10"> 441 <h2 class="display text-4xl md:text-5xl mb-12 text-white" style="text-shadow: 3px 3px 0 #001a33;">how it works</h2> 442 <div class="grid md:grid-cols-3 gap-6"> 443 <div class="sticker rounded-3xl p-6 tilt-left"> 444 <div class="display text-5xl orange">01</div> 445 <h3 class="display text-2xl mt-3">start a circle.</h3> 446 <p class="font-medium mt-3">invite your close friends, up to 12 in all. private. just you and them.</p> 447 </div> 448 <div class="sticker rounded-3xl p-6 tilt-right"> 449 <div class="display text-5xl lime">02</div> 450 <h3 class="display text-2xl mt-3">show up every day.</h3> 451 <p class="font-medium mt-3">one quick round drops at the same time. pick one, hot take, two truths, guess who said it, and more.</p> 452 </div> 453 <div class="sticker rounded-3xl p-6 tilt-left"> 454 <div class="display text-5xl orange">03</div> 455 <h3 class="display text-2xl mt-3">find out who you really are.</h3> 456 <p class="font-medium mt-3">Together. See who matches your taste, who surprises you, who's been holding out.</p> 457 </div> 458 </div> 459 </section> 460 461 <!-- Compare --> 462 <section class="max-w-6xl mx-auto px-6 py-12 relative z-10"> 463 <div class="sticker rounded-3xl p-8 md:p-12"> 464 <h2 class="display text-3xl md:text-4xl mb-8">why not justâ¦</h2> 465 <ul class="space-y-3 text-lg font-medium"> 466 <li><span class="font-extrabold text-stone-400 line-through">BeReal</span> - one prompt, gets old.</li> 467 <li><span class="font-extrabold text-stone-400 line-through">Gas / TBH</span> - anonymous polls, got mean.</li> 468 <li><span class="font-extrabold text-stone-400 line-through">group chats</span> - flat, nothing happens.</li> 469 <li class="pt-2 border-t-2 border-[#001a33]"><span class="wordmark orange text-2xl">truelike</span> - the group chat that plays back.</li> 470 </ul> 471 </div> 472 </section> 473 474 <!-- Questions: plain-text FAQ for people and answer engines. Every Q&A here is 475 mirrored word for word in the FAQPage JSON-LD in <head>; edit both together. --> 476 <section id="questions" class="max-w-3xl mx-auto px-6 py-12 relative z-10"> 477 <h2 class="display text-4xl md:text-5xl mb-8 text-white" style="text-shadow: 3px 3px 0 #001a33;">questions people ask</h2> 478 <div class="sticker rounded-3xl p-6 md:p-10"> 479 <div class="space-y-5"> 480 <div> 481 <h3 class="text-lg md:text-xl font-extrabold">what is truelike?</h3> 482 <p class="font-medium mt-2">truelike is a free app for you and your close friends. every day your private circle gets one question, everyone answers, and then all the answers are revealed together. it's the daily game for your true friends.</p> 483 </div> 484 <div class="pt-5 border-t-2 border-[#001a33]"> 485 <h3 class="text-lg md:text-xl font-extrabold">how does it work?</h3>
486 <p class="font-medium mt-2">start a circle and invite your friends, up to 12 people in all. one question drops each day and everyone answers on their own. answers stay hidden until the reveal, which takes at least 2 people, and then you all see them together.</p> 487 </div> 488 <div class="pt-5 border-t-2 border-[#001a33]"> 489 <h3 class="text-lg md:text-xl font-extrabold">is truelike free?</h3> 490 <p class="font-medium mt-2">yes. truelike is free on iPhone and Android, with no ads and no in-app purchases.</p> 491 </div> 492 <div class="pt-5 border-t-2 border-[#001a33]"> 493 <h3 class="text-lg md:text-xl font-extrabold">what ages is truelike for?</h3> 494 <p class="font-medium mt-2">truelike is for ages 13 and up. you need to be 13 or older to sign up.</p> 495 </div> 496 <div class="pt-5 border-t-2 border-[#001a33]"> 497 <h3 class="text-lg md:text-xl font-extrabold">do my friends need the app?</h3> 498 <p class="font-medium mt-2">no. a friend with your invite link can answer today's question in their browser, with no app and no account, and see the reveal there once 2 or more people have answered. the app is for answering every day and getting a notification when your circle reveals.</p> 499 </div> 500 <div class="pt-5 border-t-2 border-[#001a33]"> 501 <h3 class="text-lg md:text-xl font-extrabold">who can see my answers?</h3> 502 <p class="font-medium mt-2">only the people in your circle. there's no public feed, no followers and no strangers. anyone who opens your circle's invite link can join in, so keep it in your friend group.</p> 503 </div> 504 <div class="pt-5 border-t-2 border-[#001a33]"> 505 <h3 class="text-lg md:text-xl font-extrabold">what kinds of questions are there?</h3> 506 <p class="font-medium mt-2">rounds rotate between pick one, hot take, most likely to, two truths and a lie, guess who said it, and open questions you answer in your own words.</p> 507 </div> 508 <div class="pt-5 border-t-2 border-[#001a33]"> 509 <h3 class="text-lg md:text-xl font-extrabold">does it work on iPhone and Android?</h3> 510 <p class="font-medium mt-2">yes. get truelike free on the App Store for iPhone or on Google Play for Android.</p> 511 </div> 512 </div> 513 </div> 514 </section> 515 516 <!-- Download CTA --> 517 <section id="download" class="max-w-3xl mx-auto px-6 py-20 text-center relative z-10"> 518 <h2 class="display text-4xl md:text-6xl leading-tight text-white" style="text-shadow: 4px 4px 0 #001a33;">be first<br/>in your <span class="lime">circle.</span></h2> 519 <p class="text-lg mt-6 font-bold text-white">Download truelike, start a circle, and get your friends in.</p> 520 <div class="mt-8 flex flex-col sm:flex-row gap-3 justify-center"> 521 <a data-store="app_store" data-placement="footer" href="https://apps.apple.com/app/id6771850307" class="cta-btn px-6 py-4 rounded-2xl text-center whitespace-nowrap">ð± download on App Store</a> 522 <a data-store="play_store" data-placement="footer" href="https://play.google.com/store/apps/details?id=com.truelike.app" class="cta-btn px-6 py-4 rounded-2xl text-center whitespace-nowrap">ð¤ get it on Google Play</a> 523 </div> 524 </section> 525 526 <!-- Footer --> 527 <footer class="max-w-6xl mx-auto px-6 py-12 text-sm flex flex-col md:flex-row justify-between items-center gap-4 border-t-2 border-[#001a33] text-white font-bold relative z-10"> 528 <div class="wordmark text-xl">truelike</div> 529 <div class="flex items-center gap-2"><span class="w-2 h-2 rounded-full bg-orange-400 inline-block"></span>privacy-first. no dms. no strangers. 13+.</div> 530 <div class="flex flex-wrap items-center gap-4"> 531 <a href="/for-parents" class="hover:underline">For Parents</a> 532 <a href="/child-safety" class="hover:underline">Child Safety</a> 533 <a href="/privacy" class="hover:underline">Privacy</a> 534 <a href="/terms" class="hover:underline">Terms</a> 535 <a href="/cookies" class="hover:underline">Cookies</a> 536 <a href="#" class="termly-display-preferences hover:underline">Consent Preferences</a>
537 <span>© 2026</span> 538 </div> 539 </footer> 540 541
541<script> 542 const SUPABASE_URL = 'https://slrngimolxelqygkjkhh.supabase.co'; 543 const SUPABASE_ANON_KEY = 'sb_publishable_3qHvnHe9ycvXguoRxB0SVw_rXbi0gvP'; 544 const sb = supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY); 545 546 // ââ Store CTAs (founder path live in both stores since 1.0.21) ââââââââââ 547 const APP_STORE_URL = 'https://apps.apple.com/app/id6771850307'; 548 const PLAY_STORE_URL = 'https://play.google.com/store/apps/details?id=com.truelike.app'; 549 // Phones see only their own store: 3 of 4 Android visitors who tapped a store 550 // button in Sep tapped the App Store one, a dead end on Android. Desktop keeps both. 551 const UA = navigator.userAgent || ''; 552 const PLATFORM = /android/i.test(UA) ? 'android' 553 : (/iphone|ipad|ipod/i.test(UA) || (/macintosh/i.test(UA) && navigator.maxTouchPoints > 1)) ? 'ios' 554 : 'desktop'; 555 const HIDE_STORE = { android: 'app_store', ios: 'play_store' }[PLATFORM]; 556 document.querySelectorAll('a[data-store]').forEach(a => { 557 a.href = a.dataset.store === 'app_store' ? APP_STORE_URL : PLAY_STORE_URL; 558 if (a.dataset.store === HIDE_STORE) a.style.display = 'none'; 559 // Named conversion event. Consent-safe: no-op when Termly blocked PostHog. 560 a.addEventListener('click', () => { 561 try { window.posthog?.capture?.('landing_store_tapped', { store: a.dataset.store, placement: a.dataset.placement, platform: PLATFORM }); } catch (_) {} 562 }); 563 }); 564 565 // ââ Daily public Play section ââââââââââââââââââââââââââââââââââââââââââââ 566 (async function initPlay() { 567 const loadingEl = document.getElementById('play-loading'); 568 const contentEl = document.getElementById('play-content'); 569 const errorEl = document.getElementById('play-error'); 570 571 try { 572 const today = new Date().toISOString().slice(0, 10); // YYYY-MM-DD 573 574 // Fetch today's featured prompt 575 const { data: dailyRows, error: dailyErr } = await sb 576 .from('public_daily_prompt') 577 .select('prompt_id') 578 .eq('date', today) 579 .limit(1); 580 581 if (dailyErr || !dailyRows || dailyRows.length === 0) { 582 loadingEl.classList.add('hidden'); 583 errorEl.classList.remove('hidden'); 584 return; 585 } 586 587 const promptId = dailyRows[0].prompt_id; 588 589 // Fetch the prompt data 590 const { data: promptRows, error: promptErr } = await sb 591 .from('prompts') 592 .select('prompt, options') 593 .eq('id', promptId) 594 .limit(1); 595 596 if (promptErr || !promptRows || promptRows.length === 0) { 597 loadingEl.classList.add('hidden'); 598 errorEl.classList.remove('hidden'); 599 return; 600 } 601 602 const promptData = promptRows[0]; 603 const options = promptData.options || []; 604 605 // Fetch existing vote counts for distribution display 606 const { data: votes } = await sb 607 .from('public_votes') 608 .select('option_index') 609 .eq('prompt_id', promptId) 610 .eq('date', today); 611 612 const voteCounts = new Array(options.length).fill(0); 613 if (votes) { 614 votes.forEach(v => { if (v.option_index < options.length) voteCounts[v.option_index]++; }); 615 } 616 617 // Check if user already voted today (sessionStorage) 618 const storageKey = 'truelike:played:' + today; 619 const myPick = sessionStorage.getItem(storageKey); 620 const hasVoted = myPick !== null; 621 622 // Render prompt 623 document.getElementById('play-prompt-text').textContent = promptData.prompt; 624 625 const optionsEl = document.getElementById('play-options'); 626 options.forEach((opt, i) => { 627 const card = document.createElement('button'); 628 card.className = 'option-card rounded-2xl p-4 text-center font-extrabold text-sm' + (hasVoted ? ' voted' : ''); 629 if (hasVoted && String(i) === myPick) card.classList.add('my-pick'); 630 card.textContent = opt; 631 card.setAttribute('data-index', i); 632 if (!hasVoted) { 633 card.addEventListener('click', () => handleVote(i, promptId, today, options, voteCounts)); 634 } 635 optionsEl.appendChild(card); 636 }); 637 638 loadingEl.classList.add('hidden'); 639 contentEl.classList.remove('hidden'); 640 641 if (hasVoted) { 642 showResults(options, voteCounts, votes ? votes.length : 0, Number(myPick)); 643 } 644 645 } catch (err) { 646 loadingEl.classList.add('hidden'); 647 errorEl.classList.remove('hidden'); 648 } 649 })(); 650 651 async function handleVote(index, promptId, today, options, prevCounts) { 652 // Optimistically update 653 sessionStorage.setItem('truelike:played:' + today, String(index)); 654 655 // The landing's engagement beat - a visitor played the public demo 656 // round. Consent-safe no-op when Termly blocked PostHog.
657 try { window.posthog?.capture?.('landing_demo_voted', { prompt_id: promptId }); } catch (_) {} 658 659 // Record vote 660 await sb.from('public_votes').insert({ prompt_id: promptId, date: today, option_index: index }); 661 662 // Fetch fresh counts 663 const { data: freshVotes } = await sb 664 .from('public_votes') 665 .select('option_index') 666 .eq('prompt_id', promptId) 667 .eq('date', today); 668 669 const counts = new Array(options.length).fill(0); 670 if (freshVotes) { 671 freshVotes.forEach(v => { if (v.option_index < options.length) counts[v.option_index]++; }); 672 } 673 674 // Mark all cards as voted 675 document.querySelectorAll('#play-options .option-card').forEach((card, i) => { 676 card.classList.add('voted'); 677 card.style.cursor = 'default'; 678 if (i === index) card.classList.add('my-pick'); 679 // Remove click listener by replacing element 680 const clone = card.cloneNode(true); 681 clone.classList.add('voted'); 682 if (i === index) clone.classList.add('my-pick'); 683 card.parentNode.replaceChild(clone, card); 684 }); 685 686 showResults(options, counts, freshVotes ? freshVotes.length : prevCounts.reduce((a,b)=>a+b,0) + 1, index); 687 } 688 689 function showResults(options, counts, totalVotes, myPickIndex) { 690 const resultsEl = document.getElementById('play-results'); 691 const barsEl = document.getElementById('play-bars'); 692 const countEl = document.getElementById('play-vote-count'); 693 const ctaEl = document.getElementById('play-cta'); 694 695 const total = Math.max(totalVotes, counts.reduce((a,b)=>a+b,0), 1); 696 697 barsEl.innerHTML = ''; 698 options.forEach((opt, i) => { 699 const pct = Math.round((counts[i] / total) * 100); 700 const isMine = i === myPickIndex; 701 const row = document.createElement('div'); 702 row.className = 'mb-3'; 703 row.innerHTML = ` 704 <div class="flex items-center justify-between mb-1"> 705 <span class="text-sm font-bold${isMine ? ' orange' : ''}">${opt}${isMine ? ' â you' : ''}</span> 706 <span class="text-sm font-extrabold">${pct}%</span> 707 </div> 708 <div class="h-3 bg-stone-100 rounded-full border-2 border-[#001a33] overflow-hidden"> 709 <div class="bar-fill${isMine ? ' my-pick-bar' : ''}" style="width:${pct}%"></div> 710 </div>`; 711 barsEl.appendChild(row); 712 }); 713 714 countEl.textContent = total.toLocaleString(); 715 resultsEl.classList.remove('hidden'); 716 ctaEl.classList.remove('hidden'); 717 } 718 719 </script>
719 720
720<script defer src="/_vercel/insights/script.js"></script>
720 721</body> 722</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.