<?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: Aliza Ali</title>
    <description>The latest articles on DEV Community by Aliza Ali (@stackmasteraliza).</description>
    <link>https://dev.to/stackmasteraliza</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%2F3703525%2Fcf13c18e-51da-45be-ab73-3da4313b3f47.png</url>
      <title>DEV Community: Aliza Ali</title>
      <link>https://dev.to/stackmasteraliza</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stackmasteraliza"/>
    <language>en</language>
    <item>
      <title>NotionOps AI — 4 AI Agents That Run Your Dev Workflow End-to-End</title>
      <dc:creator>Aliza Ali</dc:creator>
      <pubDate>Fri, 13 Mar 2026 14:35:46 +0000</pubDate>
      <link>https://dev.to/stackmasteraliza/notionops-ai-4-ai-agents-that-run-your-dev-workflow-end-to-end-11ki</link>
      <guid>https://dev.to/stackmasteraliza/notionops-ai-4-ai-agents-that-run-your-dev-workflow-end-to-end-11ki</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/notion-2026-03-04"&gt;Notion MCP 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;NotionOps AI&lt;/strong&gt; is an autonomous workflow engine that connects GitHub, OpenAI, and Notion into a single pipeline for software development teams.&lt;/p&gt;

&lt;p&gt;It runs &lt;strong&gt;4 specialized AI agents&lt;/strong&gt; that automate the daily dev lifecycle:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Issue Triage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fetches open GitHub issues, classifies priority &amp;amp; type with AI, creates Notion tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PR Review&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reviews PR diffs, scores code quality 1-10, posts GitHub comments, creates Notion approval gates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sprint Planner&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Selects top tasks from backlog, estimates story points with AI, populates Notion sprint board&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Daily Report&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Aggregates sprint metrics, generates standup summary, saves report to Notion&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The agents chain together into a full pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub Issues/PRs → OpenAI Agents → Human Review in Notion → Notion Databases
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The dashboard provides real-time SSE streaming of agent activity, live stat cards, a kanban sprint board, and a full pipeline visualization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key design decision&lt;/strong&gt;: The PR Review agent creates &lt;strong&gt;human-in-the-loop approval gates&lt;/strong&gt; in Notion when it finds low-quality PRs (score &amp;lt; 6). AI never takes destructive action without human sign-off.&lt;/p&gt;
&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Dashboard&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy598k0bj55joeb7y84ho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy598k0bj55joeb7y84ho.png" alt="Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pipeline Running&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllpw7wi0rqazw3fwq76u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllpw7wi0rqazw3fwq76u.png" alt="Pipeline Running"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Agent Output&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzbuejofzeb8u01a3hwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzbuejofzeb8u01a3hwl.png" alt="AI Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tasks View&lt;/th&gt;
&lt;th&gt;Sprint Board&lt;/th&gt;
&lt;th&gt;Reports&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy718486i2ng6mfkox36o.png" alt="Tasks"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvbboeyy5yuue6ado38v0.png" alt="Sprint"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlio4cugl0r9btgr0f1j.png" alt="Reports"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Notion Integration&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tasks Database&lt;/th&gt;
&lt;th&gt;Sprint Board&lt;/th&gt;
&lt;th&gt;Agent Reports&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ng35ye51mm9fny9hyx5.png" alt="Notion Tasks"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foq3iq127a414as4g7nx4.png" alt="Notion Sprint"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqo0v9gx7gob6tl329p5v.png" alt="Notion Reports"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Video Demo
&lt;/h2&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/_Ksiqn_yz4s"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;
&lt;h2&gt;
  
  
  Show us the code
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&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/stackmasteraliza" rel="noopener noreferrer"&gt;
        stackmasteraliza
      &lt;/a&gt; / &lt;a href="https://github.com/stackmasteraliza/notionops-ai" rel="noopener noreferrer"&gt;
        notionops-ai
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Autonomous AI workflow engine — 4 Gemini-powered agents that triage GitHub issues, review PRs, plan sprints, and generate standups, all coordinated through Notion.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;NotionOps AI — Software Dev Pipeline That Runs Itself 🤖&lt;/h1&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Notion MCP Challenge Submission&lt;/strong&gt; — An autonomous AI workflow engine that closes the loop between GitHub, OpenAI, human judgment, and Notion — in real time.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What It Does&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Most dev teams have a painful daily ritual: check GitHub for new issues, triage them manually, review PRs, update Notion, plan the sprint, write the standup. &lt;strong&gt;NotionOps AI eliminates every step of that with four specialized AI agents&lt;/strong&gt; and a real-time neon dashboard.&lt;/p&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;GitHub Issues/PRs  →  OpenAI Agents  →  Human Review Gate  →  Notion (Tasks · Sprint · Reports)
        ↑                                           |
        └───────────── feedback loop ───────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One click. The pipeline runs itself.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Demo Video&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://youtu.be/_Ksiqn_yz4s" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fstackmasteraliza%2Fnotionops-ai%2Fscreenshots%2Fdashboard.png" alt="Watch Demo"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Four AI Agents&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;br&gt;
