<?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: Ashan_Dev</title>
    <description>The latest articles on DEV Community by Ashan_Dev (@itxashancode).</description>
    <link>https://dev.to/itxashancode</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%2F3805543%2F94c4e4f9-f52f-4d60-8cff-8e66d793256b.png</url>
      <title>DEV Community: Ashan_Dev</title>
      <link>https://dev.to/itxashancode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/itxashancode"/>
    <language>en</language>
    <item>
      <title>Google I/O 2026: My Annotated Field Notes (The Version They Don't Tweet)</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Wed, 20 May 2026 10:39:55 +0000</pubDate>
      <link>https://dev.to/itxashancode/google-io-2026-my-annotated-field-notes-the-version-they-dont-tweet-32h2</link>
      <guid>https://dev.to/itxashancode/google-io-2026-my-annotated-field-notes-the-version-they-dont-tweet-32h2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-io-writing-2026-05-19"&gt;Google I/O 2026 Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I took notes during Google I/O the way I take notes during any conference — obsessively, out of order, with a lot of question marks.&lt;/p&gt;

&lt;p&gt;What follows isn't a summary. Summaries flatten everything to equal importance, and not everything announced this week has equal importance. This is closer to a field guide: what I noticed, what I tested, what confused me, and what I think is actually worth your time.&lt;/p&gt;

&lt;p&gt;I'll be specific where I can. Where I'm speculating, I'll say so.&lt;/p&gt;




&lt;h2&gt;
  
  
  The context window is real. The reasoning is not automatically better.
&lt;/h2&gt;

&lt;p&gt;Gemini's 2 million token context window is not a marketing number. I fed it a full production codebase — about 180,000 tokens of actual working code, not a demo project — and it didn't choke. It loaded. It answered questions about files I hadn't mentioned.&lt;/p&gt;

&lt;p&gt;Here's the problem: &lt;strong&gt;big context and good reasoning are not the same thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I asked it to find the source of an intermittent bug. It gave me a confident, detailed, structurally convincing answer. The answer was wrong. Not slightly wrong — completely fabricated. It invented a race condition that matched the symptom description so well that I spent 40 minutes verifying it before accepting that the race condition didn't exist.&lt;/p&gt;

&lt;p&gt;The actual bug was a missing &lt;code&gt;await&lt;/code&gt; in a file I hadn't explicitly mentioned.&lt;/p&gt;

&lt;p&gt;Long context makes hallucinations &lt;em&gt;harder to catch&lt;/em&gt;, not less frequent. The model has more material to build a plausible-sounding wrong answer from. Keep that in mind before you dump your entire monorepo into the prompt.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Practical note:&lt;/strong&gt; Use long context for retrieval-style questions ("does this codebase have any usage of X?") not for debugging or reasoning tasks. The former works well. The latter is a confidence trap.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Agents went from demo toy to something I'd actually deploy
&lt;/h2&gt;

&lt;p&gt;I've been skeptical of "AI agents" since the phrase entered the hype cycle. Most implementations I've seen are just chains of API calls with a marketing layer on top.&lt;/p&gt;

&lt;p&gt;The Gemini agent demos at I/O this year were different in one concrete way: &lt;strong&gt;error recovery&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Previous agent demos I've watched fail gracefully — they stop, report the error, wait for a human. These ones rerouted. Not always correctly, but they rerouted. The agent assigned to pull data from a malformed JSON endpoint didn't quit — it tried a fallback, logged why, and continued with partial data.&lt;/p&gt;

&lt;p&gt;That's the behavior that makes agents actually useful in production. Not perfect execution. Graceful degradation.&lt;/p&gt;

&lt;p&gt;I haven't run this on my own infrastructure yet. The session I'm watching is the &lt;a href="https://io.google/2026/explore/session-types/keynotes-and-announcements/" rel="noopener noreferrer"&gt;What's New in Google AI&lt;/a&gt; stream from May 19. I'll update this after I test it on a real task this week.&lt;/p&gt;




&lt;h2&gt;
  
  
  Google AI Studio: the tool the developer relations team isn't talking about enough
&lt;/h2&gt;

&lt;p&gt;Everyone covered the Gemini API features. Almost nobody covered the quality-of-life changes to AI Studio itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session persistence.&lt;/strong&gt; This is the one that changed how I work. AI Studio now holds context between turns in a way that feels stateful — you can leave a session, come back, ask a tangentially unrelated question, return to the original task, and it still knows what you were building. I don't know if this is a context management trick or something deeper in the session architecture. What I know is that I stopped having to paste my component spec back into the chat every time I changed tabs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side-by-side diff view.&lt;/strong&gt; When you ask it to revise code, it now shows you what changed instead of just the full rewrite. Obvious feature in hindsight. Surprisingly rare before now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Direct API export.&lt;/strong&gt; You can take any successful Studio session and export it as a curl command, Python snippet, or Node.js call with one click. Sounds small. Cuts about 15 minutes out of every "ok this worked in Studio, now how do I reproduce it in my app" workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Firebase security rules + Gemini: the announcement I'm watching most carefully
&lt;/h2&gt;

&lt;p&gt;Firebase security rules are where junior devs make expensive mistakes and senior devs still have to be careful. The rules syntax is specific, the failure modes are security holes that don't announce themselves, and the feedback loop is terrible — you write rules, deploy, and find out months later that a path was too permissive.&lt;/p&gt;

&lt;p&gt;Google announced Gemini integration that can analyze your rules against your data model and flag mismatches.&lt;/p&gt;

&lt;p&gt;I haven't tested this. I want to test this. My hesitation is that "AI reads your security rules" could mean one of two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It does a pattern check against known antipatterns (useful, limited)&lt;/li&gt;
&lt;li&gt;It actually understands the relationship between your schema and your rules and flags the specific path where a user could read someone else's data (very useful, hard to build)
I'll find out next week on a project where the rules have been making me nervous for two months.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The thing nobody's calling out: Google is betting on the API layer
&lt;/h2&gt;

&lt;p&gt;Read the I/O announcements as a product person, not a developer, and something becomes clear: Google is not trying to win the UI layer. Gemini isn't competing with ChatGPT for consumer mindshare as its primary goal. The goal is the API and infrastructure layer — the part that sits underneath every product you build.&lt;/p&gt;

&lt;p&gt;AI Studio, Firebase integration, Vertex AI updates, the Gemini API in Android Studio — these are all targeting the developer who is building &lt;em&gt;something else&lt;/em&gt; and needs AI infrastructure underneath it.&lt;/p&gt;

&lt;p&gt;This is smart for Google and slightly uncomfortable if you're a startup building AI-native tools on top of Google's APIs. The infrastructure provider and the application layer are getting closer together.&lt;/p&gt;

&lt;p&gt;Not saying it's bad. Just worth knowing when you're making architectural decisions.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'm actually going to use this week
&lt;/h2&gt;

&lt;p&gt;In order of how likely I am to get to it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AI Studio with session persistence&lt;/strong&gt; — replacing my current workflow of pasting context into every new conversation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-context code review&lt;/strong&gt; — specifically for retrieval questions, not reasoning. "Find all places where we're not handling the error case in async functions."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase rules analysis&lt;/strong&gt; — one real project, one set of rules I've been nervous about&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 1.5 Pro API&lt;/strong&gt; — I have a document processing task that's been barely within the 1M token limit. 2M gives me room.
I'm skipping the agent stuff for now. Not because it's uninteresting — because the agent architecture I'd want to use it in doesn't exist yet in my stack. That's a me problem, not a Google problem.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The honest summary
&lt;/h2&gt;

&lt;p&gt;Google I/O 2026 was a solid developer conference with a few genuinely useful announcements buried under a lot of infrastructure noise that only matters if you're running things at scale.&lt;/p&gt;

&lt;p&gt;The useful stuff: AI Studio improvements, the actual behavior of agent error recovery, the Firebase rules analysis if it's as deep as the demo implied.&lt;/p&gt;

&lt;p&gt;The stuff I'll check back on in six months: the 2M token context window for reasoning tasks (I expect the model quality to improve, not just the window size), and anything involving on-device Gemini Nano — interesting in theory, and I've been burned enough times by "on-device AI" claims to wait for real-world latency numbers.&lt;/p&gt;

&lt;p&gt;If you want to watch the sessions yourself: the &lt;a href="https://io.google/2026" rel="noopener noreferrer"&gt;Google I/O session explorer&lt;/a&gt; has everything. The Gemini API session and the What's New in Google AI keynote are the two I'd start with if you're a developer who doesn't have six hours.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'll update this post after I test the Firebase rules integration. Probably Thursday.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you spotted something in the sessions I missed, drop it in the comments — I'm specifically curious if anyone tested the on-device Gemini features on non-Pixel hardware.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>googleiochallenge</category>
      <category>webdev</category>
      <category>gemini</category>
    </item>
    <item>
      <title>I Got Tired of AI Black Boxes So I Built One You Can Break Into</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Wed, 13 May 2026 05:39:33 +0000</pubDate>
      <link>https://dev.to/itxashancode/i-got-tired-of-ai-black-boxes-so-i-built-one-you-can-break-into-295n</link>
      <guid>https://dev.to/itxashancode/i-got-tired-of-ai-black-boxes-so-i-built-one-you-can-break-into-295n</guid>
      <description>&lt;h2&gt;
  
  
  Dead Star AI — A Human-in-the-Loop Reasoning Engine Built on Gemma 4
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is my submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Build with Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




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

&lt;p&gt;I work with LLMs constantly and I've hit the same wall dozens of times. You write a careful prompt, attach a complex diagram, and wait. If the model misreads one assumption in the middle of its reasoning, the final answer is wrong and you have no idea where. You just try again.&lt;/p&gt;

&lt;p&gt;Dead Star AI is what I built to fix that.&lt;/p&gt;

&lt;p&gt;It's not a chatbot. When you give it a problem, it streams its reasoning into discrete logic nodes on your screen before generating an answer. And before it commits to that answer, it stops — and gives you the keyboard back.&lt;/p&gt;

&lt;p&gt;You can click any reasoning node and rewrite it. If the model misread your database schema from an image upload, you fix that node directly, hit &lt;strong&gt;Commit Intelligence&lt;/strong&gt;, and the final answer gets generated from your corrected reasoning — not as a patch, but as the actual starting point.&lt;/p&gt;

&lt;p&gt;There's also an &lt;strong&gt;Influence Score&lt;/strong&gt; that uses a custom diffing algorithm to show exactly how much your edits changed the output. Small feature, but it makes the whole thing feel less like prompting and more like actual collaboration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live app:&lt;/strong&gt; &lt;a href="https://deadstarai.vercel.app" rel="noopener noreferrer"&gt;https://deadstarai.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fastest way to see it work: click &lt;strong&gt;"Analyze System Architecture"&lt;/strong&gt; on the home screen, wait for the reasoning nodes to load, then intercept one and rewrite it. That's the whole idea in about 30 seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/itxashancode/Dead-Star-AI" rel="noopener noreferrer"&gt;GitHub →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Worth looking at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app/api/think/route.ts&lt;/code&gt; and &lt;code&gt;app/api/answer/route.ts&lt;/code&gt; — the two-pass reasoning pipeline&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/diff.ts&lt;/code&gt; — the diffing algorithm behind the Influence Score&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/security.ts&lt;/code&gt; — Edge rate-limiting and prompt sanitization&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Two-Pass Pipeline
&lt;/h3&gt;

&lt;p&gt;Most LLM apps make one API call and display the result. Dead Star makes two, intentionally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Input + Image
       │
       ▼
 /api/think ──► Gemma 4 streams &amp;lt;|think|&amp;gt; tokens
       │               │
       │        Reasoning Nodes
       │        rendered in UI
       │               │
       │        User edits nodes
       │               │
       ▼               ▼
 /api/answer ◄── Corrected reasoning
       │         fed back as context
       ▼
  Final Answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass one (&lt;code&gt;/api/think&lt;/code&gt;) extracts Gemma 4's raw &lt;code&gt;&amp;lt;|think|&amp;gt;&lt;/code&gt; reasoning and streams it directly to the UI as editable components. Pass two (&lt;code&gt;/api/answer&lt;/code&gt;) takes whatever the user left in those nodes — corrected or not — and synthesizes the final response from that shared context.&lt;/p&gt;

&lt;p&gt;The model doesn't know you edited its thoughts. It just reasons from what's in the context window.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Influence Score
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/diff.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateInfluenceScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="nx"&gt;edited&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;changes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computeDiff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;edited&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;changes&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&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;Every character change between Gemma's original reasoning and your edited version gets tracked. The final score tells you what percentage of the reasoning was yours. A 0% score means you let the model run clean. An 80% score means you basically rewrote the logic and used Gemma to execute your thinking.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Used Gemma 4
&lt;/h2&gt;

&lt;p&gt;The app routes between &lt;code&gt;gemma-4-31b-it&lt;/code&gt; and &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; with an 8-model failover chain. The 31B Dense model runs as primary for two reasons: multimodal vision and 128k context depth.&lt;/p&gt;

&lt;p&gt;Users upload messy architecture diagrams and large code dumps. Smaller models lose coherence under that kind of load. The 31B holds the thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gemma 4 Features Used
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;How&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Multimodal (vision)&lt;/td&gt;
&lt;td&gt;✅ Active&lt;/td&gt;
&lt;td&gt;Images encoded as &lt;code&gt;inlineData&lt;/code&gt; and passed through both API passes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long context (128k)&lt;/td&gt;
&lt;td&gt;✅ Active&lt;/td&gt;
&lt;td&gt;Full conversation history + edited reasoning nodes held in context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;`&amp;lt;\&lt;/td&gt;
&lt;td&gt;think\&lt;/td&gt;
&lt;td&gt;&amp;gt;` tags&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Function calling&lt;/td&gt;
&lt;td&gt;✅ Active&lt;/td&gt;
&lt;td&gt;Gemma triggers Tavily web search autonomously mid-reasoning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model failover&lt;/td&gt;
&lt;td&gt;✅ Active&lt;/td&gt;
&lt;td&gt;31B Dense → 26B MoE → fallback chain across 8 configurations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Function Calling in the UI
&lt;/h3&gt;

&lt;p&gt;When a prompt requires live data, Gemma decides mid-reasoning to call the search tool. A glowing blue &lt;strong&gt;Action Node&lt;/strong&gt; shows up in the thought stream the moment that decision happens — before the answer, during the thinking. You can see the model acting as an agent in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────┐
│                 Next.js App                  │
│                                             │
│  ┌──────────┐    ┌───────────────────────┐  │
│  │ ChatInput│    │   Intelligence Lab    │  │
│  │ + Images │───►│   (Reasoning Nodes)   │  │
│  └──────────┘    │   - ThoughtNode       │  │
│                  │   - ActionNode        │  │
│  ┌──────────┐    │   - [editable]        │  │
│  │  Answer  │◄───└───────────────────────┘  │
│  │  Panel   │              │                │
│  └──────────┘              ▼                │
│                    useReasoningEngine        │
└─────────────────────────────────────────────┘
          │                   │
          ▼                   ▼
   /api/think           /api/answer
   (Gemma 4 31B)        (Gemma 4 31B)
          │
          ▼
   lib/security.ts
   - Upstash Redis rate limiting (Edge)
   - CORS origin validation
   - Prompt sanitization
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Edge Security
&lt;/h3&gt;

&lt;p&gt;Most hackathon projects skip this entirely. Dead Star runs global rate limiting via Upstash Redis at the Edge runtime level — before any request reaches the model. CORS validation locks the API to the production origin. Prompt content gets sanitized before it touches the model context.&lt;/p&gt;

&lt;p&gt;It's not exciting to write about but it's the difference between a demo and something you'd actually deploy.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;p&gt;The on-device inference angle is missing. The app is entirely API-based right now. Adding a toggle to route to a local Ollama endpoint (&lt;code&gt;http://localhost:11434/v1&lt;/code&gt;) would let privacy-sensitive users run the whole thing without their data leaving their machine. That's on the roadmap.&lt;/p&gt;

&lt;p&gt;The long context window is used but not demonstrated explicitly. A next version would let you drop an entire codebase or research paper into the context and watch the reasoning nodes handle it — that's a more honest showcase of the 128k capability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live:&lt;/strong&gt; &lt;a href="https://deadstarai.vercel.app" rel="noopener noreferrer"&gt;https://deadstarai.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/itxashancode/Dead-Star-AI" rel="noopener noreferrer"&gt;GitHub →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fastest path to the interesting part: load the app, click an example prompt, wait for nodes, intercept one, change something, commit. The Influence Score at the end tells you how much of the final answer was actually yours.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Got Tired of AI Black Boxes So I Built One You Can Break Into</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Wed, 13 May 2026 05:39:33 +0000</pubDate>
      <link>https://dev.to/itxashancode/i-got-tired-of-ai-black-boxes-so-i-built-one-you-can-break-into-3fmj</link>
      <guid>https://dev.to/itxashancode/i-got-tired-of-ai-black-boxes-so-i-built-one-you-can-break-into-3fmj</guid>
      <description>&lt;h2&gt;
  
  
  Dead Star AI — A Human-in-the-Loop Reasoning Engine Built on Gemma 4
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is my submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Build with Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




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

&lt;p&gt;I work with LLMs constantly and I've hit the same wall dozens of times. You write a careful prompt, attach a complex diagram, and wait. If the model misreads one assumption in the middle of its reasoning, the final answer is wrong and you have no idea where. You just try again.&lt;/p&gt;

&lt;p&gt;Dead Star AI is what I built to fix that.&lt;/p&gt;

&lt;p&gt;It's not a chatbot. When you give it a problem, it streams its reasoning into discrete logic nodes on your screen before generating an answer. And before it commits to that answer, it stops — and gives you the keyboard back.&lt;/p&gt;

&lt;p&gt;You can click any reasoning node and rewrite it. If the model misread your database schema from an image upload, you fix that node directly, hit &lt;strong&gt;Commit Intelligence&lt;/strong&gt;, and the final answer gets generated from your corrected reasoning — not as a patch, but as the actual starting point.&lt;/p&gt;

&lt;p&gt;There's also an &lt;strong&gt;Influence Score&lt;/strong&gt; that uses a custom diffing algorithm to show exactly how much your edits changed the output. Small feature, but it makes the whole thing feel less like prompting and more like actual collaboration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live app:&lt;/strong&gt; &lt;a href="https://deadstarai.vercel.app" rel="noopener noreferrer"&gt;https://deadstarai.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fastest way to see it work: click &lt;strong&gt;"Analyze System Architecture"&lt;/strong&gt; on the home screen, wait for the reasoning nodes to load, then intercept one and rewrite it. That's the whole idea in about 30 seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/itxashancode/Dead-Star-AI" rel="noopener noreferrer"&gt;GitHub →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Worth looking at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app/api/think/route.ts&lt;/code&gt; and &lt;code&gt;app/api/answer/route.ts&lt;/code&gt; — the two-pass reasoning pipeline&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/diff.ts&lt;/code&gt; — the diffing algorithm behind the Influence Score&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/security.ts&lt;/code&gt; — Edge rate-limiting and prompt sanitization&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Two-Pass Pipeline
&lt;/h3&gt;

&lt;p&gt;Most LLM apps make one API call and display the result. Dead Star makes two, intentionally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Input + Image
       │
       ▼
 /api/think ──► Gemma 4 streams &amp;lt;|think|&amp;gt; tokens
       │               │
       │        Reasoning Nodes
       │        rendered in UI
       │               │
       │        User edits nodes
       │               │
       ▼               ▼
 /api/answer ◄── Corrected reasoning
       │         fed back as context
       ▼
  Final Answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass one (&lt;code&gt;/api/think&lt;/code&gt;) extracts Gemma 4's raw &lt;code&gt;&amp;lt;|think|&amp;gt;&lt;/code&gt; reasoning and streams it directly to the UI as editable components. Pass two (&lt;code&gt;/api/answer&lt;/code&gt;) takes whatever the user left in those nodes — corrected or not — and synthesizes the final response from that shared context.&lt;/p&gt;

&lt;p&gt;The model doesn't know you edited its thoughts. It just reasons from what's in the context window.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Influence Score
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/diff.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateInfluenceScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="nx"&gt;edited&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;changes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computeDiff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;edited&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;changes&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&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;Every character change between Gemma's original reasoning and your edited version gets tracked. The final score tells you what percentage of the reasoning was yours. A 0% score means you let the model run clean. An 80% score means you basically rewrote the logic and used Gemma to execute your thinking.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Used Gemma 4
&lt;/h2&gt;

&lt;p&gt;The app routes between &lt;code&gt;gemma-4-31b-it&lt;/code&gt; and &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; with an 8-model failover chain. The 31B Dense model runs as primary for two reasons: multimodal vision and 128k context depth.&lt;/p&gt;

&lt;p&gt;Users upload messy architecture diagrams and large code dumps. Smaller models lose coherence under that kind of load. The 31B holds the thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gemma 4 Features Used
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;How&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Multimodal (vision)&lt;/td&gt;
&lt;td&gt;✅ Active&lt;/td&gt;
&lt;td&gt;Images encoded as &lt;code&gt;inlineData&lt;/code&gt; and passed through both API passes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long context (128k)&lt;/td&gt;
&lt;td&gt;✅ Active&lt;/td&gt;
&lt;td&gt;Full conversation history + edited reasoning nodes held in context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;`&amp;lt;\&lt;/td&gt;
&lt;td&gt;think\&lt;/td&gt;
&lt;td&gt;&amp;gt;` tags&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Function calling&lt;/td&gt;
&lt;td&gt;✅ Active&lt;/td&gt;
&lt;td&gt;Gemma triggers Tavily web search autonomously mid-reasoning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model failover&lt;/td&gt;
&lt;td&gt;✅ Active&lt;/td&gt;
&lt;td&gt;31B Dense → 26B MoE → fallback chain across 8 configurations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Function Calling in the UI
&lt;/h3&gt;

&lt;p&gt;When a prompt requires live data, Gemma decides mid-reasoning to call the search tool. A glowing blue &lt;strong&gt;Action Node&lt;/strong&gt; shows up in the thought stream the moment that decision happens — before the answer, during the thinking. You can see the model acting as an agent in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────┐
│                 Next.js App                  │
│                                             │
│  ┌──────────┐    ┌───────────────────────┐  │
│  │ ChatInput│    │   Intelligence Lab    │  │
│  │ + Images │───►│   (Reasoning Nodes)   │  │
│  └──────────┘    │   - ThoughtNode       │  │
│                  │   - ActionNode        │  │
│  ┌──────────┐    │   - [editable]        │  │
│  │  Answer  │◄───└───────────────────────┘  │
│  │  Panel   │              │                │
│  └──────────┘              ▼                │
│                    useReasoningEngine        │
└─────────────────────────────────────────────┘
          │                   │
          ▼                   ▼
   /api/think           /api/answer
   (Gemma 4 31B)        (Gemma 4 31B)
          │
          ▼
   lib/security.ts
   - Upstash Redis rate limiting (Edge)
   - CORS origin validation
   - Prompt sanitization
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Edge Security
&lt;/h3&gt;

&lt;p&gt;Most hackathon projects skip this entirely. Dead Star runs global rate limiting via Upstash Redis at the Edge runtime level — before any request reaches the model. CORS validation locks the API to the production origin. Prompt content gets sanitized before it touches the model context.&lt;/p&gt;

&lt;p&gt;It's not exciting to write about but it's the difference between a demo and something you'd actually deploy.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;p&gt;The on-device inference angle is missing. The app is entirely API-based right now. Adding a toggle to route to a local Ollama endpoint (&lt;code&gt;http://localhost:11434/v1&lt;/code&gt;) would let privacy-sensitive users run the whole thing without their data leaving their machine. That's on the roadmap.&lt;/p&gt;

&lt;p&gt;The long context window is used but not demonstrated explicitly. A next version would let you drop an entire codebase or research paper into the context and watch the reasoning nodes handle it — that's a more honest showcase of the 128k capability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live:&lt;/strong&gt; &lt;a href="https://deadstarai.vercel.app" rel="noopener noreferrer"&gt;https://deadstarai.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/itxashancode/Dead-Star-AI" rel="noopener noreferrer"&gt;GitHub →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fastest path to the interesting part: load the app, click an example prompt, wait for nodes, intercept one, change something, commit. The Influence Score at the end tells you how much of the final answer was actually yours.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Stopped Writing Changelogs Manually — Here's the AI Tool That Does It in Seconds (Free)</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Sat, 18 Apr 2026 23:42:59 +0000</pubDate>
      <link>https://dev.to/itxashancode/i-stopped-writing-changelogs-manually-heres-the-ai-tool-that-does-it-in-seconds-free-12bl</link>
      <guid>https://dev.to/itxashancode/i-stopped-writing-changelogs-manually-heres-the-ai-tool-that-does-it-in-seconds-free-12bl</guid>
      <description>&lt;h2&gt;
  
  
  The Problem Every Developer Ignores Until It's Too Late
&lt;/h2&gt;

&lt;p&gt;You've just merged 47 commits. The sprint is done. Your PM is pinging you for release notes. Your users are waiting for the changelog.&lt;/p&gt;

&lt;p&gt;And you're staring at this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix: edge case in auth
chore: update deps
feat: add stripe webhook
refactor: clean up user service
fix: typo in README
feat: dark mode toggle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now write that as a professional changelog. Go.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yeah. That's what I thought.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Changelogs Are a Developer's Least Favorite Task
&lt;/h2&gt;

&lt;p&gt;Here's why most developers skip or half-ass their changelogs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;strong&gt;Context switching is brutal&lt;/strong&gt; — you just finished coding, now you're a copywriter?&lt;/li&gt;
&lt;li&gt;⏰ &lt;strong&gt;It takes forever&lt;/strong&gt; — reading every commit, grouping them, writing human-readable descriptions&lt;/li&gt;
&lt;li&gt;😴 &lt;strong&gt;It's boring&lt;/strong&gt; — there's no dopamine hit from writing "Fixed authentication edge case in OAuth flow"&lt;/li&gt;
&lt;li&gt;🤷 &lt;strong&gt;Nobody teaches you how&lt;/strong&gt; — there's no "Changelog Writing 101" in CS degrees
So what happens? Developers ship with either:&lt;/li&gt;
&lt;li&gt;No changelog at all&lt;/li&gt;
&lt;li&gt;A raw &lt;code&gt;git log&lt;/code&gt; dump nobody can read&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - A 2-line "bug fixes and improvements" that tells users nothing
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What I Built to Fix This
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;&lt;a href="https://change-log-ai.vercel.app/" rel="noopener noreferrer"&gt;Changelog AI&lt;/a&gt;&lt;/strong&gt; — a free tool that transforms your raw Git commits into three polished formats in seconds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Output Format&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;📋 &lt;strong&gt;Professional Changelog&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Your &lt;code&gt;CHANGELOG.md&lt;/code&gt;, product docs, Notion updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🐙 &lt;strong&gt;GitHub Release Notes&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Paste directly into GitHub Releases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🐦 &lt;strong&gt;Twitter/X Announcement&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Ship updates to your audience instantly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No account needed. No credit card. No 14-day trial. Just open, paste, ship.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works (30-Second Demo)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Copy your commits from terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2 weeks ago"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Paste them into &lt;a href="https://change-log-ai.vercel.app/" rel="noopener noreferrer"&gt;Changelog AI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Click generate. Get this back instantly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## v2.3.0 — What's New&lt;/span&gt;

&lt;span class="gu"&gt;### ✨ New Features&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Dark Mode**&lt;/span&gt; — Full dark mode support across all pages
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Stripe Webhooks**&lt;/span&gt; — Real-time payment event handling now live

&lt;span class="gu"&gt;### 🛠️ Improvements&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Authentication system hardened with edge case handling
&lt;span class="p"&gt;-&lt;/span&gt; User service architecture refactored for better performance

&lt;span class="gu"&gt;### 🐛 Bug Fixes&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Fixed typo in README documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Three clicks and you're done.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Beats Writing It Yourself (Or Using ChatGPT)
&lt;/h2&gt;

&lt;p&gt;I know what you're thinking: &lt;em&gt;"I can just paste my commits into ChatGPT."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can. But here's what Changelog AI does differently:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Purpose-built prompts&lt;/strong&gt; — Generic LLMs give generic output. This is fine-tuned for developer release communication specifically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Three formats in one shot&lt;/strong&gt; — ChatGPT gives you one output. Changelog AI gives you the changelog, the GitHub release, AND the tweet simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Zero friction&lt;/strong&gt; — No prompt engineering. No "make it more professional." No back-and-forth. Paste → Generate → Ship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Consistent tone&lt;/strong&gt; — Every release sounds polished, not like it was written by 3 different interns.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Cost of Skipping Changelogs
&lt;/h2&gt;

&lt;p&gt;If you maintain an open source project, a SaaS, or any software people depend on — changelogs aren't optional. They're trust signals.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users want to know what changed before they update&lt;/li&gt;
&lt;li&gt;Contributors need to understand what shipped&lt;/li&gt;
&lt;li&gt;Your future self will thank you at 2am debugging a regression
A good changelog is &lt;strong&gt;developer marketing&lt;/strong&gt;. It shows you care about your users enough to communicate with them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Changelog AI makes that zero-effort.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It Free
&lt;/h2&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://change-log-ai.vercel.app/" rel="noopener noreferrer"&gt;change-log-ai.vercel.app&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No signup. No friction. Open it right now in another tab, paste your last 10 commits, and see what comes back.&lt;/p&gt;




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

&lt;p&gt;I'm actively building this out. On the roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] GitHub App integration (auto-generate on push)&lt;/li&gt;
&lt;li&gt;[ ] Jira/Linear ticket linking&lt;/li&gt;
&lt;li&gt;[ ] Team workspaces for consistent changelog style&lt;/li&gt;
&lt;li&gt;[ ] Slack/Discord announcement format&lt;/li&gt;
&lt;li&gt;[ ] Custom changelog templates
Drop a comment below if there's a feature you'd want — I'm reading every reply.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Built With
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; — Frontend + API routes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;strong&gt;Vercel&lt;/strong&gt; — Deployment
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;If this helped you, drop a ❤️ and share it with your team. Every dev I know has complained about changelogs — let's fix that.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://change-log-ai.vercel.app/" rel="noopener noreferrer"&gt;Try Changelog AI free&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>ai</category>
      <category>saas</category>
      <category>devtools</category>
    </item>
    <item>
      <title>UnProductive™: An Enterprise Dashboard for Accomplishing Absolutely Nothing</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Wed, 08 Apr 2026 17:22:14 +0000</pubDate>
      <link>https://dev.to/itxashancode/unproductive-an-enterprise-dashboard-for-accomplishing-absolutely-nothing-1d99</link>
      <guid>https://dev.to/itxashancode/unproductive-an-enterprise-dashboard-for-accomplishing-absolutely-nothing-1d99</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aprilfools-2026"&gt;DEV April Fools Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;UnProductive™ — The Anti-Productivity Suite.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A full bento-grid dashboard that looks like a legitimate SaaS product at first glance. Dark background, sidebar nav, real-time clock, progress charts, an AI advisor, a terminal. Everything a productivity app needs.&lt;/p&gt;

&lt;p&gt;Except every single feature is engineered to fail, flee, gaslight, or accomplish nothing whatsoever.&lt;/p&gt;

&lt;p&gt;Here's what's inside:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Evasive Button&lt;/strong&gt; — A box labeled "Important Decision Matrix" with a button that says "Acknowledge." It physically runs away when your cursor gets within 110px of it. If you actually manage to click it, the response is: &lt;em&gt;"Click registered. Action: none. You are welcome."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thought Shredder&lt;/strong&gt; — Type your billion-dollar idea. While you type, it randomly scrambles your characters and injects glitch symbols. Hit Obliterate and the text corrupts into garbage on-screen before disappearing to &lt;code&gt;/dev/null/forever&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UnProductive AI™&lt;/strong&gt; — Consults "The Oracle." The advice includes things like &lt;em&gt;"Analysis complete. You are 97% procrastination, 2% good intentions, 1% cached regret."&lt;/em&gt; and &lt;em&gt;"ERROR 418: Goal detected. Initiating avoidance protocol."&lt;/em&gt; Response accuracy: 0%. Powered by 0 neurons and pure vibes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vibe Check Terminal&lt;/strong&gt; — A fake terminal with real commands. Run &lt;code&gt;npm install&lt;/code&gt; and it adds 9,847 packages with 12,674 vulnerabilities. Three of them are sentient. Run &lt;code&gt;git blame&lt;/code&gt; and it just says &lt;em&gt;"you did this."&lt;/em&gt; Try to &lt;code&gt;exit&lt;/code&gt; and it tells you the void doesn't have a door.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Anti-Ledger&lt;/strong&gt; — A to-do list. Click any item and it shakes, denies your access, and changes the status to "ACCESS DENIED." The task label gets a strikethrough. You did not complete it. You were rejected by it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chaos Clock&lt;/strong&gt; — Keeps time, mostly. 10% of the time it steps backwards. 12% of the time it jumps several hours in either direction with a color flash and a CSS skew. Feels eerily plausible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Productivity Donut&lt;/strong&gt; — Animates up to 99% with great confidence, then immediately crashes to 0% and fires a toast: &lt;em&gt;"Productivity peaked at 99%. System reset to preserve institutional standards."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gaslight Toasts&lt;/strong&gt; — Random notifications every 7–21 seconds. &lt;em&gt;"You blinked 5 times. Recommended: 3. Please calibrate."&lt;/em&gt; and &lt;em&gt;"Your cursor is moving at an unsustainable velocity."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Synergy Optimizer Modal&lt;/strong&gt; — Full-screen takeover with a spinner and a progress bar permanently stuck at 99%. The Cancel button runs away from your cursor. Auto-dismisses after 28 seconds with: &lt;em&gt;"Results: statistically indistinguishable from before."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FIX UI Button&lt;/strong&gt; — Hue-rotates the page, mirrors it, rotates it slightly, or removes all color. Always reverts. Never fixes anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Daily Motivation Engine™&lt;/strong&gt; — Cycles through quotes like &lt;em&gt;"Every expert was once a beginner who gave up and rebranded as a consultant."&lt;/em&gt; and &lt;em&gt;"A plan without execution is a very impressive document."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Developer's Confession&lt;/strong&gt; — A "CLASSIFIED" section leaked as evidence that I have, outside of UnProductive™ hours, been observed writing real software. Links to my actual GitHub automation repos under a redacted watermark. The irony is intentional.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://devaprilfoolschallenge.vercel.app/" rel="noopener noreferrer"&gt;devaprilfoolschallenge.vercel.app&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the full experience, try these in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Try to click the "Acknowledge" button&lt;/li&gt;
&lt;li&gt;Type something important into the Thought Shredder, then hit Obliterate&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;git blame&lt;/code&gt; in the Vibe Terminal&lt;/li&gt;
&lt;li&gt;Click "Run AI Optimizer" and try to cancel it&lt;/li&gt;
&lt;li&gt;Press FIX UI a few times&lt;/li&gt;
&lt;li&gt;Just... wait for a gaslight toast&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/itxashancode" rel="noopener noreferrer"&gt;
        itxashancode
      &lt;/a&gt; / &lt;a href="https://github.com/itxashancode/DEV-April-Fools-Challenge" rel="noopener noreferrer"&gt;
        DEV-April-Fools-Challenge
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;Vanilla HTML, CSS, and JavaScript. No framework. Intentionally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three.js&lt;/strong&gt; for two things: a background particle field (2,200 points in acid/magenta/cyan pulled by the mouse), and the entropy visualizer widget which renders a wireframe torus knot that randomly glitches its scale, position, and color.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tailwind&lt;/strong&gt; (CDN) for layout. The bento grid is a 12-column CSS grid with span classes per widget — &lt;code&gt;w1&lt;/code&gt; through &lt;code&gt;w9&lt;/code&gt;, full-width for the GitHub confession section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 3D card tilt&lt;/strong&gt; on hover uses CSS custom properties set by &lt;code&gt;mousemove&lt;/code&gt; on each widget:&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;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--local-mouse-x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--local-mouse-y&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then consumed in CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.widget&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;perspective&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;900px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="n"&gt;rotateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--local-mouse-y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;-12deg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
             &lt;span class="n"&gt;rotateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--local-mouse-x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;12deg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
             &lt;span class="n"&gt;translateZ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;20px&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;No JS touches the transform. Keeps it smooth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The evasive button logic&lt;/strong&gt; (used in both the Acknowledge button and the Synergy Cancel button) tracks mouse distance to the button center and randomizes &lt;code&gt;top&lt;/code&gt;/&lt;code&gt;left&lt;/code&gt; within the parent's bounding rect if you get too close:&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hypot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;110&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;maxY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;maxX&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px`&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;&lt;strong&gt;The noise overlay&lt;/strong&gt; is a single &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with an SVG &lt;code&gt;feTurbulence&lt;/code&gt; filter tiled over the whole page at 4% opacity with &lt;code&gt;mix-blend-mode: overlay&lt;/code&gt;. Basically free performance-wise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Chaos Clock&lt;/strong&gt; has weighted randomness — most ticks advance normally, 10% go backwards, 12% jump by up to ±10 hours with a visual flash. Random clocks tend to feel too chaotic; weighted behavior makes it feel almost plausible until it isn't.&lt;/p&gt;

&lt;p&gt;Fonts: &lt;strong&gt;Space Mono&lt;/strong&gt; for the monospace/terminal aesthetic, &lt;strong&gt;Playfair Display&lt;/strong&gt; for the big italic headings. The contrast between them does a lot of work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prize Category
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best Ode to Larry Masinter&lt;/strong&gt; — the HTTP 418 easter egg is hardcoded in the AI advisor responses (&lt;em&gt;"ERROR 418: Goal detected. Initiating avoidance protocol."&lt;/em&gt;), the project name gestures at RFC 2324's whole ethos, and the entire thing is built on the premise that software can be technically correct and completely useless. That feels like the spirit of the teapot to me.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://dev.to/itxashancode"&gt;@itxashancode&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a bot that answers GitHub Discussions using free AI models — here's what I learned</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Wed, 08 Apr 2026 13:16:48 +0000</pubDate>
      <link>https://dev.to/itxashancode/i-built-a-bot-that-answers-github-discussions-using-free-ai-models-heres-what-i-learned-35lb</link>
      <guid>https://dev.to/itxashancode/i-built-a-bot-that-answers-github-discussions-using-free-ai-models-heres-what-i-learned-35lb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Heads up:&lt;/strong&gt; This is an educational project. The bot can post to GitHub Discussions, which means you need to use it carefully. I'll cover what responsible use looks like at the end.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;A few months ago I wanted to get GitHub's &lt;a href="https://docs.github.com/en/discussions/guides/finding-your-discussions" rel="noopener noreferrer"&gt;Galaxy Brain badge&lt;/a&gt; — the one you earn by getting answers marked as Accepted in Discussions. I figured automating the search part would be interesting. Finding relevant open questions manually is genuinely tedious.&lt;/p&gt;

&lt;p&gt;What started as a script to find unanswered threads turned into a project I actually care about. Not because of the badge, but because of the infrastructure problems it forced me to solve.&lt;/p&gt;

&lt;p&gt;Here's what's in the codebase and what I learned building each piece.&lt;/p&gt;




&lt;h2&gt;
  
  
  The basic idea
&lt;/h2&gt;

&lt;p&gt;The bot does four things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Discovers GitHub repos that have Discussions enabled, filtered by topic tags and star count&lt;/li&gt;
&lt;li&gt;Fetches open, unanswered Discussion threads from those repos&lt;/li&gt;
&lt;li&gt;Sends the question to a free LLM via OpenRouter and gets an answer&lt;/li&gt;
&lt;li&gt;Optionally posts that answer (with your confirmation, by default)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of that is complicated. The interesting problems came from making it reliable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 1: Free LLM models are flaky
&lt;/h2&gt;

&lt;p&gt;OpenRouter's free tier is great — 18+ models, no billing required. The catch is availability. A model that worked yesterday might 404 today. A model that worked an hour ago might be rate-limited now.&lt;/p&gt;

&lt;p&gt;My first version just tried one model and crashed when it failed. The fix was a rotation list:&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;_DEFAULT_MODELS&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;qwen/qwen3.6-plus:free&lt;/span&gt;&lt;span class="sh"&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;stepfun/step-3.5-flash:free&lt;/span&gt;&lt;span class="sh"&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;nvidia/nemotron-3-super-120b-a12b:free&lt;/span&gt;&lt;span class="sh"&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;meta-llama/llama-3.3-70b-instruct:free&lt;/span&gt;&lt;span class="sh"&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;google/gemma-3-27b-it:free&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# ... 13 more
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bot tries them in order. If a model returns an empty response, a 404, or a 429, it logs the failure and moves to the next one. At session end, &lt;code&gt;--models&lt;/code&gt; shows a table of which models succeeded, failed, and how fast they were.&lt;/p&gt;

&lt;p&gt;One thing I noticed: "success" and "quality" are different. A model can return a response that passes all the checks but still gives a generic non-answer. The answer length filter (&lt;code&gt;ANSWER_MIN_CHARS&lt;/code&gt;, &lt;code&gt;ANSWER_MAX_CHARS&lt;/code&gt;) catches the worst cases, but it doesn't catch confident-sounding garbage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 2: Retrying the wrong way
&lt;/h2&gt;

&lt;p&gt;Before adding proper backoff, the bot would hit a rate limit and immediately retry. Then retry again. Then again. GitHub's API would respond with &lt;code&gt;429&lt;/code&gt; for the rest of the session.&lt;/p&gt;

&lt;p&gt;The fix was reading &lt;code&gt;Retry-After&lt;/code&gt; headers:&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;retry_after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retry-After&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RATE_LIMIT_RETRY_AFTER_DEFAULT&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retry_after&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub is inconsistent about including that header. When it's missing, the bot falls back to exponential delay. It's not perfect, but it's miles better than hammering an endpoint that's already telling you to stop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 3: One bad endpoint killing the whole session
&lt;/h2&gt;

&lt;p&gt;This took me a while to notice. If a particular GraphQL query started timing out — say, because a repo was unusually large — the bot would retry it over and over, spending most of the session waiting.&lt;/p&gt;

&lt;p&gt;Circuit breakers solve this. After a configurable number of consecutive failures, the circuit "opens" and blocks further requests to that endpoint for a timeout period. Then it half-opens: one probe request goes through. If that succeeds, the circuit closes again.&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;CLOSED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;closed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;OPEN&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;HALF&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;half_open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLOSED&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opened_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The effect in practice: the bot now skips broken endpoints and moves to the next repo in the list, instead of getting stuck.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 4: Ctrl+C corrupting the stats file
&lt;/h2&gt;

&lt;p&gt;The stats file (&lt;code&gt;galaxy_brain_stats.json&lt;/code&gt;) gets written at the end of each session. If you hit Ctrl+C mid-write, you get a partial JSON file, which breaks the next session.&lt;/p&gt;

&lt;p&gt;The fix was a &lt;code&gt;ShutdownHandler&lt;/code&gt; that catches SIGINT/SIGTERM and sets a flag:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShutdownHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_shutdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGTERM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_shutdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;requested&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_shutdown&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every loop in the bot checks &lt;code&gt;shutdown.requested&lt;/code&gt; before its next iteration. Ctrl+C finishes the current task cleanly, then exits. The stats file always gets written to disk before the process ends.&lt;/p&gt;




&lt;h2&gt;
  
  
  What else is in there
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;In-memory TTL cache.&lt;/strong&gt; Avoids re-fetching the same GraphQL results within a session. Default TTL is 5 minutes. When you're processing 50 repos, this matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-modal support.&lt;/strong&gt; If a Discussion post contains images and the selected model supports vision, the bot fetches the images and includes them in the prompt. Same for external links — it fetches the page content and appends it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key rotation.&lt;/strong&gt; You can put multiple OpenRouter API keys in &lt;code&gt;.env&lt;/code&gt;, comma-separated. When one hits its rate limit, the bot rotates to the next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook notifications.&lt;/strong&gt; Discord and Slack. Sends an alert when an answer gets accepted, and a summary at the end of each session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stats by org.&lt;/strong&gt; Breaks down your answer history by repository owner. Useful for seeing which communities you've been most active in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting it up
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/YOUR_USERNAME/galaxy-brain-bot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;galaxy-brain-bot
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.template .env
&lt;span class="c"&gt;# Fill in GITHUB_TOKEN, GITHUB_USERNAME, OPENROUTER_KEYS&lt;/span&gt;
python test_bot.py  &lt;span class="c"&gt;# run this before anything else&lt;/span&gt;
python galaxy_brain_bot.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test suite checks all your credentials and API connections before you run the main bot. Run it first.&lt;/p&gt;

&lt;p&gt;By default, the bot asks for confirmation before posting each answer (&lt;code&gt;AUTO_APPROVE_ANSWERS=false&lt;/code&gt;). Keep it that way until you've seen a few answers and trust the output quality on the repos you're targeting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Responsible use
&lt;/h2&gt;

&lt;p&gt;A few things I want to say directly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't run it unsupervised at scale.&lt;/strong&gt; The &lt;code&gt;MAX_ANSWERS_PER_SESSION&lt;/code&gt; setting exists for a reason. Posting 50 answers in an hour is a good way to get flagged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read the answers before posting.&lt;/strong&gt; LLMs are wrong sometimes. Posting a confident wrong answer in a GitHub Discussion is worse than posting nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check the repo's rules.&lt;/strong&gt; Some repos have Codes of Conduct that explicitly restrict automated participation. The bot tries to detect this, but it can miss things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's a research tool, not a farming tool.&lt;/strong&gt; The badge is a byproduct. If you're using this to post low-effort answers at volume, you're not using it for what it was built for.&lt;/p&gt;




&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;Full source, setup instructions, and config reference: &lt;a href="https://github.com/itxashancode/Galaxy-Brain-Automation" rel="noopener noreferrer"&gt;https://github.com/itxashancode/Galaxy-Brain-Automation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The whole thing is one Python file (&lt;code&gt;galaxy_brain_bot.py&lt;/code&gt;) plus a test suite. No frameworks, no magic — just &lt;code&gt;requests&lt;/code&gt;, &lt;code&gt;rich&lt;/code&gt; for the terminal UI, and &lt;code&gt;python-dotenv&lt;/code&gt;. If you want to understand a specific piece, it's all in one place.&lt;/p&gt;

&lt;p&gt;Happy to answer questions in the comments. If you spot something in the circuit breaker or backoff logic that could be better, I'm genuinely interested.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built for learning. MIT licensed.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>github</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>🏥 gh-repo-health: Check Your GitHub Repo's Health Score in Seconds</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Thu, 19 Mar 2026 03:56:43 +0000</pubDate>
      <link>https://dev.to/itxashancode/gh-repo-health-check-your-github-repos-health-score-in-seconds-2bon</link>
      <guid>https://dev.to/itxashancode/gh-repo-health-check-your-github-repos-health-score-in-seconds-2bon</guid>
      <description>&lt;p&gt;Have you ever opened a GitHub repo and wondered &lt;em&gt;"is this project actually maintained?"&lt;/em&gt; — or pushed your own project and asked &lt;em&gt;"does this even look professional?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I asked myself the same questions. So I built &lt;strong&gt;&lt;code&gt;gh-repo-health&lt;/code&gt;&lt;/strong&gt; — a CLI tool that audits any GitHub repository and gives it a health score based on community standards.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Why I Built This
&lt;/h2&gt;

&lt;p&gt;When I was exploring open source projects to contribute to, I kept manually checking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it have a &lt;strong&gt;README&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Is there a &lt;strong&gt;CONTRIBUTING&lt;/strong&gt; guide?&lt;/li&gt;
&lt;li&gt;Any &lt;strong&gt;issue templates&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;LICENSE&lt;/strong&gt; file?&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;CODE_OF_CONDUCT&lt;/strong&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doing this for every repo was exhausting. I wanted a single command that tells me everything at once.&lt;/p&gt;

&lt;p&gt;So I built &lt;code&gt;gh-repo-health&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ What It Does
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gh-repo-health&lt;/code&gt; scans any public GitHub repository and checks for key community health files:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;First impression — does the project explain itself?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LICENSE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Legal clarity for contributors and users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CONTRIBUTING.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Guides new contributors on how to help&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets community standards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SECURITY.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Responsible disclosure for vulnerabilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Issue Templates&lt;/td&gt;
&lt;td&gt;Structured bug reports and feature requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pull Request Template&lt;/td&gt;
&lt;td&gt;Consistent PR process&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each check passes or fails, and you get an overall &lt;strong&gt;health score&lt;/strong&gt; at the end.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Getting Started
&lt;/h2&gt;

&lt;p&gt;Clone the repo and run it against any GitHub repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/itxashancode/gh-repo-health
&lt;span class="nb"&gt;cd &lt;/span&gt;gh-repo-health
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then audit any repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python main.py itxashancode/Pull-Shark-Automation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll get output like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ README.md          found
✅ LICENSE            found
❌ CONTRIBUTING.md    missing
❌ CODE_OF_CONDUCT    missing
✅ Issue Templates    found
❌ SECURITY.md        missing
❌ PR Template        missing

Health Score: 43% — Needs Improvement
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠️ How It Works
&lt;/h2&gt;

&lt;p&gt;The tool uses the &lt;strong&gt;GitHub REST API&lt;/strong&gt; to check for the existence of community health files. No cloning required — it's all API calls.&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&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://api.github.com/repos/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/contents/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&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="n"&gt;url&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It checks common file locations — root, &lt;code&gt;.github/&lt;/code&gt;, and &lt;code&gt;docs/&lt;/code&gt; — so it doesn't miss files tucked in subdirectories.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;This was one of my early Python projects, and it taught me a lot:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GitHub's API is incredibly powerful&lt;/strong&gt; — you can inspect almost anything about a repo without cloning it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community health files genuinely matter&lt;/strong&gt; — repos with them get more contributions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI tools are satisfying to build&lt;/strong&gt; — instant feedback, no UI needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error handling is critical&lt;/strong&gt; — private repos, rate limits, and missing tokens all need to be handled gracefully&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🔮 What's Next
&lt;/h2&gt;

&lt;p&gt;I'm planning to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Badge generation&lt;/strong&gt; — embed a health score badge in your README&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Batch scanning&lt;/strong&gt; — audit all repos in an organization at once&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;GitHub Actions integration&lt;/strong&gt; — fail CI if health score drops below a threshold&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;JSON output&lt;/strong&gt; — for piping results into other tools&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌟 Try It on Your Own Repo
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;gh-repo-health&lt;/code&gt; against your own projects. You might be surprised what's missing!&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/itxashancode/gh-repo-health" rel="noopener noreferrer"&gt;GitHub: itxashancode/gh-repo-health&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, drop a ⭐ on the repo — it genuinely motivates me to keep building.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Ashan, an APTECH student from Karachi building GitHub automation tools and learning in public. If you have ideas for features, drop them in the comments below — I read every one! 👇&lt;/em&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>opensource</category>
      <category>python</category>
      <category>devtools</category>
    </item>
    <item>
      <title>🎮 What I Learned Building a Minecraft Voting Portal with Pure HTML, CSS &amp; JS (No Frameworks!)</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Sun, 15 Mar 2026 01:50:54 +0000</pubDate>
      <link>https://dev.to/itxashancode/what-i-learned-building-a-minecraft-voting-portal-with-pure-html-css-js-no-frameworks-li1</link>
      <guid>https://dev.to/itxashancode/what-i-learned-building-a-minecraft-voting-portal-with-pure-html-css-js-no-frameworks-li1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I'm a student developer from Karachi, Pakistan 🇵🇰 — studying at APTECH and building real projects to level up my skills. This one started as a fun side project for a Minecraft server community called &lt;strong&gt;HustlersMC&lt;/strong&gt; and turned into one of the biggest learning experiences of my journey so far.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;No React. No Vue. No Tailwind. Just &lt;strong&gt;pure HTML, CSS, and JavaScript&lt;/strong&gt; — and way more depth than I expected.&lt;/p&gt;

&lt;p&gt;Here's everything I genuinely learned. 👇&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Why Build a Voting Portal?
&lt;/h2&gt;

&lt;p&gt;Minecraft servers live and die by their ranking on voting sites like &lt;a href="https://www.planetminecraft.com/" rel="noopener noreferrer"&gt;Planet Minecraft&lt;/a&gt; and &lt;a href="https://minecraft-server-list.com/" rel="noopener noreferrer"&gt;Minecraft Server List&lt;/a&gt;. The more players vote, the higher the server ranks, the more new players join.&lt;/p&gt;

&lt;p&gt;Most voting portals out there are &lt;strong&gt;ugly&lt;/strong&gt;, &lt;strong&gt;slow&lt;/strong&gt;, or just a boring list of links. I wanted to build something that actually made players &lt;em&gt;want&lt;/em&gt; to vote — something that felt premium, fast, and exciting the moment you landed on it.&lt;/p&gt;

&lt;p&gt;That became &lt;strong&gt;Vote-for-HustlersMC&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ What I Built
&lt;/h2&gt;

&lt;p&gt;Here's the feature list at a glance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🪟 &lt;strong&gt;Glassmorphism UI&lt;/strong&gt; — frosted glass cards, layered transparencies, depth without weight&lt;/li&gt;
&lt;li&gt;✍️ &lt;strong&gt;Typewriter text effects&lt;/strong&gt; — dynamic headlines that animate on load&lt;/li&gt;
&lt;li&gt;🌌 &lt;strong&gt;Animated backgrounds&lt;/strong&gt; — subtle motion that brings the page to life&lt;/li&gt;
&lt;li&gt;🔗 &lt;strong&gt;10+ verified voting platforms&lt;/strong&gt; integrated in one place&lt;/li&gt;
&lt;li&gt;📈 &lt;strong&gt;SEO-ready structure&lt;/strong&gt; — meta tags, semantic HTML, Open Graph&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Analytics-ready&lt;/strong&gt; — plug in your tracking ID and you're live&lt;/li&gt;
&lt;li&gt;♿ &lt;strong&gt;Accessibility-first&lt;/strong&gt; — keyboard navigable, proper contrast, ARIA labels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it runs on &lt;strong&gt;zero dependencies&lt;/strong&gt;. No npm. No build step. Just open &lt;code&gt;index.html&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Lesson 1: Pure CSS Can Do Incredible Things
&lt;/h2&gt;

&lt;p&gt;I went into this thinking I'd need a CSS framework to pull off the glassmorphism look. I was wrong.&lt;/p&gt;

&lt;p&gt;The glass card effect is just a few lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.glass-card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="m"&gt;32px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.3&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;That's it. &lt;code&gt;backdrop-filter: blur()&lt;/code&gt; is the magic. It blurs everything &lt;em&gt;behind&lt;/em&gt; the element, creating that frosted glass illusion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Before reaching for a framework, ask yourself — can CSS do this natively? More often than not, the answer is yes. Frameworks add weight. Native CSS adds nothing.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Lesson 2: The Typewriter Effect Taught Me JavaScript Timing
&lt;/h2&gt;

&lt;p&gt;The animated typewriter headline was something I'd seen on hundreds of sites but never built myself. I assumed it required a library. It doesn't.&lt;/p&gt;

&lt;p&gt;Here's the core logic I wrote:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;phrases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Vote. Rise. Conquer.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Support HustlersMC Today.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Every Vote Counts. ⚔️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;phraseIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;charIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isDeleting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;typeWriter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;phraseIndex&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;displayed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isDeleting&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&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="nx"&gt;charIndex&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="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&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="nx"&gt;charIndex&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.typewriter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;displayed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isDeleting&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;charIndex&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isDeleting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pause before deleting&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isDeleting&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;charIndex&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;isDeleting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;phraseIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phraseIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typeWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isDeleting&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;typeWriter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; &lt;code&gt;setTimeout&lt;/code&gt; recursion is incredibly powerful for animations. Understanding the difference between typing speed (100ms) and deletion speed (60ms) is what makes it feel &lt;em&gt;human&lt;/em&gt;. Small timing details create big UX impact.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Lesson 3: SEO Is Not Just for Big Websites
&lt;/h2&gt;

&lt;p&gt;This one surprised me most. I thought SEO was something you worry about when you have a blog or a business. But even a simple static page benefits enormously from it.&lt;/p&gt;

&lt;p&gt;I added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Basic SEO --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Vote for HustlersMC — the fastest growing Minecraft server in Pakistan. Support us on 10+ platforms!"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"keywords"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"HustlersMC, Minecraft server, vote, Pakistan Minecraft, server ranking"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Open Graph for social sharing --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Vote for HustlersMC 🎮"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Click to vote and help us climb the rankings!"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://yoursite.com/preview.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Semantic HTML --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;, &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;, &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;, &lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;, &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The moment I shared the link on Discord, the &lt;strong&gt;Open Graph preview card&lt;/strong&gt; showed up beautifully — the server logo, title, and description. Players were more likely to click it. The server's visibility on Google improved too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Semantic HTML + meta tags = free marketing. It costs you 10 minutes and pays back for months.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Lesson 4: Animated Backgrounds Are About Restraint, Not Complexity
&lt;/h2&gt;

&lt;p&gt;My first attempt at the animated background was too intense — particles flying everywhere, colors shifting rapidly. It looked like a nightclub, not a website.&lt;/p&gt;

&lt;p&gt;The version I shipped uses a subtle CSS keyframe animation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;gradientShift&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;135deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#0f0c29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#302b63&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#24243e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300%&lt;/span&gt; &lt;span class="m"&gt;300%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gradientShift&lt;/span&gt; &lt;span class="m"&gt;8s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="n"&gt;infinite&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;Slow. Smooth. Atmospheric. It adds life without distracting from the content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Great animation is mostly about what you &lt;em&gt;don't&lt;/em&gt; do. Subtlety wins. If users notice the animation more than the content, you've gone too far.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Lesson 5: Building for a Real Community Changes Everything
&lt;/h2&gt;

&lt;p&gt;This wasn't a practice project for a fake client. Real players from HustlersMC were going to use this. That pressure made me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test on mobile obsessively (most Minecraft players are on phones between sessions)&lt;/li&gt;
&lt;li&gt;Check contrast ratios for accessibility&lt;/li&gt;
&lt;li&gt;Make sure every voting link opened correctly in a new tab&lt;/li&gt;
&lt;li&gt;Add a smooth loading state so it didn't flash unstyled content (FOUC)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also integrated &lt;strong&gt;Google Analytics&lt;/strong&gt; so the server owner could see which voting platforms were being used most and which players were dropping off. That turned a static page into an actual growth tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned:&lt;/strong&gt; Building for real users forces you to care about details you'd ignore in a tutorial. Ship something real as early as possible — even if it's small.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ The Tech Stack (Zero Dependencies)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;How&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structure&lt;/td&gt;
&lt;td&gt;Semantic HTML5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Styling&lt;/td&gt;
&lt;td&gt;Pure CSS3 (glassmorphism, keyframe animations, CSS variables)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interactivity&lt;/td&gt;
&lt;td&gt;Vanilla JavaScript (typewriter, scroll effects)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEO&lt;/td&gt;
&lt;td&gt;Meta tags, Open Graph, semantic markup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;Google Analytics (plug-and-play)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting&lt;/td&gt;
&lt;td&gt;GitHub Pages (free, instant)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No npm. No node_modules. No build pipeline. Just files.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 The Result
&lt;/h2&gt;

&lt;p&gt;A voting portal that looks like it cost money to build — but didn't. Players actually commented on how clean it looked. The server owner could share the link anywhere and it looked professional on every platform.&lt;/p&gt;

&lt;p&gt;You can explore the full source code here 👇&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔗 GitHub:&lt;/strong&gt; &lt;a href="https://github.com/itxashancode/Vote-for-HustlersMC" rel="noopener noreferrer"&gt;github.com/itxashancode/Vote-for-HustlersMC&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 What Would You Build Next?
&lt;/h2&gt;

&lt;p&gt;I'm currently exploring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a live vote counter with localStorage&lt;/li&gt;
&lt;li&gt;A leaderboard showing top voters of the month&lt;/li&gt;
&lt;li&gt;A Discord webhook that pings the server when someone votes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've built something for a game community — or if you're curious about any of the techniques above — &lt;strong&gt;drop a comment below!&lt;/strong&gt; I'd love to see what you're working on. 🎮&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this helped you, consider giving the repo a ⭐ — it genuinely means a lot to a student developer from Pakistan trying to make his mark!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>css</category>
    </item>
    <item>
      <title>🐍 5 Python Scripts Every Student Dev Should Automate First</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Fri, 13 Mar 2026 16:04:02 +0000</pubDate>
      <link>https://dev.to/itxashancode/5-python-scripts-every-student-dev-should-automate-first-a21</link>
      <guid>https://dev.to/itxashancode/5-python-scripts-every-student-dev-should-automate-first-a21</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I'm a student dev from Karachi. No internship. No senior to guide me.&lt;br&gt;
Just a laptop, Python, and a habit of automating everything that bored me twice.&lt;br&gt;
Here's what I wish I had automated sooner.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. 🔁 Auto-Rename &amp;amp; Organize Your Downloads Folder
&lt;/h2&gt;

&lt;p&gt;Your downloads folder is a graveyard. Fix it in 15 lines.&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shutil&lt;/span&gt;

&lt;span class="n"&gt;FOLDER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/Downloads&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;TYPES&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;Images&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&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;.jpeg&lt;/span&gt;&lt;span class="sh"&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;.png&lt;/span&gt;&lt;span class="sh"&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;.gif&lt;/span&gt;&lt;span class="sh"&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;.webp&lt;/span&gt;&lt;span class="sh"&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;Docs&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.pdf&lt;/span&gt;&lt;span class="sh"&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;.docx&lt;/span&gt;&lt;span class="sh"&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;.txt&lt;/span&gt;&lt;span class="sh"&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;.xlsx&lt;/span&gt;&lt;span class="sh"&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;Code&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.py&lt;/span&gt;&lt;span class="sh"&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;.js&lt;/span&gt;&lt;span class="sh"&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;.ts&lt;/span&gt;&lt;span class="sh"&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;.html&lt;/span&gt;&lt;span class="sh"&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;.css&lt;/span&gt;&lt;span class="sh"&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;Videos&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.mp4&lt;/span&gt;&lt;span class="sh"&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;.mov&lt;/span&gt;&lt;span class="sh"&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;.mkv&lt;/span&gt;&lt;span class="sh"&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;Zips&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.zip&lt;/span&gt;&lt;span class="sh"&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;.rar&lt;/span&gt;&lt;span class="sh"&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;.tar&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="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FOLDER&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exts&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;exts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;dest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FOLDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FOLDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it once a week with Task Scheduler (Windows) or a cron job. You'll feel like a wizard.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. 📸 Bulk Screenshot → PDF Converter
&lt;/h2&gt;

&lt;p&gt;Got lecture slides scattered as screenshots? Merge them into one PDF instantly.&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;screenshots_to_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;merged.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&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;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;convert&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&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;.jpg&lt;/span&gt;&lt;span class="sh"&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;.jpeg&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="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;images&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="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;save_all&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append_images&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
    &lt;span class="nf"&gt;print&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;✅ Saved: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;output&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="nf"&gt;screenshots_to_pdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./slides&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install: &lt;code&gt;pip install Pillow&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This saved me hours before exams. Seriously.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. 🔔 Desktop Notifier for Any Website Change
&lt;/h2&gt;

&lt;p&gt;Watching for a job post? A price drop? A new batch opening?&lt;br&gt;
Stop refreshing. Let Python do it.&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;plyer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;

&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# replace with your target
&lt;/span&gt;&lt;span class="n"&gt;CHECK_EVERY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;  &lt;span class="c1"&gt;# seconds
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&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="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&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;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;👁️ Watching for changes...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CHECK_EVERY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🚨 Page Changed!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install: &lt;code&gt;pip install requests plyer&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Set it, forget it, get notified.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. 📂 Auto-Backup Your Projects to a Zip
&lt;/h2&gt;

&lt;p&gt;Before you break something (you will), back it up.&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;backup_project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./backups&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y%m%d_%H%M%S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;zip_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_dir&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;backup_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.zip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ZipFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zip_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZIP_DEFLATED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_dir&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;[:]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dirs&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;node_modules&lt;/span&gt;&lt;span class="sh"&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;.git&lt;/span&gt;&lt;span class="sh"&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;__pycache__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;filepath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_dir&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nf"&gt;print&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;✅ Backup saved: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;zip_name&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="nf"&gt;backup_project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./my-project&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice: it skips &lt;code&gt;node_modules&lt;/code&gt;, &lt;code&gt;.git&lt;/code&gt;, and &lt;code&gt;__pycache__&lt;/code&gt; — so the zip stays small.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. 🤖 GitHub Auto-Commit Streak Keeper
&lt;/h2&gt;

&lt;p&gt;Missing a day on your contribution graph hurts.&lt;br&gt;
This script makes a tiny commit so your streak stays alive when life gets in the way.&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="n"&gt;LOG_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;streak.log&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&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;streak kept: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&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;add&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&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;commit&lt;/span&gt;&lt;span class="sh"&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;-m&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;chore: streak &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()&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;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&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;push&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ Streak alive!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set this on a cron job at 11:50 PM. Sleep peacefully.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Use on a personal/practice repo — not your main project.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎯 Quick Recap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Script&lt;/th&gt;
&lt;th&gt;What It Solves&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Downloads Organizer&lt;/td&gt;
&lt;td&gt;Chaos in your folders&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Screenshots → PDF&lt;/td&gt;
&lt;td&gt;Messy lecture notes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Website Change Notifier&lt;/td&gt;
&lt;td&gt;FOMO on opportunities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Project Backup&lt;/td&gt;
&lt;td&gt;That "oh no" moment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Streak Keeper&lt;/td&gt;
&lt;td&gt;GitHub anxiety&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💬 Drop Your Script in the Comments
&lt;/h2&gt;

&lt;p&gt;What's the first thing YOU automated as a student dev?&lt;br&gt;
I'm building a list — your script might end up in part 2. 👇&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built in Karachi. Tested at 2am. Working on more automation tools at &lt;a href="https://github.com/itxashancode" rel="noopener noreferrer"&gt;github.com/itxashancode&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>automation</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Have 18 GitHub Repos at 17 — Here's What I Built, Broke, and Learned</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Thu, 12 Mar 2026 23:42:21 +0000</pubDate>
      <link>https://dev.to/itxashancode/i-have-18-github-repos-at-17-heres-what-i-built-broke-and-learned-3kh9</link>
      <guid>https://dev.to/itxashancode/i-have-18-github-repos-at-17-heres-what-i-built-broke-and-learned-3kh9</guid>
      <description>&lt;p&gt;When I joined GitHub, I didn't have a plan.&lt;/p&gt;

&lt;p&gt;I just started building things — some useful, some broken, some embarrassing.&lt;br&gt;
But 18 repositories later, I've learned more from pushing code than from any tutorial.&lt;/p&gt;

&lt;p&gt;Here's an honest breakdown of what I built, what flopped, and what actually taught me something real.&lt;/p&gt;




&lt;h2&gt;
  
  
  🦈 The One That Started Everything: Pull Shark Automation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Automate GitHub PR creation at scale — 62 PRs/min with Python&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was my first "real" project. I wanted the GitHub Pull Shark badge, but doing it manually was painfully slow. So I automated it.&lt;/p&gt;

&lt;p&gt;What it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dual modes: Sequential (stable) and Parallel (blazing fast async)&lt;/li&gt;
&lt;li&gt;Multi-token rotation to stay within rate limits&lt;/li&gt;
&lt;li&gt;Auto-merge, Discord/Slack webhooks, proxy support&lt;/li&gt;
&lt;li&gt;Windows compatible
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sequential mode
&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;

&lt;span class="c1"&gt;# Parallel mode (fast)
&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;parallel_automation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;concurrent&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="c1"&gt;# Test without committing
&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;dry&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real-world result: &lt;strong&gt;62.5 PRs/min&lt;/strong&gt; with 3 tokens and 20 parallel workers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;em&gt;Built for learning and CI/CD stress testing. Use responsibly.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/itxashancode/Pull-Shark-Automation" rel="noopener noreferrer"&gt;Pull-Shark-Automation on GitHub&lt;/a&gt; — drop a ⭐ if it helps!&lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 Pair Extraordinaire — Automating Co-Author Badges
&lt;/h2&gt;

&lt;p&gt;After Pull Shark, I went after the Pair Extraordinaire badge.&lt;br&gt;
Same idea — understand how GitHub's contribution system works by building around it.&lt;/p&gt;

&lt;p&gt;This one taught me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Git co-authoring actually works under the hood&lt;/li&gt;
&lt;li&gt;Managing multiple identities in commits&lt;/li&gt;
&lt;li&gt;Token scoping and permission management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/itxashancode/Pair-Extraordinaire" rel="noopener noreferrer"&gt;Pair-Extraordinaire on GitHub&lt;/a&gt; — drop a ⭐ if it helps!&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 What 18 Repos Actually Taught Me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. READMEs matter more than code quality at first&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nobody digs into your code on first impression. They read your README.&lt;br&gt;
Write it like you're explaining to a smart friend who's never seen your project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Stars don't validate you — but they do signal clarity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pull Shark got 27 stars in a week not because the code was perfect,&lt;br&gt;
but because the README was clear and the use case was specific.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Broken repos are fine. Abandoned repos are not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have repos I haven't touched in weeks. That's okay.&lt;br&gt;
What's not okay is leaving them with no description, no README, no context.&lt;br&gt;
Even a one-liner description helps someone understand what you were thinking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Your GitHub is a portfolio before you have a portfolio&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don't have a deployed portfolio site yet (it's in progress 👀).&lt;br&gt;
But recruiters and collaborators can still see exactly what I can do&lt;br&gt;
by looking at my repos. Treat every repo like a mini-resume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Committing consistently beats committing perfectly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Green squares on your contribution graph tell a story.&lt;br&gt;
Don't wait until your code is "ready." Push early, push often.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ My Current Stack Across All Projects
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language/Tool&lt;/th&gt;
&lt;th&gt;Used For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Automation, scripting, GitHub tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript / TypeScript&lt;/td&gt;
&lt;td&gt;Web apps, frontend logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React + Next.js&lt;/td&gt;
&lt;td&gt;UI, full stack projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;Backend, API building&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firebase&lt;/td&gt;
&lt;td&gt;Auth, real-time DB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML + CSS&lt;/td&gt;
&lt;td&gt;Foundations, landing pages&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🔭 What I'm Building Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Personal portfolio site with Next.js (almost done)&lt;/li&gt;
&lt;li&gt;AI-powered web app integrating Claude / OpenAI APIs&lt;/li&gt;
&lt;li&gt;More open source tools for developers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤙 Let's Connect
&lt;/h2&gt;

