# TickBeep: Find Ticks On Yourself With Your Phone

> Sweep your phone down your clothes, skin and gear. TickBeep beeps and boxes crawling ticks on screen before they reach skin. Join the free field beta.

<section class="hero-wrap">
  <div class="hero">
    <div>
      <div class="tags-row">
        <span class="tag now">Closed beta</span>
        <span class="tag next">Field testers wanted</span>
      </div>
      <h1>Find the tick before it finds skin.</h1>
      <p class="lead">TickBeep turns your phone into a tick detector. Sweep it down your trouser legs, your sleeves, your back and your gear. When something small is crawling, the phone beeps, buzzes, and boxes it on screen. Like a metal detector, but for ticks.</p>
      <a class="cta" href="#beta">Join the field beta<small>closed beta for this season, no store link yet</small></a>
    </div>
    <figure class="hero-visual">
      <picture>
        <source srcset="/hero-tick-on-trousers.webp" type="image/webp">
        <img src="/hero-tick-on-trousers.jpg" width="1280" height="853" loading="eager" decoding="async"
             alt="A person sits at the edge of a wood and sweeps a phone over their own trouser leg. On the phone screen the fabric is magnified and two ticks are each marked with a bright green box.">
      </picture>
      <figcaption>Mockup of the app in use. TickBeep is still in development, this is not a screenshot of a shipping product.</figcaption>
    </figure>
  </div>
</section>

<section id="why">
  <h2>Why your eyes are not enough</h2>
  <p class="lead narrow">You did the walk. You brush yourself off at the car and you feel like you looked. Here is what a look misses.</p>
  <div class="pain-grid">
    <div class="card">
      <svg width="40" height="40" viewBox="0 0 40 40" fill="none" aria-hidden="true">
        <circle cx="20" cy="20" r="3" fill="#ff5a36"/>
        <circle cx="13" cy="13" r="2" fill="#ffb060"/>
        <rect x="8" y="34" width="24" height="3" rx="1.5" fill="#2c3940"/>
      </svg>
      <h3>The small ones are the problem</h3>
      <p>A grown tick you spot and flick off. A nymph is one to two millimetres, and on dark trousers your eye slides right past it. Those are the ones that ride home with you and attach for days before anyone notices.</p>
    </div>
    <div class="card">
      <svg width="40" height="40" viewBox="0 0 40 40" fill="none" aria-hidden="true">
        <path d="M20 4 L36 32 L4 32 Z" fill="none" stroke="#ffb060" stroke-width="2"/>
        <circle cx="20" cy="20" r="2.5" fill="#ff5a36"/>
      </svg>
      <h3>You cannot see your own back</h3>
      <p>The back of your legs, your lower back, behind your collar, between the shoulder blades. You can twist and crane and still not see the places a tick actually climbs to. This is why people check each other. TickBeep is for the times you are on your own.</p>
    </div>
    <div class="card">
      <svg width="40" height="40" viewBox="0 0 40 40" fill="none" aria-hidden="true">
        <circle cx="20" cy="20" r="15" stroke="#ff5a36" stroke-width="2"/>
        <path d="M20 5 L20 12 M20 28 L20 35 M5 20 L12 20 M28 20 L35 20" stroke="#ff5a36" stroke-width="2" stroke-linecap="round"/>
      </svg>
      <h3>At home is already late</h3>
      <p>While you were walking, it was climbing. By the time you are on the couch it may be under a waistband or up a sleeve. The moment to check is at the trailhead, before you get in the car.</p>
    </div>
  </div>
  <p class="aside">This is not about scaring you. It is about the fact that the small, quiet ones are the ones a person checking themselves will miss.</p>
</section>

<section id="how" class="tight">
  <h2>How it works</h2>
  <p class="lead narrow">Three steps. Sweep, beep, look.</p>
  <div class="steps">
    <div class="step">
      <span class="n"></span>
      <h3>Sound instead of screen</h3>
      <p>When you run the phone down the back of your own leg, you cannot see the display at all. So TickBeep does not rely on it. It beeps and vibrates the instant it catches something. You keep sweeping and let your ears do the watching.</p>
    </div>
    <div class="step">
      <span class="n"></span>
      <h3>A green box when you do look</h3>
      <p>Anything the app catches gets a bright green box drawn on the live camera view. No squinting, no hunting the frame. The phone shows you exactly where.</p>
    </div>
    <div class="step">
      <span class="n"></span>
      <h3>It watches for movement, not shape</h3>
      <p>After a walk in the woods you are covered in specks: dirt, seeds, lint, pine needles. All of it sits still. A tick crawls. TickBeep looks for a small object of about the right size that is moving.</p>
    </div>
  </div>
  <p class="aside">Two more things that help your own eyes: a colour-inversion mode, where a dark speck against a flipped background jumps out bright, and a raking-flashlight tip, where a real three-dimensional object throws a shadow and a stain does not. Everything runs on the phone. No camera frames leave your device.</p>
