<?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: Axo</title>
    <description>The latest articles on DEV Community by Axo (@axo4321).</description>
    <link>https://dev.to/axo4321</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%2F3874358%2F08169e0e-8a95-4f78-8459-94c0b70f1c54.jpg</url>
      <title>DEV Community: Axo</title>
      <link>https://dev.to/axo4321</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/axo4321"/>
    <language>en</language>
    <item>
      <title>I am Building a Fitness Dashboard</title>
      <dc:creator>Axo</dc:creator>
      <pubDate>Sun, 03 May 2026 06:57:30 +0000</pubDate>
      <link>https://dev.to/axo4321/i-am-building-a-fitness-dashboard-4o5b</link>
      <guid>https://dev.to/axo4321/i-am-building-a-fitness-dashboard-4o5b</guid>
      <description>&lt;p&gt;A few weeks ago I had no idea what Gunicorn was, had never touched PostgreSQL, and had never written a single line of Django. This week I connected a live fitness API to a web app I built from scratch and generated a downloadable shareable card with real data on it. That feels pretty wild to say out loud.&lt;/p&gt;

&lt;p&gt;Let me back up and explain what I have been building, because I think the concept is actually kind of interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏋️ The Idea: A Fitness Identity Card
&lt;/h2&gt;

&lt;p&gt;While researching project ideas, I kept coming back to apps like Spotify Wrapped, that end of year card everyone shares on social media. I wanted to make something like that but for fitness. Something where you connect your Strava or Fitbit account, pick which stats matter to you (total distance, longest run, active days, elevation gained, etc.), arrange them however you want, and then share a link or download a card image. I am calling it FitCard.&lt;/p&gt;

&lt;p&gt;The gap I noticed is that nothing like this really exists in a clean, social friendly way. There are stat trackers out there, but none of them give you a fully personalized shareable card you could post on Instagram or hand to a recruiter as proof you actually follow through on things.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 The Part That Broke My Brain: OAuth
&lt;/h2&gt;

&lt;p&gt;Getting Strava connected was honestly the hardest part of the whole week. Not because the code was complicated, but because I did not fully understand what OAuth actually was before I started.&lt;/p&gt;

&lt;p&gt;Here is the short version of what I learned: OAuth is a system where instead of giving your password to a third party app, you get redirected to the original service (Strava, in this case), you approve access there, and then Strava hands back a token to my app. That token is what I use to make API calls on your behalf. No passwords stored, no security nightmare.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The first time the redirect worked and I saw "Strava Connected" show up on my dashboard, I genuinely did not believe it worked on the first try.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once I had the token I could call Strava's API and pull back real stats. Here is basically what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.strava.com/api/v3/athletes/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;athlete_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/stats&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fact that a few lines of Python can reach out to Strava's servers, grab someone's running history, and display it on a page I built still kind of amazes me.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎛️ Making It Feel Like a Real Product: Drag and Drop
&lt;/h2&gt;

&lt;p&gt;One of the features I really wanted was the ability to customize which widgets show on your card and arrange them however you want, kind of like how you can move apps around on an iPhone home screen. I used a JavaScript library called SortableJS for this, which handles all the drag logic. I just had to wire it up to save the new positions back to the database whenever you drop a widget in a new spot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Sortable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ghostClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sortable-ghost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onEnd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// save new positions to the database&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I did not expect was how satisfying that would feel to use. Dragging a widget, watching it snap into place, refreshing the page and seeing it stay. That is when it started feeling like a real app rather than a class project.&lt;/p&gt;

&lt;h2&gt;
  
  
  🖼️ The Downloadable Card
&lt;/h2&gt;

&lt;p&gt;The last piece this week was generating an actual downloadable image of your FitCard using a Python library called Pillow. This was different from everything else I had done because instead of building a web page, I was drawing pixels. Laying out text, colors, and shapes programmatically onto a canvas and then saving it as a PNG file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;draw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageDraw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FitCard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;229&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;font_large&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My first version had a thick black border around the card that looked terrible. Fixing it was a two line change, but it is the kind of thing you only notice when you actually look at the output. That is a lesson I keep relearning: you have to test your own work with fresh eyes.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 What's Coming Next
&lt;/h2&gt;