&lt;p&gt;If you're a dev from Pakistan, a beginner just starting out,&lt;br&gt;
or someone who loves building weird automation tools — let's connect.&lt;br&gt;
Drop a comment, follow along, or check out my repos.&lt;/p&gt;

&lt;p&gt;📦 &lt;a href="https://github.com/itxashancode" rel="noopener noreferrer"&gt;GitHub → itxashancode&lt;/a&gt;&lt;br&gt;
🌐 &lt;a href="https://linktr.ee/itxashanvibes" rel="noopener noreferrer"&gt;Linktree → itxashanvibes&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What was your first GitHub repo? Drop it in the comments 👇&lt;/em&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>beginners</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🤝 Automate GitHub's Pair Extraordinaire Badge with Python</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Wed, 11 Mar 2026 10:13:57 +0000</pubDate>
      <link>https://dev.to/itxashancode/automate-githubs-pair-extraordinaire-badge-with-python-26bi</link>
      <guid>https://dev.to/itxashancode/automate-githubs-pair-extraordinaire-badge-with-python-26bi</guid>
      <description>&lt;h2&gt;
  
  
  A deep dive into Pair Extraordinaire Automation — a Python framework that streamlines co-authored PRs at scale, with dual execution modes, token rotation, webhook notifications, and smart state resumption.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;🔗 Full source code on GitHub: &lt;a href="https://github.com/itxashancode/Pair-Extraordinaire" rel="noopener noreferrer"&gt;Pair-Extraordinaire&lt;/a&gt; — drop a ⭐ if it helps!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Ever wondered how some developers rack up GitHub achievement badges at scale? Or wanted to deeply understand how GitHub co-authoring workflows actually function under the hood? That's exactly what &lt;strong&gt;Pair Extraordinaire Automation&lt;/strong&gt; is built for.&lt;/p&gt;