&lt;thead&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/thead&gt;
&lt;br&gt;
&lt;tbody&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;🔍 &lt;strong&gt;Issue Triage&lt;/strong&gt;&lt;br&gt;
&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;Fetches all open GitHub issues, classifies each as Bug/Feature/Issue with High/Medium/Low priority&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;Notion task per issue + triage report&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;👀 &lt;strong&gt;PR Review&lt;/strong&gt;&lt;br&gt;
&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;Reviews every open PR, scores code&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/tbody&gt;
&lt;br&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/stackmasteraliza/notionops-ai" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  How I Used Notion MCP
&lt;/h2&gt;

&lt;p&gt;Notion is the &lt;strong&gt;central coordination layer&lt;/strong&gt; between AI agents and humans. Four databases drive the entire workflow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tasks Database&lt;/strong&gt;&lt;br&gt;
AI-triaged GitHub issues land here with structured metadata (priority, type, status, agent notes, GitHub URL). This is the single source of truth — the Sprint Planner reads from it, and humans can override AI classifications directly in Notion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Approvals Database&lt;/strong&gt;&lt;br&gt;
When the PR Review agent finds a problematic PR, it creates an approval page with its recommendation. Team members review and approve/reject directly in Notion. This is the human-in-the-loop gate — downstream agents respect these decisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Sprint Database&lt;/strong&gt;&lt;br&gt;
The Sprint Planner reads pending tasks from Notion, uses AI to estimate complexity and assign Fibonacci story points, then writes selected tasks back with Backlog/In Progress/Done status tracking. The dashboard renders this as a live kanban board.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Reports Database&lt;/strong&gt;&lt;br&gt;
Daily standup summaries are generated from sprint data and stored as rich-text report pages. This creates an automatic paper trail of team velocity and AI-generated insights over time.&lt;/p&gt;

