<?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: Kupa</title>
    <description>The latest articles on DEV Community by Kupa (@granturismo565).</description>
    <link>https://dev.to/granturismo565</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4062660%2Fe6c8995c-752d-4167-8c98-67479b6e64a0.jpg</url>
      <title>DEV Community: Kupa</title>
      <link>https://dev.to/granturismo565</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/granturismo565"/>
    <language>en</language>
    <item>
      <title>Show DEV: Building Smartphone Specs API with .NET and Caddy</title>
      <dc:creator>Kupa</dc:creator>
      <pubDate>Tue, 04 Aug 2026 15:13:48 +0000</pubDate>
      <link>https://dev.to/granturismo565/show-dev-building-smartphone-specs-api-with-net-and-caddy-38hi</link>
      <guid>https://dev.to/granturismo565/show-dev-building-smartphone-specs-api-with-net-and-caddy-38hi</guid>
      <description>&lt;p&gt;Mobile hardware specification APIs have long been messy and hard to integrate, largely due to incomplete and unnormalized data.&lt;/p&gt;

&lt;p&gt;Raw strings as specs are frustrating to use in program logic. So, I built &lt;a href="https://ds.gtgroup.dev" rel="noopener noreferrer"&gt;Device Specs API&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The Problem: Messy &amp;amp; Unstructured Data
&lt;/h3&gt;

&lt;p&gt;If you've ever tried to integrate a specs API into your project, you've likely faced messy data, missing fields, or raw strings. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Screen Refresh Rates:&lt;/strong&gt; You want to show the refresh rate of a device to the user properly. Instead of an integer, you get a raw string like &lt;code&gt;"6.7 inches, 120Hz LTPO OLED"&lt;/code&gt;. Parsing a complex string just to get one number is a nightmare.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU Clock Speeds:&lt;/strong&gt; It gets even crazier. An API returns:
&lt;code&gt;Octa-core (1x3.4 GHz Cortex-A725 &amp;amp; 3x3.2 GHz Cortex-A725 &amp;amp; 4x2.2 GHz Cortex-A725)&lt;/code&gt;
&lt;em&gt;Congratulations! Your simple feature just turned into a Regex lecture.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. The Solution: Strongly-Typed, Normalized Data
&lt;/h3&gt;

&lt;p&gt;I shifted the parsing heavy lifting to the backend server. The data returned to the user is clean, easy to consume, and strongly typed: numbers are numbers, lists are lists, texts are texts, and booleans are booleans.&lt;/p&gt;

&lt;p&gt;When you request data for a device, the server returns normalized JSON:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;"battery_capacity": 5000&lt;/code&gt; &lt;em&gt;(integer, not &lt;code&gt;"5000"&lt;/code&gt;)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"has_nfc": true&lt;/code&gt; &lt;em&gt;(boolean, not &lt;code&gt;"yes"&lt;/code&gt;)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Strongly-typed arrays for RAM and Storage options instead of raw blobs like &lt;code&gt;"256GB 8GB RAM, 512GB 12GB RAM"&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;(If you ever need the raw format for legacy reasons, it's still available as an optional field!)&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Deep Filtering
&lt;/h3&gt;

&lt;p&gt;What if you want to query very specific hardware parameters without pulling unnecessary data?&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;Deep Filtering&lt;/strong&gt; comes in. It allows you to query the dataset as deeply as possible directly through URL parameters.&lt;/p&gt;

&lt;p&gt;For example, to find all devices with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Battery capacity &amp;gt; 5000 mAh&lt;/li&gt;
&lt;li&gt;RAM &amp;gt;= 8GB&lt;/li&gt;
&lt;li&gt;Manufacturer is &lt;strong&gt;Samsung&lt;/strong&gt; or &lt;strong&gt;Xiaomi&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Model name contains &lt;strong&gt;"pro"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You just pass the pattern into the request URL:&lt;br&gt;&lt;br&gt;
&lt;code&gt;?battery_gt=5000&amp;amp;ram_gte=8&amp;amp;manufacturer_in=samsung,xiaomi&amp;amp;model_contains=pro&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Simple as that!&lt;/p&gt;




&lt;h3&gt;
  
  
  4. The Tech Stack &amp;amp; Architecture
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; ASP.NET Core Web API (.NET)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Blazor WebAssembly / Server hybrid&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Host:&lt;/strong&gt; Ubuntu 24.04 + Docker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse Proxy &amp;amp; SSL:&lt;/strong&gt; Caddy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Format:&lt;/strong&gt; Normalized JSON&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. Why Caddy Instead of Nginx?
&lt;/h3&gt;

&lt;p&gt;I used Nginx for a while, but dealing with manual certbot setups and container configuration tweaks became tedious. &lt;/p&gt;

&lt;p&gt;I switched to &lt;strong&gt;Caddy&lt;/strong&gt;, which handles automatic HTTPS certificate management out of the box with zero manual cron jobs. The &lt;code&gt;Caddyfile&lt;/code&gt; syntax is ultra-clean, minimal, and performance has been rock solid.&lt;/p&gt;




&lt;h3&gt;
  
  
  Try It Out
&lt;/h3&gt;

&lt;p&gt;Full docs and live interactive testing are available here:&lt;br&gt;&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://ds.gtgroup.dev" rel="noopener noreferrer"&gt;Device Specs API (ds.gtgroup.dev)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’d love to get feedback from the DEV.to community on backend performance optimizations or features you'd like to see added!&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