&lt;p&gt;This open-source Python framework automates co-authored Pull Request workflows — giving you a hands-on way to explore GitHub API integration, token management, webhook notifications, and stateful automation design, all in one project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Heads up:&lt;/strong&gt; This tool is built for &lt;strong&gt;educational purposes&lt;/strong&gt; — to study GitHub automation and co-authoring patterns. Always use it responsibly and in line with &lt;a href="https://docs.github.com/en/site-policy/github-terms/github-terms-of-service" rel="noopener noreferrer"&gt;GitHub's Terms of Service&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🏆 What Is the Pair Extraordinaire Badge?
&lt;/h2&gt;

&lt;p&gt;GitHub awards the &lt;strong&gt;Pair Extraordinaire&lt;/strong&gt; achievement when you co-author and merge Pull Requests with a collaborator. The badge has four tiers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Required PRs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;td&gt;1 PR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🥉 Bronze&lt;/td&gt;
&lt;td&gt;10 PRs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🥈 Silver&lt;/td&gt;
&lt;td&gt;24 PRs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🥇 Gold&lt;/td&gt;
&lt;td&gt;48 PRs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The magic happens through Git's &lt;code&gt;Co-authored-by&lt;/code&gt; commit trailer — a simple but powerful convention that GitHub recognises to credit multiple authors on a single commit.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 What Does This Project Do?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pair Extraordinaire Automation&lt;/strong&gt; is a configurable Python framework that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates branches, makes co-authored commits, opens Pull Requests, and merges them — all automatically&lt;/li&gt;
&lt;li&gt;Supports &lt;strong&gt;sequential&lt;/strong&gt; and &lt;strong&gt;parallel&lt;/strong&gt; execution modes&lt;/li&gt;
&lt;li&gt;Handles &lt;strong&gt;rate limits&lt;/strong&gt; with exponential backoff and smart retry logic&lt;/li&gt;
&lt;li&gt;Rotates across &lt;strong&gt;multiple GitHub tokens&lt;/strong&gt; for higher throughput&lt;/li&gt;
&lt;li&gt;Sends real-time progress updates to &lt;strong&gt;Discord or Slack&lt;/strong&gt; via webhooks&lt;/li&gt;
&lt;li&gt;Persists state so you can &lt;strong&gt;resume after any interruption&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Includes a &lt;strong&gt;dry-run mode&lt;/strong&gt; for testing without touching your repository&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏗️ Architecture Overview
&lt;/h2&gt;

