<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: mark m</title>
    <description>The latest articles on DEV Community by mark m (@devpow).</description>
    <link>https://dev.to/devpow</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3980717%2F303ae25a-28cb-4706-a66f-ba4535f04fd3.png</url>
      <title>DEV Community: mark m</title>
      <link>https://dev.to/devpow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devpow"/>
    <language>en</language>
    <item>
      <title>How I Built a Property Matching System Using Euclidean Distance</title>
      <dc:creator>mark m</dc:creator>
      <pubDate>Fri, 12 Jun 2026 07:14:17 +0000</pubDate>
      <link>https://dev.to/devpow/how-i-built-a-property-matching-system-using-euclidean-distance-e7k</link>
      <guid>https://dev.to/devpow/how-i-built-a-property-matching-system-using-euclidean-distance-e7k</guid>
      <description>&lt;p&gt;Most accommodation platforms sort by price and star ratings. When I started building &lt;a href="https://voyera.com" rel="noopener noreferrer"&gt;Voyera&lt;/a&gt;, a ski accommodation platform for Niseko, Japan, I wanted something different: a system that understands what each guest actually cares about and matches them to properties accordingly.&lt;/p&gt;

&lt;p&gt;The result is the Voyera Index, a six-dimension mapping system that treats every property as a shape rather than a number.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with star ratings
&lt;/h2&gt;

&lt;p&gt;A 4-star hotel tells you almost nothing about whether it fits your trip. A couple looking for a quiet retreat and a group of ten looking for a ski-in/ski-out chalet with a hot tub could both be searching for "4-star accommodation in Niseko." They'll get the same results, sorted by price, and spend hours figuring out what actually works.&lt;/p&gt;

&lt;p&gt;The dimensions that matter are different for every guest. Some care about proximity to the lifts. Others want space and privacy. Some need a full kitchen and laundry for a family of six. Star ratings collapse all of that into a single number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six dimensions instead of one
&lt;/h2&gt;

&lt;p&gt;The Voyera Index maps every property across six dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Luxury&lt;/strong&gt;: fit, finish, and overall quality of the accommodation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facilities&lt;/strong&gt;: on-site amenities like hot tubs, saunas, gyms, ski storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access&lt;/strong&gt;: how close and how easy it is to reach the slopes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value&lt;/strong&gt;: what you get relative to what you pay&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt;: seclusion, space, and independence from other guests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Groups/Family&lt;/strong&gt;: suitability for larger parties, kids, and multi-generational trips&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each property gets a value from 0 to 5 on each dimension. Plot those six values and you get a shape, a radar chart that acts as the property's fingerprint. A luxury penthouse with poor ski access looks completely different from a basic apartment right on the slopes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Euclidean distance comes in
&lt;/h2&gt;

&lt;p&gt;The matching works by asking guests to set their own priorities across the same six dimensions. Their answers produce an "ideal shape." Then it's a distance calculation.&lt;/p&gt;

&lt;p&gt;If a guest's ideal shape is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Luxury: 4, Facilities: 3, Access: 5, Value: 2, Privacy: 1, Groups: 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a property's shape is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Luxury: 3, Facilities: 4, Access: 4, Value: 3, Privacy: 2, Groups: 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Euclidean distance between them is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d = sqrt((4-3)² + (3-4)² + (5-4)² + (2-3)² + (1-2)² + (4-4)²)
d = sqrt(1 + 1 + 1 + 1 + 1 + 0)
d = sqrt(5)
d ≈ 2.24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lower the distance, the closer the match. Rank every property by distance and the guest gets results ordered by fit, not price.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weighted dimensions
&lt;/h2&gt;

&lt;p&gt;Not all dimensions matter equally to every guest. Someone who marks Access as their top priority and does not care about Luxury should see a different ranking than someone with the opposite preferences.&lt;/p&gt;

&lt;p&gt;Weights solve this. If a guest weights Access at 3x and Luxury at 0.5x, the distance formula becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d = sqrt(0.5*(4-3)² + 1*(3-4)² + 3*(5-4)² + 1*(2-3)² + 1*(1-2)² + 1*(4-4)²)
d = sqrt(0.5 + 1 + 3 + 1 + 1 + 0)
d = sqrt(6.5)
d ≈ 2.55
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The weighted version penalises mismatches on dimensions the guest cares about most.&lt;/p&gt;

&lt;h2&gt;
  
  
  The visual language
&lt;/h2&gt;

&lt;p&gt;Each property's six-dimension shape renders as a radar chart. Guests can compare properties visually without reading descriptions. A property that ranks high on Access and Value but sits low on Luxury and Privacy has a distinctive elongated shape. You can see the trade-offs at a glance.&lt;/p&gt;

&lt;p&gt;This also powers the “&lt;a href="//voyera.com/the-voyera-index"&gt;Find My Stay&lt;/a&gt;” quiz on voyera.com, where guests answer a few questions about their trip after entering their preferred dates. They then get ranked property suggestions based on how closely each property’s shape matches their ideal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tech stack
&lt;/h2&gt;

&lt;p&gt;For anyone interested in the implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 16 App Router&lt;/strong&gt; with TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prisma&lt;/strong&gt; ORM with &lt;strong&gt;Neon PostgreSQL&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Property dimension values stored as simple integer columns on the property model&lt;/li&gt;
&lt;li&gt;Distance calculation runs server-side at query time&lt;/li&gt;
&lt;li&gt;Radar charts rendered as SVG; the Index explainer page uses animated SVG with elastic-out easing&lt;/li&gt;
&lt;li&gt;Deployed on &lt;strong&gt;Vercel&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The distance calculation is fast enough to run on every query. With a few hundred properties, there is no need for pre-computation or caching. If the catalogue grows to thousands, pre-computed distance matrices or approximate nearest neighbour search would be the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Simple maths solves real problems.&lt;/strong&gt; Euclidean distance is first-year linear algebra, but applied to a real domain with real trade-offs, it produces results that feel intelligent to the end user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Six dimensions is a sweet spot.&lt;/strong&gt; Fewer and you lose meaningful differentiation between properties. More and the radar charts become hard to read and the quiz becomes tedious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The shape metaphor works.&lt;/strong&gt; Showing guests a visual shape rather than a list of numbers changes how they think about their trip. They stop comparing prices and start comparing fit.&lt;/p&gt;

&lt;p&gt;If you are building any kind of matching or recommendation system, multi-dimensional distance is worth considering before reaching for ML. Sometimes the geometry is enough.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Voyera is live at &lt;a href="https://voyera.com" rel="noopener noreferrer"&gt;voyera.com&lt;/a&gt;. Built with 7 years of Niseko accommodation experience.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
