<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Projects on zacharyc</title>
    <link>https://www.zacharyc.com/tags/projects/</link>
    <description>Recent content in Projects on zacharyc</description>
    <image>
      <title>zacharyc</title>
      <url>https://www.zacharyc.com/papermod-cover.png</url>
      <link>https://www.zacharyc.com/</link>
    </image>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Tue, 10 Mar 2026 11:15:55 -0600</lastBuildDate>
    <atom:link href="https://www.zacharyc.com/tags/projects/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>CNContact Is Stuck in 2015</title>
      <link>https://www.zacharyc.com/2026/03/10/cncontact-is-stuck-in-2015/</link>
      <pubDate>Tue, 10 Mar 2026 11:15:55 -0600</pubDate>
      <guid>https://www.zacharyc.com/2026/03/10/cncontact-is-stuck-in-2015/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Apple&amp;rsquo;s contact framework doesn&amp;rsquo;t understand how we actually connect.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In my &lt;a href=&#34;https://www.zacharyc.com/2026/03/07/your-contacts-app-is-broken/&#34;&gt;previous post&lt;/a&gt;, I wrote about how Apple&amp;rsquo;s Contacts app treats your relationships like a filing cabinet — a flat list of static cards with no context, no history, and no awareness of how people actually matter to you. That&amp;rsquo;s a product problem. But it&amp;rsquo;s also a technical one.&lt;/p&gt;