&lt;p&gt;The key unlock: &lt;strong&gt;agents write structured data into Notion, humans make decisions in a familiar interface, and downstream agents read those decisions to continue the workflow.&lt;/strong&gt; No context switching between GitHub, AI tools, and project management — it all flows through Notion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runtime&lt;/strong&gt;: Node.js + TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI&lt;/strong&gt;: OpenAI via OpenRouter (structured JSON outputs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIs&lt;/strong&gt;: Notion API, GitHub REST API (Octokit)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server&lt;/strong&gt;: Express.js with Server-Sent Events&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Vanilla HTML/CSS/JS (zero framework dependencies)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm &lt;strong&gt;Aliza Ali&lt;/strong&gt; — a developer who loves building AI-powered tools that solve real workflow problems. If you liked this project, check out my other challenge submission:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/stackmasteraliza/fixforward" rel="noopener noreferrer"&gt;FixForward: One Command to Go from Broken Build to Ready-to-Merge PR&lt;/a&gt;&lt;/strong&gt; — A CLI autopilot that detects failing tests, classifies bugs, generates fixes via GitHub Copilot CLI, and creates verified PRs. One command. Three ecosystems. Zero manual patching.&lt;/p&gt;

&lt;p&gt;Want to know more? Visit &lt;a href="https://alizaali.com" rel="noopener noreferrer"&gt;alizaali.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Auto-Generate Swagger Docs in Laravel — Zero Annotations, Zero Config</title>
      <dc:creator>Aliza Ali</dc:creator>
      <pubDate>Wed, 18 Feb 2026 17:55:16 +0000</pubDate>
      <link>https://dev.to/stackmasteraliza/auto-generate-swagger-docs-in-laravel-zero-annotations-zero-config-hj</link>
      <guid>https://dev.to/stackmasteraliza/auto-generate-swagger-docs-in-laravel-zero-annotations-zero-config-hj</guid>
      <description>&lt;h2&gt;
  
  
  Writing Swagger Annotations Is Pain. What If You Didn't Have To?
&lt;/h2&gt;

&lt;p&gt;Be honest — how many times have you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skipped API documentation because &lt;code&gt;@OA\Get&lt;/code&gt; annotations are a nightmare?&lt;/li&gt;
&lt;li&gt;Spent more time writing Swagger comments than actual business logic?&lt;/li&gt;
&lt;li&gt;Shipped an API with &lt;strong&gt;zero docs&lt;/strong&gt; because "we'll add them later" (you didn't)?&lt;/li&gt;
&lt;li&gt;Manually maintained a Postman collection that's always 3 endpoints behind?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What if your Laravel app could &lt;strong&gt;scan your controllers, read your FormRequest rules, and generate a complete Swagger UI automatically?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No &lt;code&gt;@OA\&lt;/code&gt; annotations. No YAML files. No config. &lt;strong&gt;Just your existing code.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing: Laravel API Response Builder
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require stackmasteraliza/laravel-api-response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;v4.7.0&lt;/strong&gt; | &lt;strong&gt;Laravel 10, 11 &amp;amp; 12&lt;/strong&gt; | &lt;strong&gt;PHP 8.1+&lt;/strong&gt; | &lt;strong&gt;MIT License&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/stackmasteraliza/laravel-api-response-builder" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://packagist.org/packages/stackmasteraliza/laravel-api-response" rel="noopener noreferrer"&gt;Packagist&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The all-in-one Laravel API toolkit:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-generated Swagger/OpenAPI docs — &lt;strong&gt;no annotations&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;One-click export to Postman &amp;amp; Insomnia&lt;/li&gt;
&lt;li&gt;Standardized JSON responses&lt;/li&gt;
&lt;li&gt;WebSocket testing built-in&lt;/li&gt;
&lt;li&gt;API versioning out of the box&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Zero configuration required.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation (30 Seconds)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require stackmasteraliza/laravel-api-response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No config publishing. No migrations. No setup wizards.&lt;/p&gt;

&lt;p&gt;Your Swagger docs are already live at &lt;strong&gt;&lt;code&gt;/api-docs&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Auto-Generated Swagger Docs (The Main Event)
&lt;/h2&gt;

&lt;p&gt;This is why you're here. &lt;strong&gt;You don't write a single &lt;code&gt;@OA\&lt;/code&gt; annotation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The package scans your controllers, detects response methods like &lt;code&gt;ApiResponse::success()&lt;/code&gt; and &lt;code&gt;ApiResponse::created()&lt;/code&gt;, reads your &lt;code&gt;FormRequest&lt;/code&gt; validation rules, and generates a &lt;strong&gt;complete OpenAPI 3.0 specification&lt;/strong&gt; — automatically.&lt;/p&gt;

&lt;p&gt;Visit &lt;code&gt;/api-docs&lt;/code&gt; and you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Beautiful, modern Swagger UI with &lt;strong&gt;dark/light theme toggle&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Every endpoint documented with correct HTTP methods&lt;/li&gt;
&lt;li&gt;Request body schemas &lt;strong&gt;auto-generated from your FormRequest rules&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Response schemas matching your actual response structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try-it-out&lt;/strong&gt; functionality — test endpoints right from the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How It Detects Everything
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The package sees this in your controller...&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;StoreUserRequest&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'User created'&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...reads your FormRequest rules...&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StoreUserRequest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;FormRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&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="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|string|max:255'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|email|unique:users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|min:8'&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; A fully documented &lt;code&gt;POST&lt;/code&gt; endpoint in Swagger with request body schema, required fields, validation types, and a &lt;code&gt;201 Created&lt;/code&gt; response — all without you writing a single doc comment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Want Even More Control? Use PHP Attributes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Stackmasteraliza\ApiResponse\Attributes\ApiEndpoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Stackmasteraliza\ApiResponse\Attributes\ApiRequestBody&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;ApiEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Create a new user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Register a new user account'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Users'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;ApiRequestBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;StoreUserRequest&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;JsonResponse&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'User created'&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;Attributes are &lt;strong&gt;optional&lt;/strong&gt; — use them only when you want to add summaries, descriptions, or override auto-detected schemas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Export to Postman &amp;amp; Insomnia (One Click)
&lt;/h2&gt;

&lt;p&gt;From the Swagger UI, export your entire API documentation:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;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;Postman&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Import directly into Postman&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Insomnia&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Import directly into Insomnia&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JSON&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CI/CD pipelines, SDK generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;YAML&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Human-readable specs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Your Postman collection is &lt;strong&gt;always in sync&lt;/strong&gt; with your code. No manual maintenance.&lt;/p&gt;




&lt;h2&gt;
  
  
  API Versioning in Swagger UI
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API_DOCS_VERSIONING=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The package auto-detects &lt;code&gt;api/v1/*&lt;/code&gt;, &lt;code&gt;api/v2/*&lt;/code&gt; patterns and adds a &lt;strong&gt;version switcher&lt;/strong&gt; in the Swagger UI. Each version gets its own OpenAPI spec. Your frontend team can browse docs for any version.&lt;/p&gt;




&lt;h2&gt;
  
  
  WebSocket Testing (Yes, In Swagger)
&lt;/h2&gt;

&lt;p&gt;Test WebSocket connections directly from the Swagger UI. Send messages, subscribe to channels, see real-time responses — with pre-built templates for Subscribe, Unsubscribe, Ping, and Client Events.&lt;/p&gt;

&lt;p&gt;No Postman. No wscat. Just click and test.&lt;/p&gt;




&lt;h2&gt;
  
  
  But Wait — It's Also a Complete Response Builder
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Facade Way
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Stackmasteraliza\ApiResponse\Facades\ApiResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Users retrieved'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;StoreUserRequest&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'User created'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;noContent&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Or Use the Trait
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Stackmasteraliza\ApiResponse\Traits\HasApiResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasApiResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Users retrieved'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Both give you perfectly consistent responses:&lt;/strong&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;"status_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"success"&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;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Users retrieved"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jane Doe"&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;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"current_page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"per_page"&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;"total"&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;"last_page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"to"&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;"links"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://example.com/api/users?page=1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://example.com/api/users?page=2"&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;span class="p"&gt;}&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;p&gt;Pagination metadata is &lt;strong&gt;automatically detected and included&lt;/strong&gt;. No extra code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Every Error Response You'll Ever Need
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;badRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Invalid input'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// 400&lt;/span&gt;
&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Token expired'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// 401&lt;/span&gt;
&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;forbidden&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Admin only'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;// 403&lt;/span&gt;
&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'User not found'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;             &lt;span class="c1"&gt;// 404&lt;/span&gt;
&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;conflict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Email already exists'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// 409&lt;/span&gt;
&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;validationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$errors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;               &lt;span class="c1"&gt;// 422&lt;/span&gt;
&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;tooManyRequests&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Slow down'&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="c1"&gt;// 429&lt;/span&gt;
&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;serverError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Something broke'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// 500&lt;/span&gt;
&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;serviceUnavailable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Back soon'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// 503&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Consistent structure every time:&lt;/strong&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;"status_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"success"&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;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Validation failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"The email field is required."&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"The password must be at least 8 characters."&lt;/span&gt;&lt;span class="p"&gt;]&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;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;
  
  
  Exception Handling That Just Works
&lt;/h2&gt;

&lt;p&gt;Drop this into your &lt;code&gt;bootstrap/app.php&lt;/code&gt; (Laravel 11+):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Stackmasteraliza\ApiResponse\Exceptions\ApiExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withExceptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Exceptions&lt;/span&gt; &lt;span class="nv"&gt;$exceptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$exceptions&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Throwable&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every exception — &lt;code&gt;ValidationException&lt;/code&gt;, &lt;code&gt;ModelNotFoundException&lt;/code&gt;, &lt;code&gt;AuthenticationException&lt;/code&gt; — returns a clean, consistent JSON response. No more HTML error pages in your API.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Helpers
&lt;/h2&gt;

&lt;p&gt;Write expressive API tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/api/users'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertApiSuccess&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertApiStatusCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertApiMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Users retrieved'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertApiHasData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertApiPaginated&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Customize Everything
&lt;/h2&gt;

&lt;p&gt;Publish the config and make it yours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;api-response-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change response keys, pagination keys, default messages, theme colors, branding — everything is configurable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config/api-response.php&lt;/span&gt;
&lt;span class="s1"&gt;'keys'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'success'&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'message'&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'data'&lt;/span&gt;        &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'data'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'errors'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'errors'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'meta'&lt;/span&gt;        &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'meta'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'status_code'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'status_code'&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;h2&gt;
  
  
  Extend With Custom Macros
&lt;/h2&gt;

&lt;p&gt;Need custom response types? The package is macroable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'banned'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Account suspended'&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$reason&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Then use it anywhere&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;banned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Your account has been suspended'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Developers Are Switching
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Writing &lt;code&gt;@OA\&lt;/code&gt; annotations for hours&lt;/td&gt;
&lt;td&gt;Auto-generated Swagger docs from code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Postman collections always outdated&lt;/td&gt;
&lt;td&gt;One-click Postman/Insomnia export&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No WebSocket documentation&lt;/td&gt;
&lt;td&gt;Built-in WebSocket tester in Swagger&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inconsistent response formats&lt;/td&gt;
&lt;td&gt;One standardized JSON structure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom exception handlers&lt;/td&gt;
&lt;td&gt;Built-in error handling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Copy-paste response code&lt;/td&gt;
&lt;td&gt;One-liner fluent methods&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Install&lt;/span&gt;
composer require stackmasteraliza/laravel-api-response

&lt;span class="c"&gt;# 2. Use in controllers&lt;/span&gt;
&lt;span class="c"&gt;# (Facade or Trait — your choice)&lt;/span&gt;

&lt;span class="c"&gt;# 3. Visit /api-docs&lt;/span&gt;
&lt;span class="c"&gt;# Your documentation is already there&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Supports Laravel 10, 11, and 12 | PHP 8.1+&lt;/strong&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/stackmasteraliza/laravel-api-response" rel="noopener noreferrer"&gt;stackmasteraliza/laravel-api-response&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Packagist&lt;/strong&gt;: &lt;a href="https://packagist.org/packages/stackmasteraliza/laravel-api-response" rel="noopener noreferrer"&gt;stackmasteraliza/laravel-api-response&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;If this package saves you time, give it a star on GitHub and share it with your team.&lt;/p&gt;

&lt;p&gt;Got questions, ideas, or feature requests? Drop a comment below or open an issue on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow me for more Laravel packages and PHP tips:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dev.to&lt;/strong&gt;: &lt;a href="https://dev.to/stackmasteraliza"&gt;@stackmasteraliza&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/stackmasteraliza" rel="noopener noreferrer"&gt;@stackmasteraliza&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy coding!&lt;br&gt;
— &lt;strong&gt;Aliza Ali&lt;/strong&gt; (&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/stackmasteraliza"&gt;@stackmasteraliza&lt;/a&gt;&lt;/strong&gt;)&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>swagger</category>
      <category>api</category>
    </item>
    <item>
      <title>FixForward: One Command to Go from Broken Build to Ready-to-Merge PR</title>
      <dc:creator>Aliza Ali</dc:creator>
      <pubDate>Sun, 15 Feb 2026 14:54:11 +0000</pubDate>
      <link>https://dev.to/stackmasteraliza/fixforward-one-command-to-go-from-broken-build-to-ready-to-merge-pr-167g</link>
      <guid>https://dev.to/stackmasteraliza/fixforward-one-command-to-go-from-broken-build-to-ready-to-merge-pr-167g</guid>
      <description>&lt;p&gt;&lt;strong&gt;GitHub Copilot CLI Challenge Submission&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is my submission for the &lt;a href="https://dev.to/challenges/github"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Every developer knows the pain: your build breaks, your tests fail, and suddenly you're down a rabbit hole of stack traces, file-hopping, and manual patching. I've been there one too many times, so I built &lt;strong&gt;FixForward&lt;/strong&gt; — a CLI autopilot that takes you from broken tests to a verified, ready-to-merge PR in a single command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;fixforward
fixforward run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. One command.&lt;/p&gt;

&lt;p&gt;FixForward detects your test framework, runs the suite, parses the failures, classifies each one, asks &lt;strong&gt;GitHub Copilot CLI&lt;/strong&gt; to generate a minimal fix, applies it on a safe branch, re-runs your tests to verify the fix actually works, and generates a PR description with a confidence score. The entire pipeline is automated, and the entire tool is powered by Copilot CLI under the hood.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsryrio20awbl94f8qbbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsryrio20awbl94f8qbbg.png" alt="FixForward Cover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Here is FixForward running against a real broken Python project. It detects the failing test, classifies the bug as an assertion failure, generates a one-line fix via Copilot CLI, patches the file, re-runs the tests, and reports 95% confidence — all without leaving the terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fstackmasteraliza%2Ffixforward%2Fmain%2Fassets%2Fdemo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fstackmasteraliza%2Ffixforward%2Fmain%2Fassets%2Fdemo.gif" alt="FixForward Demo" width="1000" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pipeline: How It Works
&lt;/h2&gt;

&lt;p&gt;FixForward is not a wrapper around a single Copilot prompt. It's a &lt;strong&gt;full incident response pipeline&lt;/strong&gt; with 8 distinct stages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tests fail → parse output → classify failure → Copilot generates fix
     → apply on safe branch → re-run tests → confidence score → PR report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Detect&lt;/strong&gt; — Scans for &lt;code&gt;pytest.ini&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, or &lt;code&gt;Cargo.toml&lt;/code&gt; to identify your ecosystem automatically. No config files, no setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Run Tests&lt;/strong&gt; — Executes your test suite (&lt;code&gt;pytest&lt;/code&gt;, &lt;code&gt;npm test&lt;/code&gt;, or &lt;code&gt;cargo test&lt;/code&gt;) and captures full raw output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Parse&lt;/strong&gt; — Custom parsers extract individual failures with file paths, line numbers, error messages, and tracebacks. This isn't regex on the whole blob — there are dedicated parsers for pytest, Jest/Mocha, and cargo test that understand each format's quirks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Classify&lt;/strong&gt; — Categorizes every failure using heuristic pattern matching:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;th&gt;Confidence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;syntax_error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;SyntaxError&lt;/code&gt;, &lt;code&gt;IndentationError&lt;/code&gt;, &lt;code&gt;Unexpected token&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;95%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dependency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ModuleNotFoundError&lt;/code&gt;, &lt;code&gt;Cannot find module&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;api_change&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;AttributeError&lt;/code&gt;, &lt;code&gt;TypeError&lt;/code&gt; (wrong args)&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;assertion&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;AssertionError&lt;/code&gt;, &lt;code&gt;assert_eq!&lt;/code&gt;, &lt;code&gt;expect().toEqual()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;85%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;env_mismatch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Version conflicts, missing commands&lt;/td&gt;
&lt;td&gt;80%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Flake8, ESLint, Clippy warnings&lt;/td&gt;
&lt;td&gt;75%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;flaky_test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Timeouts, connection refused, intermittent&lt;/td&gt;
&lt;td&gt;60%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;5. Generate Patch&lt;/strong&gt; — Sends structured failure context + relevant source files to GitHub Copilot CLI (&lt;code&gt;gh copilot -p&lt;/code&gt;) for a minimal fix. Copilot reads the actual code, understands the bug, and generates the smallest possible change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Apply&lt;/strong&gt; — Creates a &lt;code&gt;fixforward/auto-*&lt;/code&gt; branch, writes the patched files, and commits. Your working branch is &lt;strong&gt;never touched&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Verify&lt;/strong&gt; — Re-runs the entire test suite on the fix branch and computes a before/after confidence score.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Report&lt;/strong&gt; — Generates a Markdown PR title and body with what changed, why, and the verification results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Screenshots
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Full Autopilot Run
&lt;/h3&gt;

&lt;p&gt;The complete pipeline from broken tests to verified fix:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1arg61oo7gdwrqd5iawp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1arg61oo7gdwrqd5iawp.png" alt="Full run" width="780" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnose Mode
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;fixforward diagnose&lt;/code&gt; to inspect failures without applying any changes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz975p1dfw226kkx5maf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz975p1dfw226kkx5maf3.png" alt="Diagnose" width="780" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Detection
&lt;/h3&gt;

&lt;p&gt;FixForward recognizes when the fix isn't a code change but a missing package:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kw6tfiuzivyvn2ni6xu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kw6tfiuzivyvn2ni6xu.png" alt="Dependency" width="780" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Ecosystem: Node.js Support
&lt;/h3&gt;

&lt;p&gt;Same pipeline, different ecosystem. Jest failures parsed and classified automatically:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9iuwjhsm3y6wwcod5xw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9iuwjhsm3y6wwcod5xw.png" alt="Node.js" width="780" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Ecosystems, One Interface
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ecosystem&lt;/th&gt;
&lt;th&gt;Test Command&lt;/th&gt;
&lt;th&gt;What Gets Parsed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pytest --tb=long -v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Failures, tracebacks, assertion details, collection errors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jest and Mocha output, suite-level failures, missing modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Panics, &lt;code&gt;assert_eq!&lt;/code&gt; failures, test summaries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I didn't just support one language and call it a day. Each ecosystem has its own parser that understands the specific output format — pytest tracebacks look nothing like Jest failures, and cargo test panics are their own thing entirely. FixForward handles all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety First
&lt;/h2&gt;

&lt;p&gt;I spent a lot of time thinking about what could go wrong. When you're auto-applying code patches, you better not destroy someone's working tree. FixForward has several layers of protection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never touches your working branch&lt;/strong&gt; — all fixes go on &lt;code&gt;fixforward/auto-*&lt;/code&gt; branches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stashes dirty state&lt;/strong&gt; — uncommitted changes are saved and restored on rollback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Patch preview&lt;/strong&gt; — see the exact diff before confirming&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dry-run mode&lt;/strong&gt; — &lt;code&gt;fixforward run --dry-run&lt;/code&gt; diagnoses without touching anything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-command rollback&lt;/strong&gt; — &lt;code&gt;fixforward rollback&lt;/code&gt; undoes everything cleanly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State persistence&lt;/strong&gt; — rollback info stored at &lt;code&gt;~/.fixforward/state.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted this to be a tool you could trust running in your repo without hesitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;Copilot CLI is not just a helper in this project — it &lt;strong&gt;is&lt;/strong&gt; the engine. FixForward uses &lt;code&gt;gh copilot -p&lt;/code&gt; at its core to generate the actual code fixes. Here's what that looks like internally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh copilot &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"I have a python project with failing tests.
  The test test_divide in test_app.py fails with AssertionError:
  assert 3.333 == 3. Generate a minimal fix..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-all-tools&lt;/span&gt; &lt;span class="nt"&gt;--add-dir&lt;/span&gt; ./project &lt;span class="nt"&gt;--silent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copilot reads the source files through &lt;code&gt;--add-dir&lt;/code&gt;, understands the test context, and generates the smallest code change. FixForward then parses Copilot's response (which can come in several formats — code blocks, file headers, inline diffs), extracts the patched files, and applies them.&lt;/p&gt;

&lt;p&gt;Building the Copilot response parser was one of the trickier parts. Copilot doesn't always respond in the same format, so I built multiple parsing strategies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fenced code blocks&lt;/strong&gt; with &lt;code&gt;FILE:&lt;/code&gt; markers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filename headers&lt;/strong&gt; (### file.js, &lt;strong&gt;file.js&lt;/strong&gt;, backtick file.js) followed by code blocks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language-tagged blocks&lt;/strong&gt; matched to project files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fuzzy file matching&lt;/strong&gt; against the project tree (skipping node_modules)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If one strategy fails, the next one kicks in. This makes FixForward resilient to Copilot's varying output formats.&lt;/p&gt;

&lt;p&gt;I also used Copilot CLI extensively during development — for scaffolding parsers, debugging edge cases in Jest output handling, and figuring out the right subprocess patterns for capturing test output across platforms.&lt;/p&gt;

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

&lt;p&gt;The repo includes ready-made broken demo projects:&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/stackmasteraliza/fixforward.git
&lt;span class="nb"&gt;cd &lt;/span&gt;fixforward

&lt;span class="c"&gt;# Python: division bug (a / b should be a // b)&lt;/span&gt;
fixforward run &lt;span class="nt"&gt;--path&lt;/span&gt; demo/broken_python

&lt;span class="c"&gt;# Node.js: truncation bug ("..." becomes "..")&lt;/span&gt;
fixforward diagnose &lt;span class="nt"&gt;--path&lt;/span&gt; demo/broken_node

&lt;span class="c"&gt;# Rust: off-by-one in clamp()&lt;/span&gt;
fixforward diagnose &lt;span class="nt"&gt;--path&lt;/span&gt; demo/broken_rust

&lt;span class="c"&gt;# Safe mode: see the diagnosis without changing anything&lt;/span&gt;
fixforward run &lt;span class="nt"&gt;--path&lt;/span&gt; demo/broken_python &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install from PyPI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;fixforward
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;fixforward/
├── cli.py          # argparse CLI: run, diagnose, rollback
├── detector.py     # Ecosystem detection + test runner
├── classifier.py   # Regex heuristic failure classification
├── copilot.py      # GitHub Copilot CLI integration
├── patcher.py      # Safe branch creation + file patching
├── verifier.py     # Test re-run + confidence scoring
├── reporter.py     # PR title/body generation
├── display.py      # Rich-based terminal UI
├── state.py        # Rollback state persistence
└── parsers/
    ├── pytest_parser.py   # pytest output parser
    ├── npm_parser.py      # Jest/Mocha output parser
    └── cargo_parser.py    # cargo test output parser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Only one dependency:&lt;/strong&gt; &lt;a href="https://github.com/Textualize/rich" rel="noopener noreferrer"&gt;&lt;code&gt;rich&lt;/code&gt;&lt;/a&gt;. Everything else is Python standard library.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PyPI:&lt;/strong&gt; &lt;a href="https://pypi.org/project/fixforward/" rel="noopener noreferrer"&gt;fixforward on PyPI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/stackmasteraliza/fixforward" rel="noopener noreferrer"&gt;stackmasteraliza/fixforward on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thanks for reading! I'd love to hear your feedback — especially if you try it on your own broken tests.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>I built Spotify Wrapped for Git using GitHub Copilot CLI</title>
      <dc:creator>Aliza Ali</dc:creator>
      <pubDate>Sun, 15 Feb 2026 06:37:15 +0000</pubDate>
      <link>https://dev.to/stackmasteraliza/i-built-spotify-wrapped-for-git-using-github-copilot-cli-10lj</link>
      <guid>https://dev.to/stackmasteraliza/i-built-spotify-wrapped-for-git-using-github-copilot-cli-10lj</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI 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;git-wrapped&lt;/strong&gt; — Spotify Wrapped, but for your Git history.&lt;/p&gt;

&lt;p&gt;Every December, Spotify tells you what kind of listener you are. I wanted the same thing for coding. What if your terminal could tell you that you're a Night Owl who codes at 2 AM, or a Code Surgeon who deletes more than they write?&lt;/p&gt;

&lt;p&gt;git-wrapped is a Python CLI tool that analyzes any Git repository and generates a beautiful, colorful terminal report. No browser, no dashboard, no account — just run a command and see your year in code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Full Feature Set
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Numbers&lt;/strong&gt; — Total commits, files changed, lines added/deleted, net line impact, active days&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activity Heatmap&lt;/strong&gt; — A GitHub-style contribution calendar rendered entirely in your terminal using Unicode block characters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When You Code&lt;/strong&gt; — Hour-of-day and day-of-week bar charts showing your coding rhythm&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Top Files&lt;/strong&gt; — Leaderboard of your most frequently modified files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Languages&lt;/strong&gt; — Programming language breakdown with percentage bars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaks &amp;amp; Records&lt;/strong&gt; — Longest streak, current streak, busiest single day, best month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coder DNA&lt;/strong&gt; — A personality assessment based on your commit patterns: Night Owl, Early Bird, Weekend Warrior, Streak Master, Feature Machine, Code Surgeon, or Balanced Builder&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fun Facts&lt;/strong&gt; — Holiday commits, longest/shortest commit messages, contributor count, productivity stats&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare Mode&lt;/strong&gt; — Year-over-year comparison (&lt;code&gt;--compare 2024 2025&lt;/code&gt;) with delta percentages and personality shift tracking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share Card&lt;/strong&gt; — A copy-pasteable plain text card for sharing on social media (&lt;code&gt;--share&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON Export&lt;/strong&gt; — Dump raw stats as JSON for further analysis or integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why I Built This
&lt;/h3&gt;

&lt;p&gt;I spend a lot of time in the terminal. I wanted something that celebrates the work developers do — not just the PRs that get merged, but the late-night debugging sessions, the weekend side projects, the 14-day commit streaks that nobody notices.&lt;/p&gt;

&lt;p&gt;git-wrapped makes that visible. And it's fun.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;GitHub repo:&lt;/strong&gt; &lt;a href="https://github.com/stackmasteraliza/git-wrapped" rel="noopener noreferrer"&gt;stackmasteraliza/git-wrapped&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5r4mvzjvblvc1lxsqao.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5r4mvzjvblvc1lxsqao.gif" alt="Demo" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it yourself
&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;# Install from PyPI&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;git-wrapped

&lt;span class="c"&gt;# Or install from source&lt;/span&gt;
git clone https://github.com/stackmasteraliza/git-wrapped.git
&lt;span class="nb"&gt;cd &lt;/span&gt;git-wrapped
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Run on any repo&lt;/span&gt;
git-wrapped

&lt;span class="c"&gt;# Analyze a specific year&lt;/span&gt;
git-wrapped &lt;span class="nt"&gt;--year&lt;/span&gt; 2025

&lt;span class="c"&gt;# Compare two years&lt;/span&gt;
git-wrapped &lt;span class="nt"&gt;--compare&lt;/span&gt; 2024 2025

&lt;span class="c"&gt;# Generate a share card&lt;/span&gt;
git-wrapped &lt;span class="nt"&gt;--share&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.8+&lt;/strong&gt; — Core language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich&lt;/strong&gt; — Terminal formatting (panels, tables, progress bars, styled text)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git log parsing&lt;/strong&gt; — Custom parser using &lt;code&gt;--numstat&lt;/code&gt; and &lt;code&gt;--format&lt;/code&gt; for file-level stats&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero external API calls&lt;/strong&gt; — Everything runs locally, your data never leaves your machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One external dependency. That's it.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot CLI was my pair programmer for this entire project. Instead of tab-switching between Stack Overflow, Git docs, and Rich documentation, I stayed in my terminal and asked Copilot directly.&lt;/p&gt;

&lt;p&gt;Here's exactly how I used it at each stage of development:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Understanding git log format
&lt;/h3&gt;

&lt;p&gt;The first challenge was figuring out how to extract structured data from &lt;code&gt;git log&lt;/code&gt;. I asked Copilot CLI to explain the &lt;code&gt;--format&lt;/code&gt; flags, and it gave me a clear breakdown of every placeholder — &lt;code&gt;%H&lt;/code&gt; for hash, &lt;code&gt;%an&lt;/code&gt; for author name, &lt;code&gt;%aI&lt;/code&gt; for ISO date, &lt;code&gt;%s&lt;/code&gt; for subject line — plus how &lt;code&gt;--numstat&lt;/code&gt; adds per-file insertion/deletion stats and how &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; delimiters can separate commits for reliable parsing.&lt;/p&gt;

&lt;p&gt;This saved me from trial-and-error with Git's dense documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foizmomnfqcp7gxupzvqq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foizmomnfqcp7gxupzvqq.png" alt="Copilot CLI — git log format" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Calculating commit streaks
&lt;/h3&gt;

&lt;p&gt;Computing the longest daily commit streak was trickier than expected. I needed to handle gaps, deduplicate dates, and track both the longest historical streak and the current active one.&lt;/p&gt;

&lt;p&gt;I asked Copilot CLI for approaches and it gave me multiple solutions — a Python version using &lt;code&gt;datetime.timedelta&lt;/code&gt; to detect consecutive days, and even a Bash one-liner. I adapted the Python approach directly into my analyzer:&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="c1"&gt;# Copilot helped me arrive at this pattern
&lt;/span&gt;&lt;span class="n"&gt;sorted_dates&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="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commit_dates&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;streak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_streak&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="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&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;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_dates&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_dates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;sorted_dates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&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="n"&gt;days&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="n"&gt;streak&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;max_streak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_streak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;streak&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;streak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljyu5xivaulqoz9t50ez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljyu5xivaulqoz9t50ez.png" alt="Copilot CLI — streak calculation" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Grouping commits by hour of day
&lt;/h3&gt;

&lt;p&gt;For the "When You Code" charts, I needed to count commits grouped by hour. Copilot CLI gave me multiple shell approaches — from simple &lt;code&gt;cut&lt;/code&gt; pipelines to &lt;code&gt;awk&lt;/code&gt; loops — which helped me understand the data shape before writing the Python version.&lt;/p&gt;

&lt;p&gt;Seeing the shell approach first made the Python implementation obvious.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frp83vg71d5xhv428gfeo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frp83vg71d5xhv428gfeo.png" alt="Copilot CLI — hourly commits" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Rendering the terminal heatmap
&lt;/h3&gt;

&lt;p&gt;This was the hardest visual to get right. A GitHub-style contribution heatmap, but in the terminal, using colored Unicode blocks.&lt;/p&gt;

&lt;p&gt;I asked Copilot CLI how to render a colored heatmap using Python's Rich library, and it showed me two approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Table-based approach&lt;/strong&gt; using Rich's &lt;code&gt;Table&lt;/code&gt; with colored cells&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;block character approach&lt;/strong&gt; mapping values to &lt;code&gt;█&lt;/code&gt; characters with ANSI colors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ended up combining both — using Rich's &lt;code&gt;Console&lt;/code&gt; for color management and block characters for the grid cells:&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;colors&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;bright_black&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;dark_green&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;green&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;bright_green&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;█&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;week&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weeks&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;day&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;intensity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_intensity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;week&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;day&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&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;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;intensity&lt;/span&gt;&lt;span class="p"&gt;]&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;char&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;[/]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9g9japdx7p9j0xahkac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9g9japdx7p9j0xahkac.png" alt="Copilot CLI — heatmap rendering" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Impact
&lt;/h3&gt;

&lt;p&gt;Without Copilot CLI, each of these problems would have meant opening a browser, scanning docs, finding a relevant example, adapting it, and testing. That cycle breaks flow.&lt;/p&gt;

&lt;p&gt;With Copilot CLI, the cycle was: ask a question → get a working answer → adapt and move on. I stayed in my terminal the entire time. The cognitive load dropped and I could focus on making the output feel delightful instead of fighting implementation details.&lt;/p&gt;

&lt;p&gt;It felt less like using a tool and more like pair programming with someone who has every man page memorized.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenges &amp;amp; Discoveries
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The heatmap was the hardest part.&lt;/strong&gt; Terminals don't have pixels — you're working with a character grid where each "cell" is a text character. Getting the heatmap to look like GitHub's contribution graph required careful math: mapping 52 weeks × 7 days into a grid, choosing the right Unicode block characters, and picking green shades that look good across different terminal themes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Personality detection was surprisingly fun.&lt;/strong&gt; The "Coder DNA" feature assigns you a personality based on your commit patterns. Calibrating the thresholds (e.g., "30% of commits after 10 PM = Night Owl") required running it against a bunch of real repos to make sure the labels felt accurate and fun, not arbitrary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rich is incredible.&lt;/strong&gt; Python's Rich library does the heavy lifting for all the terminal visuals — panels, tables, progress bars, colored text. It's the reason git-wrapped looks polished without needing a web UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes This Special
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See your coding habits visualized in seconds&lt;/li&gt;
&lt;li&gt;Discover patterns you didn't know you had (turns out I code most on Thursdays)&lt;/li&gt;
&lt;li&gt;A fun conversation starter in team standups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For teams:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run it on shared repos to see team-wide patterns&lt;/li&gt;
&lt;li&gt;Compare year-over-year to track how the team's rhythm evolves&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For the community:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fully open source — fork it, extend it, make it yours&lt;/li&gt;
&lt;li&gt;Single dependency — easy to install anywhere&lt;/li&gt;
&lt;li&gt;Privacy-first — everything runs locally, no data leaves your machine&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Built with Python, Rich, and a lot of late-night commits. Powered by GitHub Copilot CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/stackmasteraliza/git-wrapped" rel="noopener noreferrer"&gt;stackmasteraliza/git-wrapped&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
  </channel>
</rss>