&lt;p&gt;The project is cleanly structured into four layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pair Extraordinaire Automation
│
├── run.py              ← Entry point &amp;amp; orchestrator
├── src/                ← Core bot logic (git ops, GitHub API, token mgr)
├── config/             ← JSON settings + .env variables
└── templates/          ← Commit message &amp;amp; PR body templates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The orchestration flow looks 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;Start → Load Config → Choose Mode (Sequential / Parallel)
      → Create Branch → Co-authored Commit → Push → Open PR
      → Auto-Merge → Save State → Notify → Repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I like about this design is its clear separation of concerns. The &lt;code&gt;src/&lt;/code&gt; layer handles all Git and GitHub API interactions, while &lt;code&gt;config/&lt;/code&gt; and &lt;code&gt;templates/&lt;/code&gt; let you customise behaviour without touching any core logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;You'll need Python 3.8+, Git 2.0+, and the &lt;a href="https://cli.github.com/" rel="noopener noreferrer"&gt;GitHub CLI&lt;/a&gt; installed. You also need two GitHub accounts — your own and a collaborator's.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repo&lt;/span&gt;
git clone https://github.com/itxashancode/Pair-Extraordinaire-Automation.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Pair-Extraordinaire-Automation

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Authenticate GitHub CLI&lt;/span&gt;
gh auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;Copy &lt;code&gt;.env.example&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt; and fill in your details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GITHUB_TOKEN=your_personal_access_token
REPO_OWNER=your_github_username
REPO_NAME=your_repository_name