</section>

<section id="where" class="tight">
  <h2>Where it looks</h2>
  <p class="lead narrow">You, what you wore, and what you carried.</p>
  <div class="grid-3">
    <div class="where-card">
      <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
        <path d="M14 8 h8 v8 M14 8 c-6 6 -7 14 -5 22 l4 4 M14 8 v32 M22 16 v28 M26 20 l4 -4 c4 2 5 6 3 10 l-6 6" stroke="#ff5a36" stroke-width="2.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
      <h3>Clothing</h3>
      <p>Trouser legs, sleeves, cuffs, collars, the seams they hide in. Sweep the fabric before it gets into the car with you.</p>
    </div>
    <div class="where-card">
      <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
        <path d="M22 6 c-6 0 -9 6 -9 13 v16 h5 v-20 h8 v20 h5 V19 c0 -7 -3 -13 -9 -13 Z" stroke="#ff5a36" stroke-width="2.4" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
        <line x1="22" y1="6" x2="22" y2="22" stroke="#ff5a36" stroke-width="2.4"/>
      </svg>
      <h3>Bare skin</h3>
      <p>Arms, neck, ankles, the back of the knee. The spots a tick heads for and the spots you cannot easily see.</p>
    </div>
    <div class="where-card">
      <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
        <rect x="8" y="12" width="28" height="20" rx="4" stroke="#ff5a36" stroke-width="2.4" fill="none"/>
        <path d="M14 14 v-5 h16 v5" stroke="#ff5a36" stroke-width="2.4" fill="none" stroke-linecap="round"/>
        <line x1="22" y1="12" x2="22" y2="8" stroke="#ff5a36" stroke-width="2.4" stroke-linecap="round"/>
        <path d="M16 24 h12" stroke="#ffb060" stroke-width="2.4" stroke-linecap="round"/>
      </svg>
      <h3>Your gear</h3>
      <p>Backpack, boots, tent, sleeping mat. A tick rides home on the kit you carried, then finds you later. Check what you wore and what you packed, not just yourself.</p>
    </div>
  </div>
</section>

<section id="status" class="tight">
  <h2>What it does today, and what is in progress</h2>
  <p class="lead narrow">We would rather be straight with you than oversell. Here is the honest split.</p>
  <div class="grid-2">
    <div class="panel">
      <span class="tag now">Working now</span>
      <ul>
        <li>Live detection of small moving objects on the camera view</li>
        <li>Bright green box around whatever it catches</li>
        <li>Beep and vibration so it works blind</li>
        <li>Colour-inversion mode</li>
        <li>Raking-flashlight guidance</li>
        <li>Runs fully on the phone, no frames uploaded</li>
      </ul>
    </div>
    <div class="panel">
      <span class="tag next">In progress</span>
      <ul class="next">
        <li>Coverage mapping using the depth sensor, so the app knows which parts of you have been swept and which you skipped</li>
        <li>A mode tuned for animal fur, for later</li>
        <li>A thermal clip-on for warm-body detection</li>
      </ul>
    </div>
  </div>
  <p class="aside">We are not putting dates on the in-progress list. It ships when it is good, not before.</p>
</section>

