- Turn user feedback into an actionable test and bug-fixing plan using a systematic framework
- Use AI-assisted debugging and apply the “teach me” pattern to understand fixes
- Write simple tests to verify fixes work and catch potential regression issues
- Use browser DevTools to identify and diagnose problems
- Debugged MVP: Your MVP app with P0/P1 bugs fixed
- Feedback Triage System: A prioritized action plan using the 3-question framework and MoSCoW method
- Issue Tracker: Structured documentation of bugs, root causes, and fixes
- Test Checklist: Documentation for regression prevention and issue tracking
- Students have completed a working MVP (screens, navigation, AI feature) in Building Your AI-Powered Prototype
- Students have completed Iterating and Refining Your MVP with user testing feedback from 5-10 users
By now you have built an AI-powered MVP and tested edge cases before sharing it. Now your real users have tried your app, and they have feedback. Some features work great. Others may confuse users or break unexpectedly. This is normal. Every startup goes through this.
As you explored in Iterating and Refining Your MVP, collecting and synthesizing user feedback is essential to refining your MVP. The challenge now is turning that feedback into code fixes. When users report “it doesn’t work,” then we need to figure out the specific, fixable problem. When we find a bug, we need to understand not only how to fix it, but why the fix works so it minimizes the chances of breaking again.
In this unit, we will work through a systematic approach to debugging that will help you become faster and more confident. You will use AI-assisted debugging, not to write code blindly, but to help you understand what is happening and why. You will also learn to write tests to catch problems before your users do.
From Feedback to Action Plan
User feedback is valuable, but it often arrives in a messy form.
- “The app crashed” could mean the button did nothing, or the page froze, or an error appeared.
- “I couldn’t figure it out” could mean poor labels, missing instructions, or a confusing flow.
In Iterating and Refining Your MVP, you spent time testing your MVP with users and collecting their feedback. You then prioritized and categorized issues that were uncovered.
Throughout this unit, we will use the same example app from previous units, TutorMatch, a student-facing platform that helps students identify what type of tutor they need based on their learning struggles, built with React and Javascript. TutorMatch was built in Github Codespaces. You’ll work with YOUR OWN MVP AND FEEDBACK for this activity. TutorMatch examples are shown for reference only.
ACTIVITY 1
Build Your Feedback Triage System
Estimated Time: 20 Minutes
We will create a system to categorize user feedback and turn it into a prioritized action plan. This saves debugging time because we work on the most important problems first, not the ones we notice first or are biased to fix.
1. Open Github and Codespaces
Open your repository on Github and open your Codespace.
If you still have an open repository branch, use that branch and codespace.
Otherwise, create a new branch. Open the same codespace you used before, but you’ll need to switch branches, by typing these commands in the terminal window.
git pull origin main
git checkout new-branch-name
git checkout -b new-branch-name
2. Gather Feedback from User Testing
In your user testing, you prioritized issues and categorized them, using the Testing Analysis worksheet.
Find that information in your worksheet, as you will need that for this activity.
3. Ask Copilot to Help Organize Issues
Here we will document the issues and the action plan through an issue tracker.
- In your Codespace, create a new folder called test and a new file called issue_tracker.md . You can do this in the File Explorer panel (click the new file icon).
- Ask Github Copilot to provide a structured and categorized set of issues by feeding it your top P0/P1 issues from your testing. You can use this template:
I’m debugging my app based on user testing feedback. Help me create structured issue descriptions for each problem.
For each issue below, provide:
- **Summary:** One-sentence description
- **Category:** Bug, Usability, Missing Feature, or Enhancement
- **What the user experienced:** What they saw or didn’t see
- **Possible root causes:** 2-3 hypotheses for why this happened (numbered)
- **Where to look first:** Which file or section of code to investigate
- **Suggested fix approach:** A starting point (not the complete solution)
Here are my issues:
- Copy and paste your top P0/P1 issues at the bottom of the prompt. You can include what you have already in your table in the worksheet.
- Read what Copilot generates. For each issue, ask yourself:
- Do the possible root causes make sense for MY app?
- Is “where to look first” pointing to the right part of my code?
- If something seems off, tell Copilot. For example: “For Issue 1, my app uses React and the Groq API. The error happens when the user submits the form. Can you revise the root causes?”
- Once you’re satisfied, copy the refined descriptions into your issue_tracker.md file and save the file.
4. Stage and Commit Change to Github
Stage and commit your changes to your repository branch.
The "Teach Me" Pattern
When something breaks, we can be tempted to paste the error into AI and ask “fix this.” The AI will usually give you code that works (especially if you use Gemini 3 models or similar powerful LLMs). But you won’t understand why and how, which means that the next time a similar issue appears, you can get stuck again.
The “Teach Me” pattern can change this. Instead of asking AI for a fix, you ask it to explain the problem first. You add one instruction to your prompts:
Before giving me any code, explain what are potential causes of the issue and explain why each fix could work. It’s important to not update the code yet until we’ve decided on the best approach forward. My goal is to understand the problem, not just solve it.
This instruction transforms how AI responds. While generally Copilot is very good at showing its thought process and it highlights the code changes, asking explicilty for an explanation before updating the code is a great way to learn so you don’t repeat mistakes.
Without the “Teach Me” pattern
You: My app shows “No Response” when I click Get Recommendations. Fix it.
AI: Added 3 lines at line 61. The backend has been updated to check for Groq API errors in the response and return the error details (including error codes) to the frontend instead of defaulting to “No response.”
This is fast but you don’t get a full explanation of what is happening and the real problem.
With the “Teach Me” pattern
You: My app shows “No Response” when I click Get Recommendations. Before giving me any code, explain what’s causing this issue, identify possible causes, create a fix plan and explain why the proposed fix may work. I want to understand the problem, not just solve it.
AI: The key issue :
fetch does NOT throw on HTTP errors.
So this code:
const groqResponse = await fetch(groqUrl, { ... })
const groqData = await groqResponse.json()
will happily run even if Groq returns:
401 (bad API key)
429 (rate limit)
400 (bad model name)
In those cases, Groq returns an error JSON, not choices, so this line:
const text = groqData.choices?.[0]?.message?.content || 'No response.'
falls back to "No response."
App displays “Groq didn’t respond”, when in reality it did, but with an error.
The fix: Add an explicit status check immediately after fetch:
if (!groqResponse.ok) {const errorText = await groqResponse.text()
console.error('Groq API HTTP error:', groqResponse.status, errorText)
return res.status(500).json({error: 'Groq API request failed',
status: groqResponse.status,
details: errorText,})}
Then parse JSON only if it’s OK.
DevTools
Every browser has built-in Developer Tools that let you see what’s happening behind the scenes. You used DevTools briefly in the Founder’s Toolkit to view localStorage. Now you’ll use additional tabs:
- Console tab – Shows JavaScript errors and log messages your app produces. Red messages are errors. Yellow messages are warnings.
- Network tab – Shows every request your app makes to external services (like the Groq API). Reveals status codes and response data.
- Elements tab – Shows the HTML structure and CSS styles of your page. Useful for diagnosing layout and visual issues.
Together, they can show problems that users can’t see easily, and you can use them to give you the evidence you need to fix them.
In the next activity, you’ll fix your top issues using the process you’ve been building: start with your categorized list, form a hypothesis, use the “Teach Me” pattern to understand the root cause, then apply the fix.
ACTIVITY 2
The "Teach Me" Debugging Pattern
Estimated Time: 30 Minutes
1. Open your Codespace and Issue Tracker
- Open your Codespace from Activity 1.
- Locate the issue_tracker.md file with your P0 and P1 issues listed and open it.
- Start with your top P0 issue that has been categorized as a bug. If you don’t have a P0, start with your top P1, but it should be something identified as an error or bug.
2. Reproduce the Bug and Document What You See
- Run your app by typing npm run dev (if app is React/JS) in the terminal window.
- If the bug/issue involves any backend issue, like an API call, also start up your backend server. Type npm run dev from the server folder in another terminal window..
- Try to reproduce the issue by doing exactly what the tester or your notes said caused the problem.
- Write down precisely what happens:
- Does the page go blank?
- Does a button do nothing?
- Does an error message appear?
- If you see an error message in the app itself, or in either terminal window (app or server), copy the exact text. This detail makes the next steps much more productive.
3. Use DevTools to Gather Evidence
- In the app browser window, open DevTools (F12 or right-click -> Inspect).
- For any issue, start with Console:
- Click Console tab.
- Type clear to clear old messages.
- Reproduce the bug.
- Copy any red error messages.
- If it involves AI or data, check Network:
- Click Network tab.
- Reproduce the bug.
- Find your API request (look for your API’s domain).
- Check Status code and Response.
- If it involves AI or data, and you don’t see anything in the app window’s dev tools:
- Open DevTools in the browser window running your backend server.
- Click Console tab.
- Type clear to clear old messages.
- Reproduce the bug.
- Copy any red error messages.
4. Form a Hypothesis
Before asking AI for help, look at the possible root causes that Copilot suggested in Activity 1 and that you have in your issue tracker.
- Open your issue tracker.
- Under the issue you are currently recreating, look at the possible root cause for that issue.
- You can copy the possible root cause listed, or write down your own hypothesis, but write down something.
“I think this is happening because _______________”
Tip: Having a hypothesis, even a wrong one, can make the debugging process more productive. You’re not just saying “it’s broken.” You’re saying “I think it’s broken because of X, and I want to verify that.” This additional context is very helpful for LLMs and can help them narrow down the range of possibilities.
5. Ask Copilot For Help With the Teach Me Pattern
Ask Copilot, or another LLM, to help you debug . You can use this template and replace with your specific issues:
Before giving me any code and making the fix, explain what’s causing this issue and why the fix works. I want to understand the problem, not just solve it.
Issue:[Copy and paste the issue, including Summary, Category, Possible root causes, Where to look first, and Suggested Fix Approach]. Giving the LLM as much context as possible can help its response.
My hypothesis: [What you think is causing it]
Expected Results: [what I think should happen]
6. Read the Explanation Before Applying the Fix
- Read what Copilot says before applying any fix.
This is the key step. When Copilot responds, read the explanation first. Make sure you can understand and can answer these questions:- What is the root cause?
- Why does the suggested fixes address the cause?
- Could this same type of issue appear elsewhere in my app?
- Ask follow up questions if something in the explanation doesn’t make sense, like “Can you explain what this means in this context”?
7. Apply the Fix
Once you understand the problem and agree with the fix plan, you can now apply the fixes. You can either:
- Make the code changes manually based on Copilot’s explanation. This is a great opportunity for you to get more comfortable digging into the code yourself and taking your learning to the next step.
- Ask Copilot to make the changes: “Now apply the fix you described to my code”.
Copilot will then apply the fixes and update all the places in the code directly. If it asks you to review the changes, then read the proposal before accepting them. This is what it’s called: AI-assistant debugging with human in the loop.
8. Test the Fix
Test by running your app and try reproducing the original bug.
Does the issue still occur?
If so, repeat the steps and iterate.
In some cases, there may be multiple hypothetical causes of the issues with different proposed fixes. If that was the cause, you can simply go back and ask Copilot again to go to the next possible fix. You can share additional context about the bug to help Copilot refine the plan.
9. Update your Issue Tracker and Commit
- Once you’re done, ensure to document the issue-tracker.md. You can add this documentation under the issue you fixed .
For example::
- Issue 1: [issue description]
- Root cause: [What was actually wrong]
- What I changed in the code [Brief description of the fix]
- Tested: [Yes/No — did the fix resolve the issue?]
- Date: [Today]
- Commit this fix to GitHub with the right commit description like:
“Fix: [brief description of what you fixed]”
Good commit messages describe the fix, not the bug:
Good Examples:
- Fix: Handle empty API response in results display
- Fix: Add loading state to prevent double-submit
Bad Examples:
- Fixed bug
- Update code
10. Repeat for your Next Issue
Go back to Step 1 and pick your next highest-priority issue and follow the same process:
Hypothesis → “Teach Me” → Understand → Fix → Test → Commit
You can also address some of your non-bug issues, such as a usability issue or missing feature, as long as you’ve prioritized it as P0 or P1. You would approach it a little differently with your prompting, but you can still ask Copilot to assist you in those other issues.
Debugging UI vs API Issues Using DevTools
Some bugs need more than looking at the app to diagnose. Here are some examples:
- A button does nothing when clicked, but there’s no error message telling you why.
- The AI returns no response, but you can’t tell if the request failed or the response was empty.
- A section of the page is missing, but the HTML code and CSS looks correct.
In each case above, you can see the effect but not the cause. DevTools lets you see the cause. In this activity, you’ll use DevTools to gather evidence about an issue, then bring that evidence to Copilot for a more targeted fix.
In the video below, we will debug some issues in the TutorMatch app. The code has been modified to simulate these potential issues.
As shown in the video, here is the general process for fixing issues you find using DevTools.
Open GitHub Codespace and Dev Tools
- Go to GitHub and navigate to your MVP repo.
- Open a new branch (or use an existing dev branch). Open any existing codespace and make sure to switch to the correct branch.
- Run your app from within Codespaces.
- In the browser tab, right-click anywhere on the page and select “Inspect (or press F12) to open the Developer Tools Panel.
2. Hypothesize if This is a UI Issue or a Logic/API Issue
Before diving into tabs, ask yourself what type of problem you’re seeing. This will determine where to look first.
What You See
Type
Where to Look in DevTools Panel
Element is missing, misaligned, or overlapping
UI issue
Elements tab
Button does nothing or wrong data appears
Logic issue
Console tab
AI feature returns no response or errors
API issue
Network tab
Page layout looks broken after a fix
UI issue
Elements tab
“Cannot read property of undefined”
Logic issue
Console tab
3. For UI issues - Inspect with the Elements Tab
If your issue is visual like layout, spacing, missing elements, etc.
- Click the Elements tab in DevTools
- Use the element selector tool (the cursor icon in the top-left corner of DevTools, or press Ctrl+Shift+C / Cmd+Shift+C).
- Hover over the problem area on your page to highlight the HTML element and show its CSS styles
4. For logic and API Issues — Check Console and Network Tabs on Backend
If your issue is about data, behavior, or API calls, check your backend server browser window. Start with the Console tab.
- Click the Console tab.
- Clear old messages by clicking the clear button to start fresh.
- Now reproduce the bug in the app and start seeing new messages come in
- Watch for new messages: like:
- Red messages are errors that they often include a file name, line number, and description
- Yellow messages are warnings. These are worth noting but not always causing issues.
- Copy any error message if one appears.
- If no error appears in the Console, switch to the Network tab.
- Clear the existing entries and reproduce the bug again (note that the Network tab only records requests made while it’s open).
- Look for your API call. It usually shows as a POST:
- look for analyze or /api/analyze
- If the request failed, the status will appear in red.
- Even is the status is green (200), click on the request and response fields on the far right and check these details below
- Copy the status code, request and response bodies, and any error message. This is your evidence.
What to Check
Where to Find It
What it Means
Status Code
Status column, or Headers tab
The number tells you what type of error occurred
Request
Click Request tab (far right)
What your app sent—helps check if the input was wrong
Response
Click Response tab (far right)
The actual error message from the server, or the response itself, which may be formatted incorrectly.
Here are some common status codes:
Status Code
Meaning
Common Cause
200
Success
Everything worked (if results are still wrong, check what you sent and what the response was)
400
Bad Request
Your API key is missing, expired, or incorrect
401
Unauthorized
The actual error message from the server, or the response itself, which may be formatted incorrectly.
403
Forbidden
Your API key doesn’t have permission for this action
429
Too Many Requests
You’ve hit the rate limit—wait a minute and try again
500
Server Error
The API service has a problem on their end—try again later
5. Use your Evidence with Copilot
- Go back to Codespaces to bring your DevTools findings to Copilot. This evidence makes your debugging prompt much more specific
- Enter your evidence using this template:
Do no give me any code yet. Just explain what’s causing this issue and why the fix works. I want to understand the problem, not just solve it.
**Issue:** [What happened when the user triggered the feature]
**DevTools evidence:**
– Console error: [paste error message, or “no console error”]
– Network status code: [e.g., 401]
– Request: [paste what your app sent, if relevant]
– Response: [paste the error or content response from the API]
Because you’re providing evidence instead of a vague description, Copilot can give you a precise explanation and targeted fix.
6. Apply the Fix and Verify in DevTools
After Copilot explains the issue and you understand it, apply the fix in your Codespace. Then verify by running the app and recreating the steps that caused the issue. You should be able to verify in the app itself, but you can also verify using DevTools:
- For API fixes: Open the backend’s Network tab, trigger the same action that previously failed. Check:
- Is the request now returning 200 (success)?
- Does the Response tab show the expected data?
- For UI fixes: Use the Elements tab(frontend) to confirm the element is now visible and styled correctly.
- For logic fixes: Check the Console (frontend) for no new red errors that appear when you trigger the action.
7. Stage and Commit your Fix
Update your issue-tracker.md with what you found in DevTools and how you fixed it. Once done, stage the changes and commit the fix to your repo branch.
Verify and Document Testing
You have learned how to use DevTools to diagnose some tricky problems. In your own debugging and code updates to your MVP, you need to verify everything works together, document what you did, and merge your changes into your main branch.
Testing is how you confirm your fixes actually work and that they didn’t break something else. In this next activity, you will learn how to transform test plans so these can be used to test the app’s functionality in a more systematic manner. It will also help the AI understand what tests should pass and could even run them for you.
ACTIVITY 3
Test, Validate, and Document Your Fixes
Estimated Time: 25 Minutes
1. Open GitHub Codespace and Create your Test Checklist
Testing without a checklist means we forget cases or test inconsistently. Instead of manually typing the structure, we will use Copilot to generate a comprehensive test checklist based on your bug fixes and app features.
- Go to GitHub and navigate to your MVP repo.
- Navigate to your dev branch (or create a new branch) and open any existing codespace from the existing activity.
- Open your Codespace.
- Make sure to switch to the dev branch.
- Create a file called test-checklist.md in your Codespace test folder.
- Prompt Copilot with your evidence using this template:
Add content to the test_checklist.md file in the test folder for [your app name] with the following structure:
– Header with app name, last tested date, and tester name placeholders
– Core Functionality section covering these main features: [list your 2-3 main features]
– Edge Cases section with common scenarios: empty input, long input (100+ words), rapid clicks, mobile viewport testing
– Recent Bug Fixes section
For the Recent Bug Fixes section, review my recent commits on the current branch and create specific test cases for each fix. Each test should verify the bug is resolved and describe the expected behavior.
Make test cases specific and actionable – someone else should be able to run them without asking questions.
2. Review the Output of your Checklist
Review the generated checklist and ask yourself:
- Do the core functionality tests cover the main user journey from ENT 9? If not, add missing steps.
- Are there edge cases my users actually experience that aren’t listed? If so, add them manually.
- Do the bug fix tests match what I actually fixed?
- Are test cases specific enough?
If you find gaps, you can either fill them in yourself or ask Copilot to enhance specific sections and ensure they are added to the generated file.
3. Run Through your Checklist
Work through each row systematically:
- Perform the exact steps listed.
- Compare what happens to the expected result.
- Mark Pass or Fail.
- If anything fails, note what went wrong.
Tips for thorough testing:
- Test in a fresh incognito/private browser window to avoid cached data.
- Test the happy path first (everything works as expected).
- Then test edge cases (empty inputs, very long inputs, rapid clicks).
- Test on mobile viewport (DevTools → Device Mode, or test on your phone)
If a test fails:
- This is a regression issue – it means the fix broke something else.
- Go back to Activity 2 and apply the “Teach Me” pattern.
- Sometimes the first fix addresses a symptom rather than the root cause.
4. Commit Changes and Merge into Main
- Once you have run all tests and filled in the results, stage and commit changes to your branch.
- Go to Github, and merge your branch into the main branch.
Reflection
Responding to user testing issues and debugging your app is an ongoing process. Ask yourself these questions:
Debugging Process
"Teach Me"
DevTools Discovery
Evidence-based Debugging
Bug Patterns
Key Terms
- Bug: A defect in your app where it doesn’t behave as intended. Crashes, wrong results, and confusing behavior are all types of bugs.
- P0 / P1 / P2 / P3: Priority levels for issues. P0 is critical (blocks users), P1 is important (painful but workable), P2 is minor (low frequency), P3 is cosmetic (polish).
- MoSCoW Method: A prioritization framework that groups items into Must, Should, Could, and Won’t categories for a given iteration.
- Root Cause: The underlying reason a bug occurs—not just what the user sees, but why it happens in the code. Fixing root causes prevents recurrence.
- “Teach Me” Pattern: A debugging approach where you ask AI to explain the problem before providing a fix. Builds understanding instead of copy-paste solutions.
- DevTools: Browser Developer Tools (F12 or right-click → Inspect). Includes Console for errors, Network for API calls, and Elements for layout inspection.
- Console Tab: Shows JavaScript errors, warnings, and log messages. Red entries are errors with file names and line numbers pointing to the problem.
- Network Tab: Shows all HTTP requests your app makes, including API calls. Reveals status codes, request details, and response data.
- Elements Tab: Shows the HTML structure and CSS styles of your page. Useful for diagnosing layout and visual issues.
- Status Code: A number returned by a server indicating success (200), client error (400-499), or server error (500-599).
- Issue Tracker: A document that records bugs, their priority, root causes, and fixes. Keeps debugging organized and provides a history of changes.
- Regression: When fixing one issue accidentally breaks another feature that was previously working. Test checklists help catch regressions.
Additional Resources
- Chrome DevTools Documentation: Official guide to browser developer tools
- HTTP Status Codes: Reference for understanding API response codes
- GitHub Pull Requests: How to create and manage pull requests
- GitHub Copilot Guide: Power user tips for Copilot
