Building a Travel Power Adapter Tool with Claude in a Weekend

How I turned leftover destination data into a 221-country power adapter finder with plug types and voltage comparison. The first version was unusable.

· · 7 min read

I travel a lot. And every single time, I’m standing in an airport Googling “do I need an adapter for Thailand” while my boarding group is already lining up. The existing tools for this are bad. They’re buried in blog posts from 2016 with popup ads, or they’re a wall of text that doesn’t actually answer the question.

I already had most of the data. My destination guides on Vientapps cover dozens of countries, and each one tracks the local plug type and voltage. The pieces were sitting there. I just needed to turn them into something interactive.

What it does

You pick where you’re from and where you’re going. It tells you: do you need an adapter, do you need a voltage converter, or do you need nothing. It covers 221 countries, all 15 plug types (A through O), and links you to the right adapter on Amazon if you need one.

There’s a collapsible section with plug diagrams, a voltage comparison, and a converter guide. A table of popular routes (US to UK, US to France, etc.) with pre-computed answers. FAQs for the common questions. And the whole thing also works as an embeddable widget other travel sites can iframe in.

How I worked with Claude on this one

This was almost entirely Claude Code agentic runs. I described what I wanted, pointed it at my existing destination data, and let it build. My role was more like a product manager reviewing output than a developer writing code. I’d describe the feature, Claude would ship a complete implementation, I’d review it, and then tell it what to fix.

The initial build took one agentic run. The restyle took another. The whole thing was done in two sessions over two days.

The stack

Astro static page with all logic running client-side in a single <script> block. No framework, no React, no build step beyond what Astro already does. The country data and plug type info get serialized into JSON script tags at build time, then the client-side JS reads them and renders results.

I considered making this a separate app like PackSmart, but it didn’t need a backend. Every possible result is just a comparison between two objects in a JSON array. No API calls, no server, no loading states.

export function getAdapterVerdict(origin: CountryElectrical, destination: CountryElectrical): AdapterVerdict {
  const originPlugs = new Set(origin.plugTypes);
  const shared = destination.plugTypes.filter((p) => originPlugs.has(p));
  const missing = destination.plugTypes.filter((p) => !originPlugs.has(p));
  const needsAdapter = shared.length === 0;
  const voltageMatch = Math.abs(origin.voltage - destination.voltage) <= 20;
  const needsConverter = !voltageMatch;

  const freqOrigin = Array.isArray(origin.frequency) ? origin.frequency : [origin.frequency];
  const freqDest = Array.isArray(destination.frequency) ? destination.frequency : [destination.frequency];
  const frequencyMatch = freqOrigin.some((f) => freqDest.includes(f));

  return { needsAdapter, needsConverter, sharedPlugTypes: shared, missingPlugTypes: missing, voltageMatch, frequencyMatch };
}

That’s the core logic. If none of your home country’s plug types exist in the destination’s list, you need an adapter. If the voltage difference is more than 20V, you need a converter. Simple, but it handles the edge cases: countries with multiple plug types, dual-voltage regions, frequency mismatches.

The hard part

Information hierarchy. The tool needs to answer one question fast: “do I need to buy something before my trip?” But it also needs to handle the follow-up questions: “what type?” and “what about my hair dryer?”

Claude’s first implementation threw everything at the user at once. Plug diagrams, voltage charts, converter guides, notes about regional voltage variations. It was technically complete and practically unusable. Nobody landing on this page from Google wants to parse a wall of technical data. They want a yes/no verdict with a link to buy the thing.

The fix was progressive disclosure. The verdict sits at the top in a bold banner. The Amazon link is right below it. Everything else collapses behind a details element:

<details id="pf-details" class="pf-details mt-3">
  <summary class="pf-details-summary">
    <span>Voltage details, plug picture, and converter guide</span>
  </summary>
  <div class="pf-details-body">
    <!-- Plug type cards, voltage comparison, converter advice -->
  </div>