<section id="beta">
  <div class="form-panel">
    <span class="tag now">Closed beta</span>
    <h2>Sign up for the beta</h2>
    <p class="lead">We are recruiting field testers for this season. A spot in the beta is free.</p>
    <form id="beta-form" action="/api/forms/tickbeep/beta" method="post">
      <div class="field">
        <label for="email">Email</label>
        <input type="email" id="email" name="email" required placeholder="you@example.com" autocomplete="email">
      </div>
      <div class="field">
        <label for="region">Region or country</label>
        <input type="text" id="region" name="region" placeholder="Scotland, Connecticut, Bavaria" autocomplete="country-name">
      </div>
      <div class="field">
        <label for="device">Phone you carry</label>
        <input type="text" id="device" name="device" placeholder="iPhone 15 Pro, Pixel 8, Galaxy S23">
      </div>
      <div class="field">
        <span class="label">Where do you spend time?</span>
        <label class="check"><input type="checkbox" name="terrain" value="woods"> Woods and trails</label>
        <label class="check"><input type="checkbox" name="terrain" value="fields"> Fields and edges</label>
        <label class="check"><input type="checkbox" name="terrain" value="grassland"> Grassland and water edges</label>
        <label class="check"><input type="checkbox" name="terrain" value="work"> Working outdoors</label>
      </div>
      <div class="hp" aria-hidden="true">
        <label for="website">Website</label>
        <input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
      </div>
      <div class="cf-turnstile" data-sitekey="0x4AAAAAADTuJu-BSkxDDaDc"></div>
      <button class="btn" id="beta-submit" type="submit">Save my spot</button>
      <p class="form-status" id="beta-status" role="status" aria-live="polite"></p>
      <p class="fine">Why we ask for region: ticks are local. The species on a trail in Scotland is not the one on a path in Connecticut. We test against the ticks that actually live where you are, so we want testers spread across real places, not a lab.</p>
    </form>
  </div>
</section>

<section id="faq" class="tight">
  <h2>FAQ</h2>
  <details>
    <summary>Is this a medical device?</summary>
    <p>No. TickBeep is a detection aid that helps you spot a crawling tick sooner. It does not diagnose anything, it does not assess a bite, and it is not a substitute for medical advice.</p>
  </details>
  <details>
    <summary>What if the tick stops moving?</summary>
    <p>Then it may not catch it. TickBeep keys on movement, so a tick that goes still can slip past. Treat the app as a second set of eyes, not a replacement for a proper look-over. It finds things faster than you would alone. It does not promise to find every one.</p>
  </details>
  <details>
    <summary>Where do my camera frames go?</summary>
    <p>Nowhere. All the processing happens on your phone. No frames are uploaded, stored on a server, or sent anywhere.</p>
  </details>
  <details>
    <summary>Does it flag mosquitoes too?</summary>
    <p>Yes. It looks for anything small and moving, so mosquitoes, midges and ants will get boxed as well. Ticks are the target and the rest is a side effect of how it works. A box you can dismiss in a second beats a nymph you never saw.</p>
  </details>
  <details>
    <summary>What will it cost?</summary>
    <p>Free for this season's beta testers. That is the whole deal for signing up now.</p>
  </details>
  <details>
    <summary>Can it check a dog?</summary>
    <p>Not the focus. TickBeep is built for checking yourself and your clothes in the field. A mode tuned for animal fur is something we are looking at later, but the app is for you and what you wore, not the pet.</p>
  </details>
  <details>
    <summary>Android?</summary>
    <p>On the list. Tell us in the form which phone you carry and it helps us decide what to build next.</p>
  </details>
</section>

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<script>
(function () {
  var form = document.getElementById('beta-form');
  if (!form) return;
  var status = document.getElementById('beta-status');
  var submit = document.getElementById('beta-submit');
  var renderedAt = Math.floor(Date.now() / 1000);

  function setStatus(text, isError) {
    status.textContent = text;
    status.classList.toggle('is-error', !!isError);
    status.classList.toggle('is-ok', !isError && !!text);
  }

  function uuid() {
    return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) {
      return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16);
    });
  }

  form.addEventListener('submit', async function (e) {
    e.preventDefault();
    submit.disabled = true;
    setStatus('Sending...', false);

    var data = new FormData(form);
    var terrain = data.getAll('terrain').join(', ');
    var payload = {
      fields: {
        email: data.get('email'),
        region: data.get('region') || '',
        device: data.get('device') || '',
        terrain: terrain
      },
      website: data.get('website') || '',
      rendered_at: renderedAt,
      idempotency_key: uuid(),
      'cf-turnstile-response': (form.querySelector('[name="cf-turnstile-response"]') || {}).value || null
    };

    try {
      var resp = await fetch('/api/forms/tickbeep/beta', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(payload)
      });
      var result = await resp.json();
      if (result.ok) {
        setStatus('You are on the list. We will email you before the season starts.', false);
        form.reset();
        if (window.turnstile) window.turnstile.reset();
      } else {
        setStatus('Could not send that. Please try again in a minute.', true);
        if (window.turnstile) window.turnstile.reset();
      }
    } catch (err) {
      setStatus('Network error. Please try again later.', true);
      if (window.turnstile) window.turnstile.reset();
    } finally {
      submit.disabled = false;
    }
  });
})();
</script>