CO_AUTHOR_NAME=Collaborator Name
CO_AUTHOR_EMAIL=collaborator@email.com
CO_AUTHOR_TOKEN=collaborator_token_optional

# Optional webhooks
DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
SLACK_WEBHOOK=https://hooks.slack.com/services/...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then set your run parameters in &lt;code&gt;config/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pr_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"delay_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"auto_merge"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dry_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_retries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Always test first with dry-run
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python run.py &lt;span class="nt"&gt;--dry-run&lt;/span&gt; &lt;span class="nt"&gt;--count&lt;/span&gt; 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simulates the full workflow — branch creation, commits, PRs — without making any real changes. It's a great way to catch config mistakes before they matter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run for real
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Basic run (uses config defaults)&lt;/span&gt;
python run.py

&lt;span class="c"&gt;# Custom count with specific delay&lt;/span&gt;
python run.py &lt;span class="nt"&gt;--count&lt;/span&gt; 50 &lt;span class="nt"&gt;--delay&lt;/span&gt; 10

&lt;span class="c"&gt;# Resume after an interruption — state is automatically tracked&lt;/span&gt;
python run.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sample output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;🚀 Starting Pair Extraordinaire Automation from PR #&lt;/span&gt;1
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;🔹 Processing PR #&lt;/span&gt;1
&lt;span class="go"&gt;  ├─ 🌿 Created branch: pair-auto-1-a1b2c3d4
  ├─ 💾 Committed with Co-authored-by trailer
  ├─ 📤 Pushed to remote