</details>

Simple pattern, but it took two full restyle passes to get there because Claude kept defaulting to “show everything.”

Where Claude surprised me

The data layer. Claude compiled a 221-country JSON dataset with plug types, voltages, frequencies, and edge-case notes in a single pass. Countries like Brazil where voltage varies by region, Cambodia where five different plug types are in use, Bangladesh where Type D and G are most common despite officially supporting five types.

{"name": "Brazil", "iso": "BR", "plugTypes": ["C", "N"], "voltage": 127, "frequency": 60, "notes": "Voltage varies by region: 127V in most of the southeast (Sao Paulo, Rio) and 220V in the south (Brasilia, Florianopolis) and northeast (Recife, Salvador). Always check before plugging in."}

I spot-checked a bunch of these against IEC standards and travel forums. They were accurate. Claude also generated all 15 plug type SVGs inline, each with the correct pin layout, grounding, and shape. No external image files needed. That saved me from sourcing or licensing illustrations.

Where Claude fell short

The initial UI was a disaster. Claude built something that was technically functional but impossible to actually use. The country selectors were basic dropdowns with no search. The results showed every data point at once with no hierarchy. There was no visual distinction between “you need nothing” and “you need a specific adapter.”

I had to run a complete restyle. The first attempt at the restyle was still too busy. I ended up having to be very specific about what I wanted: a horizontal picker row with flag emojis, a single bold verdict line, a dark CTA button, and everything else hidden behind a collapsible. Claude needed that level of direction to produce something clean.

The country picker alone went through multiple iterations:

function initPicker(root: HTMLElement, onSelect: (iso: string, name: string) => void) {
  const trigger = root.querySelector('.pf-picker-trigger') as HTMLButtonElement;
  const panel = root.querySelector('.pf-picker-panel') as HTMLElement;
  const search = root.querySelector('.pf-picker-search') as HTMLInputElement;
  // ...keyboard nav, filtering, popular chips, scroll-into-view
  return { setTriggerDisplay, selectIso };
}

This picker has search, keyboard navigation, popular country chips, and proper ARIA. None of that existed in the first version. Claude could build each individual piece when asked, but it couldn’t intuit what the right UX shape was from a high-level description.

What went wrong overall

Scope was actually fine here. The real problem was making two things at once: a standalone tool page and an embeddable widget. The widget version needs to work in an iframe at arbitrary widths, with theme detection, without any of the page chrome. That doubled the surface area for styling bugs.

I also launched it hidden behind a sitemap exclusion initially, which means I didn’t get real feedback on the UX until I enabled it on the tools page. If I’d shown it to someone earlier, I might have caught the information-overload problem faster.

Where it is now

Live at /tools/plug-finder. Indexed, included in the tools listing, has an embeddable widget version for outreach. The affiliate links are working. It handles URL parameters (?from=US&to=GB) so you can deep-link to specific routes.

What I would do differently

Start with a wireframe. Not a pixel-perfect mockup, just a rough sketch of the information hierarchy: what does the user see first, what’s hidden, what’s the action. Claude is great at building whatever you describe, but it defaults to “show all the data” when you don’t constrain the layout upfront. A 30-second sketch on paper would have saved me the entire restyle pass.

I’d also be more explicit about the “nothing needed” state. That’s actually the most satisfying result for the user, and it deserves its own distinct treatment. Claude’s first version treated it as just another line of text. Now it gets a big “Nothing.” headline. Small thing, but it’s the difference between a tool that feels good to use and one that just dumps information.

C
Caden Sorenson

Senior Staff Engineer and Indie Developer

Caden Sorenson is a senior staff engineer with 15+ years of experience building iOS apps, web platforms, and developer tools. He holds a Computer Science degree from Utah State University and runs Vientapps, an indie studio based in Logan, Utah, where he ships small, focused tools and writes about every build in public.

Stay in the loop

Get notified when I publish new posts. No spam, unsubscribe anytime.