{"id":17,"date":"2026-08-25T16:09:18","date_gmt":"2026-08-25T10:39:18","guid":{"rendered":"https:\/\/huffme.com\/blogs\/?p=17"},"modified":"2026-08-25T16:37:23","modified_gmt":"2026-08-25T11:07:23","slug":"founders-note-1","status":"publish","type":"post","link":"https:\/\/huffme.com\/blogs\/founders-note-1\/","title":{"rendered":"Founder&#8217;s Note #1"},"content":{"rendered":"\n<!--\n  Huff founder's letter no. 1. WordPress paste block.\n\n  WHERE TO PASTE\n  Block editor: add a \"Custom HTML\" block and paste this whole file into it.\n  (Or: post options menu > Code editor, and paste it there.)\n  Paste while logged in as an Administrator or Editor. Lower roles have the\n  <style> tag stripped by WordPress's HTML filter, and you would get plain text.\n\n  TWO KNOBS, both at the top of the .huff-post rule below\n    --hp-pad   side padding. 0px by default, because your theme already pads the\n               content column. If text touches the screen edge on a phone, set 16px.\n    --hp-max   reading-width cap. 46rem keeps lines readable on a wide theme\n               without leaving gutters on a normal one. Set \"none\" to fill fully.\n\n  FONT\n  It inherits your theme's typeface on purpose, so the post looks native to the\n  site. To use Huff's own face instead, uncomment the @import line and the\n  font-family line marked GEIST.\n\n  THE TITLE\n  If your theme already prints the post title above the content, delete the\n  <h1> block marked \"REMOVE IF THEME PRINTS TITLE\".\n\n  Colours adapt to the page: greys and hairlines are derived from your theme's\n  own text colour, so this reads correctly on a light or a dark theme.\n-->\n\n<style>\n\/* @import url('https:\/\/fonts.googleapis.com\/css2?family=Geist:wght@400;500;600;700&display=swap'); *\/\n\n.huff-post {\n  --hp-pad: 0px;\n  --hp-max: 46rem;\n  --hp-accent: #C23F73;\n  --hp-line: color-mix(in srgb, currentColor 15%, transparent);\n  --hp-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;\n\n  max-width: var(--hp-max);\n  margin-inline: auto;\n  padding-inline: var(--hp-pad);\n  line-height: 1.7;\n  \/* GEIST: font-family: 'Geist', inherit; *\/\n}\n@media (prefers-color-scheme: dark) {\n  .huff-post { --hp-accent: #E8779F; }\n}\n\n.huff-post *, .huff-post *::before, .huff-post *::after { box-sizing: border-box; }\n\n\/* ---- masthead ---- *\/\n.huff-post h1 {\n  font-size: clamp(2rem, 7vw, 3.1rem);\n  line-height: 1.06;\n  letter-spacing: -0.03em;\n  font-weight: 700;\n  margin: 0 0 1.1rem;\n  text-wrap: balance;\n}\n.huff-post .hp-standfirst {\n  font-size: clamp(1.1rem, 3.6vw, 1.3rem);\n  line-height: 1.5;\n  opacity: 0.72;\n  margin: 0 0 2rem;\n  text-wrap: pretty;\n}\n.huff-post .hp-rule {\n  border: 0;\n  border-top: 1px solid var(--hp-line);\n  margin: 0 0 2.4rem;\n  height: 0;\n}\n\n\/* ---- body ---- *\/\n.huff-post p { margin: 0 0 1.25rem; }\n.huff-post strong { font-weight: 600; }\n.huff-post h2 {\n  font-size: clamp(1.35rem, 4.6vw, 1.75rem);\n  line-height: 1.18;\n  letter-spacing: -0.02em;\n  font-weight: 600;\n  margin: 2.8rem 0 1rem;\n  text-wrap: balance;\n}\n\n\/* ---- pull quote ---- *\/\n.huff-post .hp-pull {\n  margin: 2rem 0;\n  padding: 0.2rem 0 0.2rem 1.15rem;\n  border-left: 3px solid var(--hp-accent);\n  font-size: clamp(1.15rem, 3.8vw, 1.4rem);\n  line-height: 1.36;\n  letter-spacing: -0.014em;\n  font-weight: 600;\n  text-wrap: pretty;\n}\n\n\/* ---- numbers strip ---- *\/\n.huff-post .hp-figures {\n  list-style: none;\n  margin: 1.9rem 0;\n  \/* Transparent: two hairlines instead of a filled card, so it sits on the\n     page's own background whatever colour that is. *\/\n  padding: 1.15rem 0;\n  border: 0;\n  border-top: 1px solid var(--hp-line);\n  border-bottom: 1px solid var(--hp-line);\n  background: transparent;\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));\n  gap: 1.2rem 1.4rem;\n}\n.huff-post .hp-figures li {\n  margin: 0;\n  padding: 0;\n  background: transparent;\n  display: flex;\n  flex-direction: column;\n  gap: 0.1rem;\n}\n.huff-post .hp-figures b {\n  font-family: var(--hp-mono);\n  font-size: clamp(1.3rem, 5vw, 1.5rem);\n  font-weight: 500;\n  letter-spacing: -0.02em;\n  line-height: 1.1;\n  color: var(--hp-accent);\n  font-variant-numeric: tabular-nums;\n}\n.huff-post .hp-figures span { font-size: 0.82rem; line-height: 1.4; opacity: 0.68; }\n\n\/* ---- the failure tally ---- *\/\n.huff-post .hp-tally {\n  margin: 1.8rem 0 1.4rem;\n  display: flex;\n  flex-direction: column;\n  gap: 1.1rem;\n}\n.huff-post .hp-fail {\n  display: grid;\n  grid-template-columns: 2rem 1fr;\n  gap: 0.6rem;\n  align-items: start;\n}\n.huff-post .hp-fail .hp-n {\n  font-family: var(--hp-mono);\n  font-size: 0.8rem;\n  color: var(--hp-accent);\n  padding-top: 0.4rem;\n  font-variant-numeric: tabular-nums;\n}\n.huff-post .hp-fail p { margin: 0; font-size: 0.97rem; line-height: 1.62; }\n.huff-post .hp-fail b { font-weight: 600; }\n\n\/* ---- signoff ---- *\/\n.huff-post .hp-signoff {\n  margin: 2.8rem 0 0;\n  padding-top: 1.8rem;\n  border-top: 1px solid var(--hp-line);\n  font-size: 0.97rem;\n  opacity: 0.75;\n}\n.huff-post .hp-signoff strong { opacity: 1; }\n\n\/* ---- phones ---- *\/\n@media (max-width: 480px) {\n  \/* Insurance: if your theme runs content to the screen edge on a phone, this\n     keeps text off the bezel. Delete this line if your theme already pads. *\/\n  .huff-post { padding-inline: max(var(--hp-pad), 14px); }\n  .huff-post .hp-figures { grid-template-columns: repeat(2, 1fr); }\n  .huff-post .hp-fail { grid-template-columns: 1.7rem 1fr; }\n  .huff-post h1 { letter-spacing: -0.022em; }\n}\n<\/style>\n\n<div class=\"huff-post\">\n\n\n  <p class=\"hp-standfirst\">\n    Every app I admire spends its life solving discovery. We built one where\n    you are invisible by default, there is no follow button, and no amount of\n    searching will surface you. <br><br>That is not a roadmap gap. That is the product.\n  <\/p>\n  <hr class=\"hp-rule\">\n\n  <h2>The bet<\/h2>\n  <p>\n    Gifting is not a discovery problem. Nobody in 2026 struggles to\n    <em>find things to buy<\/em>. Amazon alone will happily show you four hundred\n    million options and a carousel of regret. The problem is narrower and much\n    more annoying: you do not know what your sister actually wants, and asking\n    her ruins the only interesting part.\n  <\/p>\n  <p>\n    Every social wishlist I looked at solved this with a profile. A public page,\n    a follower count, a feed. Which quietly converts <em>a private list of things\n    you want<\/em> into a performance of taste. People notice. So they curate. So the\n    list stops being true, and a list of gifts that isn&#8217;t true is worse than no\n    list at all.\n  <\/p>\n  <p>\n    And they share a second habit that bothers me more, because it is invisible:\n    they are all <strong>list-based<\/strong>. You create a list. A baby registry,\n    a wedding registry, a <em>Birthday 2026<\/em> list. Which quietly means the\n    product only exists during an occasion. When you spot the perfect thing in the\n    middle of March, you have nowhere to put it, so you do what everyone does and\n    remember it wrong six months later.\n  <\/p>\n  <p>\n    Huff has no lists to create. You have one wishlist, it is always on, and you\n    add to it in the two seconds after you see the thing. That is the only moment\n    anyone reliably knows what they want.\n  <\/p>\n  <p>\n    So we turned the arrow around. On Huff you can see someone&#8217;s wishlist only if\n    <strong>they<\/strong> have your number saved in their phone. Not if you have\n    theirs. Theirs.\n  <\/p>\n\n  <div class=\"hp-pull\">\n    The person who owns the list decides who sees it, and they already decided\n    years ago, when they saved your number.\n  <\/div>\n\n  <h2>How it actually works<\/h2>\n  <p>\n    The awkward part of a contact-graph product is that contact books are the\n    most sensitive thing on a phone, and every company that has ever asked for\n    yours has gone on to do something regrettable with it.\n  <\/p>\n  <p>\n    So we never receive them. Your contacts are normalised and hashed\n    <em>on the device<\/em> with Argon2id, salted with a server-side global salt\n    plus an epoch salt that rotates daily, then truncated to 96 bits before\n    anything leaves the phone. What our database holds is a pile of anonymous\n    fingerprints that expire into uselessness. The only phone number we store in\n    plaintext is your own, because we have to text you a code.\n    In plain English: your phone turns your address book into confetti before\n    anything leaves it, and nobody here can put the confetti back, least of all\n    me at 2am with a debugger.\n  <\/p>\n  <p>\n    This is not a privacy policy. It is an architecture. We cannot sell a social\n    graph we were never given, and I find that a far more convincing promise\n    than a paragraph in a footer.\n  <\/p>\n  <p>\n    The rest is deliberately boring. You add things with your phone&#8217;s share\n    sheet. The app never asks you to copy a link, because nobody wants to be a\n    data-entry clerk for their own birthday. Our server unfurls the URL through\n    an adapter chain: a site-specific parser if we have one, then structured\n    JSON-LD, then plain OpenGraph. And when someone taps <em>Gifted<\/em>, that\n    item goes into a thirty-minute exclusive hold, so two cousins in two cities\n    don&#8217;t independently buy the same blender.\n  <\/p>\n\n  <h2>Where we are<\/h2>\n  <ul class=\"hp-figures\">\n    <li><b>1,083<\/b><span>people signed up<\/span><\/li>\n    <li><b>9<\/b><span>countries they&#8217;re in<\/span><\/li>\n    <li><b>1,956<\/b><span>things added to a wishlist<\/span><\/li>\n    <li><b>36<\/b><span>of them actually gifted<\/span><\/li>\n  <\/ul>\n  <p>\n    Read those last two together, because that is the whole company in two\n    numbers. Nineteen hundred and fifty-six things that people want badly enough\n    to save. Thirty-six of them actually bought. <strong>The gap between those two\n    numbers is the product I am building.<\/strong>\n  <\/p>\n  <p>\n    Nine countries is a slightly cheeky way to say a thousand people in India and\n    a rounding error everywhere else: nine in the UAE, seven in the UK, three in\n    Canada, and one lonely pioneer each in the US, Lebanon, T\u00fcrkiye and Germany.\n    I like that column more than the big one. Gifting across a diaspora is the\n    version of this problem that genuinely hurts, and those are the people\n    feeling it first.\n  <\/p>\n  <p>\n    Under that: FastAPI and Postgres on Fly, a React Native app on both stores,\n    Firebase for phone auth, and a scraper that has strong opinions about Indian\n    e-commerce. iOS 1.0.37 went up today. The whole thing is small enough that I\n    know what every table is for, which I am told is a phase.\n  <\/p>\n\n  <h2>Five things that went wrong<\/h2>\n  <p>\n    I would rather write this section than the previous one, because the previous\n    one is a scoreboard and this one is the actual education.\n  <\/p>\n\n  <div class=\"hp-tally\">\n    <div class=\"hp-fail\"><span class=\"hp-n\">01<\/span><p>\n      <b>Two releases shipped pointing at localhost.<\/b> The config file is\n      gitignored; a fresh checkout didn\u2019t have one; the build tool bakes\n      environment variables in at compile time. So the app was entirely broken in\n      production, and <em>invisible in our telemetry<\/em>, because the missing\n      file also held the telemetry keys. The perfect crime, committed against\n      ourselves.\n    <\/p><\/div>\n    <div class=\"hp-fail\"><span class=\"hp-n\">02<\/span><p>\n      <b>iOS lets people share only <em>some<\/em> contacts.<\/b> We inferred\n      permission from how many contacts came back. Seventeen percent of synced\n      users therefore had a quietly crippled graph, and no way to know.\n    <\/p><\/div>\n    <div class=\"hp-fail\"><span class=\"hp-n\">03<\/span><p>\n      <b>Forty-four percent of people who finished onboarding never synced at\n      all.<\/b> A check threw an exception before the sync started. No error\n      screen, no event, no complaint. Just half our funnel walking into a room\n      with the lights off.\n    <\/p><\/div>\n    <div class=\"hp-fail\"><span class=\"hp-n\">04<\/span><p>\n      <b>\u201cThe app feels slow\u201d was not the app.<\/b> It was a database\n      in the wrong city, cold starts, and a cache we were wiping on every launch.\n      We nearly rewrote the client to fix a hosting decision.\n    <\/p><\/div>\n    <div class=\"hp-fail\"><span class=\"hp-n\">05<\/span><p>\n      <b>And this week, doing design work:<\/b> every confirmation dialog in the\n      app had letter-spacing tuned for 32px text being applied at 22px. A\n      progress bar that rendered permanently full. Fifty-seven animations, not\n      one of which respected the operating system\u2019s \u201creduce\n      motion\u201d setting.\n    <\/p><\/div>\n  <\/div>\n\n  <p>\n    Look at the shape of that list. <strong>Almost nothing failed loudly.<\/strong>\n    Not one of those arrived as a crash report or an angry email. They were all\n    found by going and looking, usually at something adjacent, usually by refusing\n    to accept a number that seemed slightly off.\n  <\/p>\n\n  <h2>What we&#8217;re building next<\/h2>\n  <p>\n    Near term: shared lists, so a family can coordinate one gift instead of six\n    sweaters. Better extraction, so pasting any link from any shop on earth just\n    works. We&#8217;re teaching a model to read product pages that have no structured\n    data, which is most of them. And nine countries&#8217; worth of phone formats,\n    currencies and address shapes, because gifting across a diaspora is the\n    version of this problem that actually hurts.\n  <\/p>\n  <p>\n    Further out, the thing I keep circling: <em>\u201cthings I want\u201d<\/em> is\n    a durable object and nobody owns it. Your search history is rented to\n    advertisers. Your cart is owned by one retailer. Your Pinterest board is\n    aspiration, not intent. A list you maintain honestly, shown only to people who\n    already know you, is the most valuable and least exploited object in commerce.\n    The only way to hold it is to build something that structurally cannot spy on\n    you.\n  <\/p>\n  <p>\n    Birthdays are the wedge. The wedge is not the point.\n  <\/p>\n\n  <p class=\"hp-signoff\">\n    <strong>Operator<\/strong><br>\n    If someone you know saved your number, you might already be visible. Sorry.\n  <\/p>\n\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nobody can find you on huff. That is not a roadmap gap, it is the product. Here is the bet.<\/p>\n","protected":false},"author":1,"featured_media":23,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[4],"class_list":["post-17","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-founders-note"],"_links":{"self":[{"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/posts\/17","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/comments?post=17"}],"version-history":[{"count":3,"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/posts\/17\/revisions"}],"predecessor-version":[{"id":22,"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/posts\/17\/revisions\/22"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/media\/23"}],"wp:attachment":[{"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/media?parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/categories?post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/huffme.com\/blogs\/wp-json\/wp\/v2\/tags?post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}