PageSourceSearch

https://truelike.com/

html truelike.com collected 2026-10-02 00:34:07 UTC 33,989 bytes, 722 lines download raw bytes

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.