&lt;p&gt;The app works but there is still a lot left to do. The VM's IP address keeps changing every time I restart it, which is annoying and something I need to fix with a static IP. I also want to add support for a second fitness platform and make sure the public profile page shows real data instead of placeholder values.&lt;/p&gt;

&lt;p&gt;But the core loop works: connect an account, pick your widgets, arrange them, view your public card, download the image. For three weeks of work starting from zero Django knowledge, I am pretty happy with where this is.&lt;/p&gt;

&lt;p&gt;Thanks for reading. More updates coming as the project continues.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I am Building a Fitness Dashboard</title>
      <dc:creator>Axo</dc:creator>
      <pubDate>Sun, 03 May 2026 06:57:30 +0000</pubDate>
      <link>https://dev.to/axo4321/i-am-building-a-fitness-dashboard-h1c</link>
      <guid>https://dev.to/axo4321/i-am-building-a-fitness-dashboard-h1c</guid>
      <description>&lt;p&gt;A few weeks ago I had no idea what Gunicorn was, had never touched PostgreSQL, and had never written a single line of Django. This week I connected a live fitness API to a web app I built from scratch and generated a downloadable shareable card with real data on it. That feels pretty wild to say out loud.&lt;/p&gt;

&lt;p&gt;Let me back up and explain what I have been building, because I think the concept is actually kind of interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏋️ The Idea: A Fitness Identity Card
&lt;/h2&gt;

&lt;p&gt;While researching project ideas, I kept coming back to apps like Spotify Wrapped, that end of year card everyone shares on social media. I wanted to make something like that but for fitness. Something where you connect your Strava or Fitbit account, pick which stats matter to you (total distance, longest run, active days, elevation gained, etc.), arrange them however you want, and then share a link or download a card image. I am calling it FitCard.&lt;/p&gt;

&lt;p&gt;The gap I noticed is that nothing like this really exists in a clean, social friendly way. There are stat trackers out there, but none of them give you a fully personalized shareable card you could post on Instagram or hand to a recruiter as proof you actually follow through on things.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 The Part That Broke My Brain: OAuth
&lt;/h2&gt;

&lt;p&gt;Getting Strava connected was honestly the hardest part of the whole week. Not because the code was complicated, but because I did not fully understand what OAuth actually was before I started.&lt;/p&gt;

&lt;p&gt;Here is the short version of what I learned: OAuth is a system where instead of giving your password to a third party app, you get redirected to the original service (Strava, in this case), you approve access there, and then Strava hands back a token to my app. That token is what I use to make API calls on your behalf. No passwords stored, no security nightmare.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The first time the redirect worked and I saw "Strava Connected" show up on my dashboard, I genuinely did not believe it worked on the first try.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once I had the token I could call Strava's API and pull back real stats. Here is basically what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.strava.com/api/v3/athletes/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;athlete_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/stats&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fact that a few lines of Python can reach out to Strava's servers, grab someone's running history, and display it on a page I built still kind of amazes me.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎛️ Making It Feel Like a Real Product: Drag and Drop
&lt;/h2&gt;

&lt;p&gt;One of the features I really wanted was the ability to customize which widgets show on your card and arrange them however you want, kind of like how you can move apps around on an iPhone home screen. I used a JavaScript library called SortableJS for this, which handles all the drag logic. I just had to wire it up to save the new positions back to the database whenever you drop a widget in a new spot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Sortable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ghostClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sortable-ghost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onEnd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// save new positions to the database&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I did not expect was how satisfying that would feel to use. Dragging a widget, watching it snap into place, refreshing the page and seeing it stay. That is when it started feeling like a real app rather than a class project.&lt;/p&gt;

&lt;h2&gt;
  
  
  🖼️ The Downloadable Card
&lt;/h2&gt;

&lt;p&gt;The last piece this week was generating an actual downloadable image of your FitCard using a Python library called Pillow. This was different from everything else I had done because instead of building a web page, I was drawing pixels. Laying out text, colors, and shapes programmatically onto a canvas and then saving it as a PNG file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;draw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageDraw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FitCard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;229&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;font_large&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My first version had a thick black border around the card that looked terrible. Fixing it was a two line change, but it is the kind of thing you only notice when you actually look at the output. That is a lesson I keep relearning: you have to test your own work with fresh eyes.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 What's Coming Next
&lt;/h2&gt;