&lt;/span&gt;&lt;span class="gp"&gt;  └─ ✅ PR #&lt;/span&gt;101 created and merged
&lt;span class="go"&gt;
⏱️  Waiting 15 seconds...

&lt;/span&gt;&lt;span class="gp"&gt;🔹 Processing PR #&lt;/span&gt;2
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔑 The Co-authored-by Mechanic
&lt;/h2&gt;

&lt;p&gt;The key to how this project works is a Git commit trailer that GitHub specifically recognises:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;feat: automated update #1

This is an automated co-authored commit.

Co-authored-by: Collaborator Name &lt;span class="nv"&gt;&amp;lt;collaborator@email.com&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a PR containing this trailer is merged, GitHub awards the Pair Extraordinaire badge to &lt;strong&gt;both&lt;/strong&gt; the author and the co-author. The email in the trailer must match an email associated with the collaborator's GitHub account — that's a common gotcha.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛡️ Security Considerations
&lt;/h2&gt;

&lt;p&gt;A few things to keep in mind when running this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never commit your &lt;code&gt;.env&lt;/code&gt; file&lt;/strong&gt; — it's already in &lt;code&gt;.gitignore&lt;/code&gt;, keep it that way&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;fine-grained personal access tokens&lt;/strong&gt; scoped to specific repos only&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rotate tokens every 30–90 days&lt;/strong&gt; as a good hygiene practice&lt;/li&gt;
&lt;li&gt;Monitor your rate limit with &lt;code&gt;gh api rate_limit&lt;/code&gt; — you get 5,000 requests/hour per token, and multi-token rotation lets you stack that&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🐛 Common Issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;gh: command not found&lt;/code&gt;&lt;/strong&gt; → Install GitHub CLI for your platform and verify with &lt;code&gt;gh --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Authentication failed&lt;/code&gt;&lt;/strong&gt; → Run &lt;code&gt;gh auth login&lt;/code&gt; and follow the prompts, or use &lt;code&gt;echo "TOKEN" | gh auth login --with-token&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Co-authored-by not recognized&lt;/code&gt;&lt;/strong&gt; → Double-check that &lt;code&gt;CO_AUTHOR_EMAIL&lt;/code&gt; exactly matches an email registered on the collaborator's GitHub account&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;API rate limit exceeded&lt;/code&gt;&lt;/strong&gt; → Increase &lt;code&gt;delay_seconds&lt;/code&gt; in config, or add a second token for rotation&lt;/p&gt;




