Why AI is the Default (and Offline Mode is Opt-In)
Early versions of Contact Scout offered two equal paths: AI-powered extraction and regex-based parsing. Users saw three context menu items every time they right-clicked. It felt cluttered. Worse, new users had to understand the difference before they could even start.
We watched how people actually used the tool. The pattern was clear: once someone tried AI Scout, they rarely went back. AI handles messy formatting, images, multi-language text, and all the edge cases that regex can't touch. The experience is just better.
So we made a call: one "Scout" button that auto-detects whether you've selected text or an image and routes accordingly. Offline Mode is still there — toggle it in Settings for situations where you're offline or want to parse locally — but it's no longer competing for attention on every right-click.
Reduce three context menu items to one. Let the tool be smart so the user doesn't have to think.
Why There's No Retry Button
We had a retry button. It seemed like a no-brainer — if extraction fails, let users try again with one click. But we realized something: retrying requires the same amount of effort as just right-clicking and selecting "Scout" again. The user is already on the page, already looking at the text. A retry button doesn't save any meaningful steps.
What it does add is visual clutter. Every button in a panel is one more thing to scan. One more decision to make. In a tool that's supposed to be fast, that friction matters.
When extraction fails, we show a clear message and a "Enter Manually" option. If users want to try again, they just re-select and right-click. It's the same gesture they used to get there in the first place.
Remove the retry button. Don't add UI for something the browser already does natively.
Your Data Never Touches Our Servers
When you scout a contact, the text or image is sent to Google's Gemini API for parsing, and the structured result comes straight back to your browser. We don't store it. We don't log it. There's no database row with your contacts in it.
This was a deliberate architectural choice, not an afterthought. Storing contact data would mean taking on responsibility for PII we don't need. It would mean privacy policies with more caveats, more infrastructure to secure, and more reasons for enterprise customers to say no.
Our backend is stateless. It authenticates your request, sends it to Gemini, and returns the result. Quota tracking uses your account email — we know how many scouts you've used, but we never see or store what you scouted.
Stateless by design. We track usage, not content. Your contacts go from the page to your address book — we're just the bridge.
Publishing Our Real Accuracy Numbers
Our Quality Dashboard shows live accuracy data from automated nightly test runs against real websites. Not cherry-picked demos. Not synthetic benchmarks. Real pages, real parsing, real results.
Early on, we caught ourselves inflating the numbers. Canary runs (quick sanity checks triggered on every code push) were being mixed into the dashboard averages, pulling the accuracy up to 71% when the honest nightly number was 53%. We fixed that. The dashboard now excludes canary runs entirely.
It's tempting to only show the best numbers. But accuracy you can't reproduce isn't accuracy — it's marketing. We'd rather show real numbers we can improve than fake numbers we have to defend.
Publish honest accuracy. Exclude canary inflation. Show numbers we can stand behind and improve.
One File Owns All Parsing
All contact parsing and formatting logic lives in a single file: formatting-rules.js.
Phone normalization, name splitting, email extraction, address parsing, company detection —
it's all there. The service worker imports it. The content script imports it. Tests run against it directly.
This sounds like a recipe for a 2,000-line monster file, and it is. But the alternative — scattering parsing logic across popup, content script, and service worker — is worse. When a regex pattern needs fixing, you fix it in one place. When a new phone format appears in the wild, there's one function to update. When tests fail, they point to one file.
We tried a more sophisticated approach — a three-phase "elimination pipeline" that masked extracted fields and scored leftovers. It was architecturally elegant. It also dropped real-world accuracy by 7 percentage points. We reverted within hours. Sometimes the less clever solution is the right one.
Keep all parsing in one file. Resist the urge to over-architect. Measure changes against real websites, not just unit tests.
Announcements Without Tracking
Most extensions use push notifications or analytics-laden update checks. We wanted a way to communicate with users — version updates, maintenance windows, new features — without any tracking infrastructure.
Our announcement system is pull-based. The extension periodically fetches a static JSON file hosted on GitHub Pages. No analytics. No user identification. No tracking pixels. If we need to tell users something, we update a JSON file. If we don't, the file sits dormant.
Users can dismiss announcements, and that state is stored locally in their browser. We never know who saw it, who dismissed it, or who ignored it. And that's fine.
Pull-based announcements via static JSON. No tracking, no analytics, no user identification. Communication without surveillance.
Duplicates: Ask, Don't Assume
When you save a contact that already exists in Google Contacts or Outlook, we show an amber "Duplicate Found" panel. You get three choices: update the existing contact, save as a new one, or open the existing contact in your address book to compare.
We could have auto-merged. Some tools do. But auto-merging assumes the new data is always better, and that's not true. Maybe you're scouting an outdated page. Maybe the existing contact has notes or a photo you don't want to overwrite. The cost of asking is a single click. The cost of silently overwriting is data loss the user might not notice for months.
Never auto-merge. Show the duplicate, explain the options, and let the user decide. One extra click beats silent data loss.
Trust Blue and Emerald Green
Contact Scout's color palette is built on two colors: Trust Blue (#2563EB) and Emerald Green (#10B981). Blue for primary actions, navigation, and branding. Green for success states — saved, exported, connected.
We chose these deliberately. The tool handles personal contact information and connects to Google and Microsoft accounts. Users need to feel that it's safe and professional. Blue signals trust and reliability. Green signals "this worked" without ambiguity.
For users who want something different, we offer four themes: Light Glass (default), Gold Executive, Cotton Candy, and Neon Cyberpunk. The themes change the panel and popup appearance, but the core blue-and-green vocabulary stays consistent across the website and onboarding flow.
Blue for trust, green for success. Keep the core palette professional and consistent, then let themes add personality.