&lt;p&gt;Underneath the Contacts app sits a framework called &lt;code&gt;CNContact&lt;/code&gt;, introduced at WWDC 2015 as a replacement for the widely despised &lt;code&gt;AddressBook.framework&lt;/code&gt;. AddressBook was a C-based API with no Objective-C layer, opaque types like &lt;code&gt;ABRecordRef&lt;/code&gt;, and virtually no error handling. When Apple announced its deprecation, the WWDC audience cheered — one of the loudest reactions in the conference&amp;rsquo;s history.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>Apple&rsquo;s contact framework doesn&rsquo;t understand how we actually connect.</strong></p>
<hr>
<p>In my <a href="https://www.zacharyc.com/2026/03/07/your-contacts-app-is-broken/">previous post</a>, I wrote about how Apple&rsquo;s Contacts app treats your relationships like a filing cabinet — a flat list of static cards with no context, no history, and no awareness of how people actually matter to you. That&rsquo;s a product problem. But it&rsquo;s also a technical one.</p>
<p>Underneath the Contacts app sits a framework called <code>CNContact</code>, introduced at WWDC 2015 as a replacement for the widely despised <code>AddressBook.framework</code>. AddressBook was a C-based API with no Objective-C layer, opaque types like <code>ABRecordRef</code>, and virtually no error handling. When Apple announced its deprecation, the WWDC audience cheered — one of the loudest reactions in the conference&rsquo;s history.</p>
<p><code>CNContact</code> was a genuine improvement. Type-safe. Thread-safe immutable objects. A <code>keysToFetch</code> system that lets you load only the properties you need. It&rsquo;s a well-engineered API for an outdated model. Because while the engineering got better, the underlying concept of what a contact <em>is</em> didn&rsquo;t change at all. A person is still a card with fields on it. Name, phone number, email, address.</p>
<p>It&rsquo;s 2026 and that model is broken.</p>
<hr>
<h2 id="what-cncontact-actually-is">What CNContact Actually Is</h2>
<p><code>CNContact</code> is an immutable object representing a single contact record. You access the database through <code>CNContactStore</code>, and when you fetch contacts, you specify which properties you want via <code>keysToFetch</code> — conceptually similar to a SQL <code>SELECT</code> where you name your columns.</p>
<p>A contact has string properties for names (<code>givenName</code>, <code>familyName</code>, <code>middleName</code>), and multi-value properties for phone numbers, email addresses, and postal addresses. Those multi-value fields use <code>CNLabeledValue</code> — an immutable tuple pairing a label (like &ldquo;home&rdquo; or &ldquo;work&rdquo;) with a value (like the phone number itself). Modification goes through <code>CNMutableContact</code>, a mutable subclass. A <code>CNContactType</code> enum distinguishes between people and organizations, though the distinction is thin — the same flat field structure applies to both.</p>
<p>The engineering is competent. The problem is what the engineering models.</p>
<hr>
<h2 id="a-contact-is-not-a-business-card">A Contact Is Not a Business Card</h2>
<p><code>CNContact</code> knows a person&rsquo;s name, phone numbers, email addresses, physical addresses, birthday, organization, and social profiles. That&rsquo;s what you&rsquo;d find on a business card, plus a birthday.</p>
<p>It doesn&rsquo;t know when you last spoke to this person, how you met them, who introduced you, or what your relationship actually is. It can&rsquo;t tell you whether someone is important to you right now or someone you haven&rsquo;t spoken to in three years. It doesn&rsquo;t understand any connection between this person and your other contacts. There&rsquo;s no concept of interaction history, relationship strength, or the social graph between the people in your life.</p>
<p><code>CNContact</code> models a person as a <em>record</em>. It does not model a <em>relationship</em>. In 2026, the relationship is the valuable part. The phone number is the least interesting thing about someone in your network — what you can&rsquo;t easily recover is <em>context</em>.</p>
<p>The model doesn&rsquo;t even work well for its most basic use case. There&rsquo;s a single <code>organizationName</code> field — one company per contact. People consult, freelance, change jobs, hold board seats. <code>CNContact</code> can&rsquo;t represent any of that. It&rsquo;s not a model of a person or a business. It&rsquo;s a model of one person at one company at one point in time.</p>
<p>Apple does expose a <code>contactRelations</code> field — you can label someone as a spouse, parent, or assistant. But it&rsquo;s a string label, not a link. It doesn&rsquo;t point to another <code>CNContact</code>. You can&rsquo;t traverse your network. You can&rsquo;t ask &ldquo;show me everyone connected to Sarah.&rdquo; The relationships, like everything else in this framework, are flat text on a card.</p>
<p>The notes field is singular — one freeform text blob per contact. If you want to track conversations over time, or keep structured notes about multiple interactions, you&rsquo;re appending to a wall of unstructured text. No timestamps, no separation, no history.</p>
<p>There is no concept of archiving. A contact exists or it&rsquo;s deleted. There&rsquo;s no &ldquo;inactive&rdquo; state, no way to move someone to the back of the drawer without losing them entirely.</p>
<hr>
<h2 id="the-identifier-problem">The Identifier Problem</h2>
<p>Every <code>CNContact</code> has an <code>identifier</code> property — a string that should uniquely identify the contact. The natural instinct is to use this as a foreign key, linking your app&rsquo;s data to a specific person.</p>
<p>That instinct will hurt you.</p>
<p>The identifier is local to the device. The same human being on your iPhone and your iPad will have different identifiers. The identifier isn&rsquo;t stable across backup and restore cycles. Developers on Apple&rsquo;s own forums have reported that the <em>same contact</em> accessed through different code paths on the <em>same device</em> returns different identifiers — share a contact from Contacts.app and you get one with an <code>:ABPerson</code> suffix, select it via <code>CNContactPickerViewController</code> and you get a different one without it.</p>
<p>Apple can correlate contacts across devices because they control iCloud and the sync engine beneath the framework. Third-party developers cannot. The workaround is rolling your own matching logic — normalized phone numbers, email addresses, name combinations — essentially rebuilding deduplication from scratch.</p>
<p>If you want to build anything that tracks a contact over time — notes, interaction history, relationship metadata — you can&rsquo;t reliably key it to a <code>CNContact</code>. The identifier that&rsquo;s supposed to be your anchor is quicksand.</p>
<hr>
<h2 id="the-frozen-schema">The Frozen Schema</h2>
<p>So the identifier is unreliable. Could you at least store your additional data <em>on</em> the contact itself?</p>
<p>No.</p>
<p><code>CNContact</code> has a fixed set of properties. No custom fields, no metadata dictionary, no extension points. The schema is what Apple decided a contact needed in 2015, and it hasn&rsquo;t meaningfully expanded since. &ldquo;Last contacted,&rdquo; &ldquo;relationship strength,&rdquo; &ldquo;met at WWDC 2024&rdquo; — anything not on Apple&rsquo;s predetermined list requires your own data store.</p>
<p>That data store needs a key to link back to the contact, which brings you directly back to the identifier problem. You&rsquo;re building on a foundation that shifts under your feet.</p>
<p>Even the simplest CRM systems offer custom fields, tags, activity timelines, and relationship types. <code>CNContact</code> isn&rsquo;t missing features — it&rsquo;s missing the <em>concept</em> that a contact might mean something different to different people and different apps.</p>
<hr>
<h2 id="your-data-lives-on-apples-terms">Your Data Lives on Apple&rsquo;s Terms</h2>
<p>I&rsquo;ll save the full portability deep-dive for a future post, but the short version: getting your contacts <em>out</em> of Apple&rsquo;s ecosystem is harder than it should be.</p>
<p>The only native export format is vCard. No CSV, no JSON, no bulk API. On iOS, you can share one contact at a time. Export is all-or-nothing per contact — you can&rsquo;t select which fields to include. Import vCards back in and you&rsquo;ll likely create duplicates, because the &ldquo;unified contact&rdquo; system that deduplicates on-device doesn&rsquo;t survive a round trip.</p>
<p>Your contacts flow into Apple&rsquo;s ecosystem with minimal friction. Getting them out requires workarounds and third-party tools. This asymmetry is not accidental.</p>
<hr>
<h2 id="built-for-a-world-that-doesnt-exist-anymore">Built for a World That Doesn&rsquo;t Exist Anymore</h2>
<p>The <code>keysToFetch</code> system is well-designed. The immutable/mutable pattern is sound. <code>CNLabeledValue</code> is a good abstraction for multi-value properties. Apple&rsquo;s engineers built a competent framework.</p>
<p>They built it to digitize the Rolodex, and they succeeded. <code>CNContact</code> is an excellent digital Rolodex card.</p>
<p>The problem is that we don&rsquo;t live in a Rolodex world. Our relationships are contextual, dynamic, and cross-platform. A contact isn&rsquo;t a card with a name and number — it&rsquo;s a node in a network, with history, context, and meaning that changes over time. <code>CNContact</code> doesn&rsquo;t model any of that. Its closed schema means you can&rsquo;t teach it to.</p>
<p>It&rsquo;s a 2015 solution to a 1985 problem, and it&rsquo;s the foundation that every app on Apple&rsquo;s platforms is expected to build on when it wants to work with the people in your life.</p>
<hr>
<h2 id="whats-next">What&rsquo;s Next</h2>
<p>I&rsquo;ve spent enough time studying this framework to understand that patching it isn&rsquo;t the answer.</p>
<p>The problems compound. There&rsquo;s no stable identifier, so you can&rsquo;t reliably extend a contact with your own data. There&rsquo;s no extensible schema, so you can&rsquo;t store that data on the contact itself. And there&rsquo;s no universal key to map against — some contacts are unique by phone number, some by email, some by name and company, some by something else entirely. Every contact is a special case.</p>
<p>You could try to build a mapping layer on top of <code>CNContact</code>. Normalize phone numbers, deduplicate emails, fuzzy-match names. But you&rsquo;d be building an increasingly fragile bridge between your data and a foundation that was never designed to support it. At some point, the cost of maintaining that bridge exceeds the cost of building something new.</p>
<p>The model needs to change. Not the UI on top of it, not the permissions around it, not the visual design — the model itself. What a contact is. How identity works. How relationships are represented. How your data moves between devices and platforms.</p>
<p>I&rsquo;m working on that. More soon.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Your Contacts App Is Broken</title>
      <link>https://www.zacharyc.com/2026/03/07/your-contacts-app-is-broken/</link>
      <pubDate>Sat, 07 Mar 2026 19:47:08 -0700</pubDate>
      <guid>https://www.zacharyc.com/2026/03/07/your-contacts-app-is-broken/</guid>
      <description>&lt;p&gt;&lt;strong&gt;And it was never that good to begin with.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;When I was a kid, my dad carried a Filofax everywhere. A thick leather binder stuffed with business cards, meticulously organized. It was his most important professional tool — his grail. He could flip to any section and find exactly who he needed, with notes scribbled in the margins about when they&amp;rsquo;d last spoken and what they&amp;rsquo;d discussed.&lt;/p&gt;