&lt;h2&gt;
  
  
  📈 Real-World Benchmarks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Badge Goal&lt;/th&gt;
&lt;th&gt;PRs&lt;/th&gt;
&lt;th&gt;Approx. Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~30 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bronze&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;~3 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Silver&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;~5 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gold&lt;/td&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;~10 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💡 What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;This project is a great reference for several Python and GitHub automation patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stateful automation&lt;/strong&gt; — persisting progress to a JSON file so a long-running task can be safely interrupted and resumed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exponential backoff&lt;/strong&gt; — retry logic that doubles the wait time on each failure (5s → 10s → 20s) to avoid hammering a rate-limited API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token rotation&lt;/strong&gt; — cycling through multiple API tokens to multiply your effective request quota&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template-based commit messages&lt;/strong&gt; — separating message content from code so customisation doesn't require touching logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhook integration&lt;/strong&gt; — pushing structured notifications to Discord/Slack with colour-coded severity levels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if you never use this for badge automation specifically, these patterns come up constantly in real-world automation and DevOps work.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 Contributing
&lt;/h2&gt;

&lt;p&gt;The project is MIT licensed and welcomes contributions. If you want to jump in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh repo fork itxashancode/Pair-Extraordinaire-Automation
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature/your-improvement
&lt;span class="c"&gt;# Make changes, commit with conventional commits&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat: add your amazing feature"&lt;/span&gt;
gh &lt;span class="nb"&gt;pr &lt;/span&gt;create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The codebase follows type hints and clear docstrings — &lt;code&gt;black&lt;/code&gt; for formatting, &lt;code&gt;flake8&lt;/code&gt; for style, &lt;code&gt;mypy&lt;/code&gt; for type checking.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/itxashancode/Pair-Extraordinaire-Automation" rel="noopener noreferrer"&gt;itxashancode/Pair-Extraordinaire-Automation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👤 &lt;strong&gt;Author:&lt;/strong&gt; &lt;a href="https://github.com/itxashancode" rel="noopener noreferrer"&gt;@itxashancode&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;More from the author:&lt;/strong&gt; &lt;a href="https://linktr.ee/itxashanvibes" rel="noopener noreferrer"&gt;linktr.ee/itxashanvibes&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you found this interesting, drop a ⭐ on the repo and let me know in the comments — what GitHub automation patterns have you built or wanted to build?&lt;/p&gt;

