<?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.us-east-2.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>Learning How AI Can Reverse Engineer Software</title>
      <dc:creator>Axo</dc:creator>
      <pubDate>Thu, 15 Oct 2026 06:59:37 +0000</pubDate>
      <link>https://dev.to/axo4321/learning-how-ai-can-reverse-engineer-software-184c</link>
      <guid>https://dev.to/axo4321/learning-how-ai-can-reverse-engineer-software-184c</guid>
      <description>&lt;p&gt;Reverse engineering has always looked intimidating from the outside. It usually means reading assembly, learning heavy tools like Ghidra or IDA, and spending hours tracing code by hand. Recently I came across an open source project called REA that connects AI agents to those same tools, so you can ask questions about a program in plain English and get answers back with evidence attached.&lt;/p&gt;

&lt;p&gt;In this post I break down what REA is, how it works under the hood, what it can analyze, how to set it up, and what every beginner should know before trying it, including how to stay on the right side of the law.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 The Idea: Reverse Engineer Anything
&lt;/h2&gt;

&lt;p&gt;Reverse engineering is figuring out how software works when you do not have its source code. Security teams use it to pick apart malware, researchers use it to find vulnerabilities, and developers use it to make old software talk to new systems. As a networking and server admin student leaning toward cybersecurity, it is a skill I kept seeing on job postings and kept avoiding because the learning curve looked like a cliff.&lt;/p&gt;

&lt;p&gt;Then I found &lt;a href="https://github.com/morluto/rea" rel="noopener noreferrer"&gt;REA (Reverse Engineer Anything)&lt;/a&gt;, an open source, MIT licensed project that connects AI agents like Claude Code, Codex, Cursor and Gemini CLI to real reverse engineering tools. Instead of memorizing every menu in Ghidra, you ask your agent a question in plain English. The agent calls REA, REA runs the heavy tools on your own machine, and you get findings back along with the evidence and limitations behind each conclusion.&lt;/p&gt;

&lt;p&gt;What surprised me most is how much it covers. Here are the targets that stood out to me:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;What REA gives back&lt;/th&gt;
&lt;th&gt;What you need&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Native binaries&lt;/td&gt;
&lt;td&gt;Pseudocode, assembly, strings, symbols, calls and references&lt;/td&gt;
&lt;td&gt;Ghidra (free), Hopper or IDA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript and Electron apps&lt;/td&gt;
&lt;td&gt;Modules, imports, routes and IPC between processes&lt;/td&gt;
&lt;td&gt;Just Node.js and npm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET assemblies&lt;/td&gt;
&lt;td&gt;Metadata and CIL instructions&lt;/td&gt;
&lt;td&gt;Nothing extra, static analysis only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android APKs&lt;/td&gt;
&lt;td&gt;Manifest, classes and decompiled methods&lt;/td&gt;
&lt;td&gt;JADX and a full JDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Packet summaries&lt;/td&gt;
&lt;td&gt;Endpoints, DNS, TLS SNI and protocol breakdown&lt;/td&gt;
&lt;td&gt;tshark and capinfos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That last row is the one that got me as a networking student. The same agent that reads a binary can also summarize a packet capture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/morluto/rea" rel="noopener noreferrer"&gt;Source: REA README&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The concept that took me the longest to understand was how an AI chatbot could suddenly "use" a program like Ghidra.&lt;/p&gt;

&lt;p&gt;Here is the short version of what I learned. MCP stands for Model Context Protocol, and it is a standard way for an AI agent to call outside tools. On its own, an AI model can only read and write text, so if you paste in some assembly it is basically guessing. REA runs as a local MCP server that offers the agent a set of tools, things like "decompile this function" or "list the strings in this file." The loop looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You ask your agent a question about a program.&lt;/li&gt;
&lt;li&gt;The agent picks a REA tool and calls it through MCP.&lt;/li&gt;
&lt;li&gt;REA runs Ghidra (or another engine) locally against the file.&lt;/li&gt;
&lt;li&gt;REA sends back pseudocode, assembly and references, plus what it could not confirm.&lt;/li&gt;
&lt;li&gt;The agent reads the evidence, asks follow up questions, and explains it to you.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;The moment it clicked for me: the AI is not making up what the program does. It is reading the same evidence a human reverse engineer would read, just a lot faster.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That "what it could not confirm" part matters more than I expected. AI models can sound confident while being wrong, so a tool that reports its own unknowns keeps both you and the agent honest.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Getting It Running
&lt;/h2&gt;

&lt;p&gt;REA needs Node.js and npm. The supported versions are Node 22 (22.19 or newer), Node 24 (24.11 or newer), or Node 26 and up. For native binaries you also need an analysis engine such as Ghidra, Hopper or IDA. Ghidra is the easiest place for a beginner to start because it is free. Setup is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rea-agents setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It asks which agents you use, shows you the changes it wants to make, and backs up your existing config before adding the REA MCP server. After that you restart your agent and it can use the new tools.&lt;/p&gt;