&lt;p&gt;The app works but there is still a lot left to do. The VM's IP address keeps changing every time I restart it, which is annoying and something I need to fix with a static IP. I also want to add support for a second fitness platform and make sure the public profile page shows real data instead of placeholder values.&lt;/p&gt;

&lt;p&gt;But the core loop works: connect an account, pick your widgets, arrange them, view your public card, download the image. For three weeks of work starting from zero Django knowledge, I am pretty happy with where this is.&lt;/p&gt;

&lt;p&gt;Thanks for reading. More updates coming as the project continues.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>sudo - Power Tool, Not a Magic Fix</title>
      <dc:creator>Axo</dc:creator>
      <pubDate>Sun, 12 Apr 2026 04:45:10 +0000</pubDate>
      <link>https://dev.to/axo4321/sudo-power-tool-not-a-magic-fix-1lgo</link>
      <guid>https://dev.to/axo4321/sudo-power-tool-not-a-magic-fix-1lgo</guid>
      <description>&lt;p&gt;If you've spent any time in a Linux terminal, you've typed &lt;code&gt;sudo&lt;/code&gt; in front of a command. Maybe it was because something was blocked, maybe someone told you to, or maybe you just picked up the habit. Either way, most beginners use it constantly without really thinking about what it's doing.&lt;/p&gt;

&lt;p&gt;So let's talk about it. What &lt;code&gt;sudo&lt;/code&gt; actually is, when you should reach for it, and where it can genuinely get you into trouble.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 What You're Actually Doing When You Type &lt;code&gt;sudo&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sudo&lt;/code&gt; stands for &lt;strong&gt;"superuser do."&lt;/strong&gt; When you put it in front of a command, you're telling Linux to run that command as the root user, the most powerful account on the Root can read, modify, or delete anything. No file is off limits, no permission can stop it, and nothing it does is automatically undoable.&lt;/p&gt;

&lt;p&gt;That's a lot of power to invoke casually.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ When &lt;code&gt;sudo&lt;/code&gt; Makes Sense
&lt;/h2&gt;

&lt;p&gt;There are plenty of situations where &lt;code&gt;sudo&lt;/code&gt; is exactly the right tool. Installing software, editing system configuration files, managing users, restarting services. These all genuinely require elevated privileges and &lt;code&gt;sudo&lt;/code&gt; is the correct way to get them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx
&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/hosts
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The common thread is that these are all tasks that affect the system beyond your own user space. That's the right mental bar to clear before reaching for &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ When People Misuse It
&lt;/h2&gt;

&lt;p&gt;The most common mistake beginners make is using &lt;code&gt;sudo&lt;/code&gt; as a shortcut whenever they hit a Permission Denied error. That error exists for a reason. The system is telling you that your current user isn't supposed to be doing that thing, and the correct response is to ask &lt;em&gt;why&lt;/em&gt;, not to bulldoze through it with root privileges.&lt;/p&gt;

&lt;p&gt;The second big mistake is running commands you don't fully understand and adding &lt;code&gt;sudo&lt;/code&gt; to make them work. That's genuinely risky. If you copied a command from the internet and can't explain what every part of it does, adding &lt;code&gt;sudo&lt;/code&gt; to it is not the move.&lt;/p&gt;




&lt;h2&gt;
  
  
  💀 The Commands Worth Being Careful With
&lt;/h2&gt;

&lt;p&gt;A few combinations are worth knowing about specifically because they go from useful to catastrophic very quickly with root access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This deletes everything on the system. No confirmation prompt, no warning, no recovery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 777 /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This strips all permission restrictions from the entire filesystem, leaving your system wide open.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo dd &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This wipes your hard drive completely by overwriting it with zeros.&lt;/p&gt;

&lt;p&gt;None of these commands will ask if you're sure. Linux assumes you know what you're doing.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠  The Simple Rule
&lt;/h2&gt;

&lt;p&gt;If something works fine without &lt;code&gt;sudo&lt;/code&gt;, don't add it. Reach for it only when the system genuinely requires elevated privileges, and when you do, read the full command twice before you hit Enter. Root doesn't do second chances.&lt;/p&gt;




</description>
      <category>linux</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