</description>
      <category>python</category>
      <category>github</category>
      <category>opensource</category>
      <category>automation</category>
    </item>
    <item>
      <title>I'm a Self-Taught Dev from Pakistan — Here's What My First 6 Months Looked Like</title>
      <dc:creator>Ashan_Dev</dc:creator>
      <pubDate>Thu, 05 Mar 2026 16:37:40 +0000</pubDate>
      <link>https://dev.to/itxashancode/im-a-self-taught-dev-from-pakistan-heres-what-my-first-6-months-looked-like-1i0m</link>
      <guid>https://dev.to/itxashancode/im-a-self-taught-dev-from-pakistan-heres-what-my-first-6-months-looked-like-1i0m</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Everyone talks about learning to code. Nobody talks about learning to code when resources cost money you don't have, and people around you don't understand why you're staring at a screen at 2 AM."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm &lt;strong&gt;Ashan&lt;/strong&gt; — a student at APTECH Pakistan and an aspiring full stack developer. This is my honest, unfiltered story.&lt;/p&gt;




&lt;h2&gt;
  
  
  📅 Month 1–2: HTML &amp;amp; CSS (The Honeymoon Phase)
&lt;/h2&gt;

&lt;p&gt;I started the way everyone does — building a portfolio page that looked &lt;em&gt;nothing&lt;/em&gt; like what I imagined.&lt;/p&gt;

&lt;p&gt;I spent &lt;strong&gt;3 hours&lt;/strong&gt; trying to center a div. No joke.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
Please just center



  Finally.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The lesson?&lt;/strong&gt; Everyone struggles with CSS at first. It's not you — it's the box model.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Month 3–4: JavaScript Hit Different
&lt;/h2&gt;

&lt;p&gt;HTML/CSS felt visual and rewarding. JavaScript felt like being handed a book written in a language I'd never seen.&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="c1"&gt;// My first real "aha" moment&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;! You can actually code.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ashan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
&lt;span class="c1"&gt;// → Hello, Ashan! You can actually code.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The moment &lt;strong&gt;functions&lt;/strong&gt; clicked for me, everything changed. I started building small projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ A to-do app&lt;/li&gt;
&lt;li&gt;✅ A quiz game&lt;/li&gt;
&lt;li&gt;✅ A basic calculator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of them were pretty. All of them taught me something.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 Month 5–6: React &amp;amp; The Real World
&lt;/h2&gt;

&lt;p&gt;React blew my mind. Components, state, props — it felt like thinking in &lt;strong&gt;building blocks&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WelcomeCard&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&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="p"&gt;(&lt;/span&gt;

      &lt;span class="nx"&gt;Welcome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="err"&gt;👋&lt;/span&gt;
      &lt;span class="nx"&gt;You&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;re building something real.

  );
}

export default WelcomeCard;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mental shift from "writing HTML" to "composing UI" was huge.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 3 Things Nobody Told Me
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. You will Google everything — and that's completely normal
&lt;/h3&gt;

&lt;p&gt;Senior devs do it too. The skill isn't memorizing syntax. It's knowing &lt;em&gt;what&lt;/em&gt; to search for.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Build ugly projects first
&lt;/h3&gt;

&lt;p&gt;Pretty comes with practice. Shipping something broken teaches you more than planning something perfect.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Your background doesn't disqualify you
&lt;/h3&gt;

&lt;p&gt;It's your superpower story. Developers from non-traditional backgrounds bring perspectives the industry desperately needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 My Honest Progress Chart
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Month&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;th&gt;Feeling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;HTML basics&lt;/td&gt;
&lt;td&gt;🤩 Excited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;CSS layouts&lt;/td&gt;
&lt;td&gt;😤 Frustrated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;JS fundamentals&lt;/td&gt;
&lt;td&gt;😵 Confused&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;JS projects&lt;/td&gt;
&lt;td&gt;😤→😊 Getting it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;React intro&lt;/td&gt;
&lt;td&gt;🤯 Mind blown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;React + Firebase&lt;/td&gt;
&lt;td&gt;🔥 Building real things&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🚀 What's Next for Me
&lt;/h2&gt;

&lt;p&gt;I'm now diving into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; — for server-side rendering and full stack apps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase&lt;/strong&gt; — for auth, databases, and real-time features&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI integrations&lt;/strong&gt; — because that's where the web is going&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The journey is far from over — but I'm proud of how far I've come from that mis-centered div.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;💬 &lt;strong&gt;If you're starting&lt;/strong&gt; — what's the hardest thing you've hit so far? Drop it in the comments. Let's figure it out together. 👇&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>career</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