&lt;p&gt;I sometimes wonder if he had a better handle on his network than any of us do now with our phones.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>And it was never that good to begin with.</strong></p>
<hr>
<p>When I was a kid, my dad carried a Filofax everywhere. A thick leather binder stuffed with business cards, meticulously organized. It was his most important professional tool — his grail. He could flip to any section and find exactly who he needed, with notes scribbled in the margins about when they&rsquo;d last spoken and what they&rsquo;d discussed.</p>
<p>I sometimes wonder if he had a better handle on his network than any of us do now with our phones.</p>
<p>Everyone has a contacts app. Almost no one thinks about it. It&rsquo;s done roughly the same thing since phones went digital: show you a list of names with phone numbers and email addresses. Apple&rsquo;s Contacts app is the one I know best, and with macOS 26 and iOS 26, they finally gave it a visual redesign. They somehow made it worse. But the real problem isn&rsquo;t the redesign. The real problem is the model underneath — and it hasn&rsquo;t changed in decades.</p>
<hr>
<h2 id="what-your-contacts-app-actually-does">What Your Contacts App Actually Does</h2>
<p>Apple Contacts is a card viewer. You scroll a list, tap a name, and see fields. It stores names, phone numbers, email addresses, physical addresses, birthdays, a photo, and a single notes field. That&rsquo;s roughly what you&rsquo;d find on a business card, plus a birthday.</p>
<p>Here&rsquo;s what it doesn&rsquo;t do. It can&rsquo;t tell you when you last talked to someone. It doesn&rsquo;t show you how the people in your life are connected to each other. It can&rsquo;t help you organize contacts in meaningful ways — groups exist but are barely functional, and after more than a decade you still can&rsquo;t create a group on iPhone without workarounds. It doesn&rsquo;t track any history or context about a relationship. It doesn&rsquo;t handle the basic reality that people change jobs, move, and get new numbers. There&rsquo;s no way to archive a contact — you either keep it or delete it, with nothing in between.</p>
<p>It treats every contact the same. Your spouse and someone whose card you scanned at a conference three years ago sit in the same flat list, given equal weight.</p>
<hr>
<h2 id="the-redesign-made-things-worse">The Redesign Made Things Worse</h2>
<p>With macOS 26 (Tahoe) and iOS 26, Apple applied their new Liquid Glass design language to Contacts. The result has been rough.</p>
<p>On macOS, users are reporting that the app <a href="https://discussions.apple.com/thread/256194303">crashes when adding new contacts</a>, closing mid-entry without saving. The new photo and background blocks <a href="https://forums.macrumors.com/threads/contacts-app-is-a-nightmare-on-tahoe.2465399/">take up enormous screen real estate and flicker when scrolled</a>. Basic operations are broken — <a href="https://forums.macrumors.com/threads/contacts-app-is-a-nightmare-on-tahoe.2465399/page-2">copying a contact&rsquo;s name pastes it as oversized, centered text in Mail</a>, and you can&rsquo;t copy a company name or job title at all. Users with large contact databases are hitting white screens. Dragging contacts to groups randomly fails.</p>
<p>On iOS 26, you <a href="https://www.macobserver.com/news/ios-26s-contacts-app-has-a-basic-feature-missing/">can&rsquo;t delete contacts from search results</a> — you have to manually scroll through the full list. The redesigned Phone app makes it <a href="https://forums.macrumors.com/threads/anyone-else-not-a-fan-of-the-new-phone-app-in-ios-26.2466258/">harder to actually call someone</a> from your contacts. Everything requires more taps than before.</p>
<p>The consistent theme: more visual chrome, less functionality. The redesign is cosmetic surgery on an app that needed a rethinking.</p>
<hr>
<h2 id="the-things-that-were-always-missing">The Things That Were Always Missing</h2>
<p>The Tahoe redesign exposed problems, but the app was stagnant long before it.</p>
<p>There&rsquo;s no interaction history. Contacts has no idea when you last emailed, called, or texted someone — even though your phone has all of that data. There&rsquo;s no concept of &ldquo;important&rdquo; versus &ldquo;stale&rdquo; contacts, no way to surface people you&rsquo;re losing touch with or flag people you need to follow up with.</p>
<p>There&rsquo;s one company field per contact. In the real world, people consult, change jobs, and hold multiple roles. Contacts doesn&rsquo;t accommodate that. When someone&rsquo;s information changes, the old data is simply overwritten — there&rsquo;s no history, no record of where they used to work or what their old number was.</p>
<p>The notes field is singular. One freeform text blob per contact. If you want to track multiple interactions or keep notes over time, you&rsquo;re appending to a wall of text with no structure.</p>
<p>You can&rsquo;t archive. A contact is either active or deleted. There&rsquo;s no &ldquo;I don&rsquo;t need this right now but I don&rsquo;t want to lose it&rdquo; state — something my dad&rsquo;s Filofax handled effortlessly by just moving a card to a different section.</p>
<p>Group management on iOS still doesn&rsquo;t exist in any real way. Smart groups, tags, filters — none of it. The merge and deduplication tools are unreliable. Sharing is limited to one contact at a time, in vCard format only, with no ability to choose which fields to include.</p>
<hr>
<h2 id="a-card-viewer-not-a-relationship-tool">A Card Viewer, Not a Relationship Tool</h2>
<p>The fundamental issue is how the app thinks about what a contact <em>is</em>. To Apple Contacts, a contact is a record — a static card with data fields on it.</p>
<p>But your contacts aren&rsquo;t records. They&rsquo;re relationships.</p>
<p>Some people matter more than others at different times in your life. The context of how you know someone, what you&rsquo;ve discussed, who connected you — that&rsquo;s the valuable information. The phone number is the least interesting thing about someone in your network.</p>
<p>Apple does allow you to add relationships to a contact — mother, spouse, assistant. But it&rsquo;s just a text label. It&rsquo;s not a real link to another contact in your database. You can&rsquo;t traverse your network. You can&rsquo;t ask &ldquo;show me everyone I know through Sarah&rdquo; or &ldquo;who do I know at this company.&rdquo;</p>
<p>This flatness shows up across Apple&rsquo;s entire product line. In Photos, you can tag a person&rsquo;s face — but it&rsquo;s not connected to their contact card. Everything about people in Apple&rsquo;s ecosystem feels siloed and disconnected, like each app reinvented the concept of &ldquo;a person&rdquo; from scratch.</p>
<p>A contacts app should understand relationships, not just store records. It should have opinions about your network — who you&rsquo;re close to, who you&rsquo;re drifting from, who you should reconnect with. Instead, what we have is a filing cabinet.</p>
<hr>
<h2 id="competitors-exist-but-theyre-built-on-the-same-foundation">Competitors Exist, But They&rsquo;re Built on the Same Foundation</h2>
<p>There are alternatives. Apps like Cardhop offer better search, natural language input, smart groups, and interaction tracking. Users are actively leaving Apple&rsquo;s broken Tahoe experience for these tools, and for good reason — they&rsquo;re genuinely better at the basics.</p>
<p>But they&rsquo;re all built on top of the same underlying contact model. They can make the card viewer faster, smarter, and prettier. They can add features on top. But they can&rsquo;t change the fact that the foundation treats a contact as a flat record with a fixed set of fields. They&rsquo;re still building better Rolodexes.</p>
<p>The demand for something fundamentally better is real and growing.</p>
<hr>
<h2 id="why-i-care">Why I Care</h2>
<p>I&rsquo;ve been thinking about how we manage relationships since studying social networks in college in 2005. Twenty years later, the default tool for managing your most important connections is still a digital address book. My dad&rsquo;s Filofax had sections, annotations, and a system that reflected how he actually thought about people. Our phones, with all their power, offer less.</p>
<p>A contact isn&rsquo;t a name and a number. It&rsquo;s a relationship — with history, context, and meaning that changes over time. The model underneath Apple Contacts, and every major contacts platform, doesn&rsquo;t reflect that.</p>
<p>In the next post, I&rsquo;m going to dig into <em>why</em> — at a technical level — the foundation is broken. And after that, what I think we should build instead.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Dogs of Newport</title>
      <link>https://www.zacharyc.com/2024/02/13/dogs-of-newport/</link>
      <pubDate>Tue, 13 Feb 2024 13:37:39 -0500</pubDate>
      <guid>https://www.zacharyc.com/2024/02/13/dogs-of-newport/</guid>
      <description>&lt;p&gt;Not wanting another project, I created another one: Dogs Of Newport. One of my goals for this year is to start retaking photos. Not just take pictures but also &lt;em&gt;make&lt;/em&gt; photos. Spend time trying to get something decent out of the box we call a camera. One of my favorite subjects is the dogs in the town. As a dog owner, a chunk of my daily is set aside to care for my four-legged best friend. During this time, I meet other four legged creatures around town. Some fantastic dogs are in town, and even more come to visit over the summer.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Not wanting another project, I created another one: Dogs Of Newport. One of my goals for this year is to start retaking photos. Not just take pictures but also <em>make</em> photos. Spend time trying to get something decent out of the box we call a camera. One of my favorite subjects is the dogs in the town. As a dog owner, a chunk of my daily is set aside to care for my four-legged best friend. During this time, I meet other four legged creatures around town. Some fantastic dogs are in town, and even more come to visit over the summer.</p>
<p>This Instagram <a href="https://www.instagram.com/dogsofnpt/">DogsOfNpt</a> is about these beautiful doggos and their adventures around Newport, RI. Expect the photography quality to grow as I learn skills or wane as I begin to get overwhelmed with other aspects of life.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