&lt;p&gt;If you want the &lt;code&gt;rea&lt;/code&gt; command in your terminal for regular use, you can install it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; rea-agents
rea &lt;span class="nt"&gt;--help&lt;/span&gt;
rea update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One gotcha to watch for on Linux: Ghidra and the JavaScript analysis need a procps compatible &lt;code&gt;ps&lt;/code&gt; command on your PATH, so if things fail on a minimal VM, check that first.&lt;/p&gt;

&lt;p&gt;One more thing I did not expect to learn from a README: the project warns that copycat repos with similar names exist, and you should only install from the official GitHub repo, rea.tools, or the &lt;code&gt;rea-agents&lt;/code&gt; npm package. That is a real supply chain attack lesson hiding inside an install guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 How You Actually Use It
&lt;/h2&gt;

&lt;p&gt;There are two ways to work with REA. The first is through your AI agent. After setup, you describe what you want to understand in plain English, and the agent decides which REA tools to call. A prompt might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain how the clipboard feature in this app works, show me the evidence,
and list anything you could not confirm.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second way is the terminal, which runs the same workflows without an agent. For example, this command inspects an extracted JavaScript or Electron app and needs no native analysis engine at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; rea-agents@latest analyze-javascript-application /absolute/path/to/app &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to the docs, the output lists the app's modules, imports and Electron boundaries, along with the evidence for each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 A Core Skill: Spotting Known Algorithms
&lt;/h2&gt;

&lt;p&gt;Whether a person or an AI is doing the analysis, one of the most useful reverse engineering tricks is recognizing well known algorithms by their fingerprints. Compiling throws away comments, and stripping a binary removes function names, but neither can hide the math. Here is a classic example, a string hash called djb2, written in C:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;djb2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5381&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;h&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;Once this is compiled and stripped, the name djb2 is gone. What survives in the pseudocode or assembly are two clues: the starting value 5381, and a shift left by 5 followed by an add, which is just a fast way to multiply by 33. Someone who knows those clues can name the function in seconds, and an agent reading evidence from REA can match them the same way. Other famous constants work like this too, such as 0x67452301 at the start of MD5 and SHA-1, or 0xEDB88320 in CRC32.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compilers erase names, but they cannot erase math. That is why constants are one of the first things reverse engineers look for.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Identifying an algorithm is only half the job. The other half is proving it, by running the original program and a rewritten version on the same inputs and checking that the outputs match.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 What I Learned (Including Staying Legal)
&lt;/h2&gt;

&lt;p&gt;The biggest takeaway is that AI does not replace understanding, it speeds it up. An agent can find an answer fast, but testing that answer against the original program is what proves it. Skip that step and you are just trusting a confident sounding paragraph.&lt;/p&gt;

&lt;p&gt;The second lesson is about responsibility, because reverse engineering tools can be misused:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Only analyze what you own or are authorized to examine.&lt;/strong&gt; The REA project says it is meant for lawful research, education, interoperability, software preservation, and software you own or have permission to analyze. Software license agreements and laws can restrict reverse engineering, so practicing on your own programs or on CTF challenges is the safe move.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use legit tools.&lt;/strong&gt; REA does not come with licenses for paid tools like IDA, Hopper or JEB, and the project is clear that cracked copies and stolen keys are not okay. Ghidra is free, which makes it perfect for students.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Think about your data.&lt;/strong&gt; REA runs the analysis locally, but the results still go to your agent, and the AI provider behind it has its own data policy. I would not feed it anything from work or school that I am not allowed to share.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Next, I want to dig into the packet capture side of REA, since that ties straight into my networking classes. I also want to work through beginner reverse engineering challenges on &lt;a href="https://picoctf.org/" rel="noopener noreferrer"&gt;picoCTF&lt;/a&gt;, where breaking things is the whole point and completely allowed.&lt;/p&gt;

&lt;p&gt;If you want to see what this looks like on real software, the &lt;a href="https://rea.tools/showcase/" rel="noopener noreferrer"&gt;REA showcases&lt;/a&gt; are worth reading. In one, someone traced a sound calculation in the old game DX Ball and rebuilt it in C so accurately that it passes 3,205 test cases against the original x86 code. Another follows how the Notion desktop app moves clipboard data between its processes. They are a great example of the verify step done at scale.&lt;/p&gt;

&lt;p&gt;The core idea is simple: ask a question, let the agent gather evidence with REA, then verify the answer yourself. That loop makes a field that once felt out of reach a lot more approachable for beginners.&lt;/p&gt;

&lt;p&gt;Thanks for reading. More updates coming as I keep digging in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt; &lt;a href="https://github.com/morluto/rea" rel="noopener noreferrer"&gt;REA on GitHub&lt;/a&gt; · &lt;a href="https://rea.tools/" rel="noopener noreferrer"&gt;rea.tools&lt;/a&gt; · &lt;a href="https://ghidra-sre.org/" rel="noopener noreferrer"&gt;Ghidra&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>learning</category>
      <category>opensource</category>
      <category>security</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-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>
