JavaScript Notes
Learn to build a GitHub profile search app in JavaScript using the GitHub REST API, fetch, async/await, error handling, and dynamic profile card rendering.
What You'll Learn
- How to use the
fetchAPI with async/await - How to handle API errors gracefully (404, rate limit, network failure)
- How to render a profile card from JSON response data
- How to show/hide loading spinners during async operations
- How to implement a debounced search to avoid excessive API calls
Project Overview
This app takes a GitHub username, calls the public GitHub REST API, and displays the user's avatar, bio, stats (repos, followers, following), and a list of recent public repositories.
Component Structure
How It Works — Flow Diagram
Step-by-Step Build
Step 1 — HTML Structure
<div class="github-search-app">
<div class="search-bar">
<input type="text" id="searchInput" placeholder="Enter GitHub username..." autocomplete="off">
<button id="searchBtn" class="btn-search">🔍 Search</button>
</div>
<div id="loader" class="loader hidden">Loading...</div>
<div id="errorMsg" class="error hidden"></div>
<div id="profileCard" class="profile-card hidden">
<img id="avatar" src="" alt="avatar" class="avatar">
<div class="profile-info">
<h2 id="profileName"></h2>
<p id="profileLogin" class="login"></p>
<p id="profileBio" class="bio"></p>
<p id="profileMeta" class="meta"></p>
<div class="stats">
<span id="repoCount"></span>
<span id="followers"></span>
<span id="following"></span>
</div>
<a id="profileLink" href="#" target="_blank" class="btn-github">View on GitHub</a>
</div>
</div>
<div id="repoSection" class="repo-section hidden">
<h3>Recent Repositories</h3>
<ul id="repoList"></ul>
</div>
</div>Step 2 — Fetch User Data
const BASE_URL = "https://api.github.com";
async function fetchUser(username) {
const res = await fetch(`${BASE_URL}/users/${username}`);
if (!res.ok) {
if (res.status === 404) throw new Error("User not found");
if (res.status === 403) throw new Error("API rate limit exceeded — try again later");
throw new Error(`GitHub API error: ${res.status}`);
}
return res.json();
}
async function fetchRepos(username) {
const res = await fetch(`${BASE_URL}/users/${username}/repos?sort=stars&per_page=6`);
if (!res.ok) return [];
return res.json();
}Step 3 — Render Profile Card
Step 4 — Render Repository List
Step 5 — Main Search Function
Step 6 — UI Helper Functions
function showLoading(on) {
document.getElementById("loader").classList.toggle("hidden", !on);
}
function showError(msg) {
const el = document.getElementById("errorMsg");
el.textContent = msg;
el.classList.remove("hidden");
}
function hideError() { document.getElementById("errorMsg").classList.add("hidden"); }
function hideProfile() {
document.getElementById("profileCard").classList.add("hidden");
document.getElementById("repoSection").classList.add("hidden");
}Step 7 — Wire Events
Console Output
// Searching "torvalds"
fetchUser("torvalds")
→ GET https://api.github.com/users/torvalds → 200 OK
→ { login: "torvalds", name: "Linus Torvalds", public_repos: 8, followers: 240000, ... }
fetchRepos("torvalds")
→ GET https://api.github.com/users/torvalds/repos?sort=stars&per_page=6 → 200 OK
→ [{ name: "linux", stargazers_count: 230000, language: "C", ... }, ...]
renderProfile() → profile card visible
renderRepos() → 6 repo items rendered
// Searching "zzzdoesnotexistzzz"
fetchUser("zzzdoesnotexistzzz")
→ GET ... → 404 Not Found
→ Error thrown: "User not found"
showError("User not found") → red error message shownEdge Cases to Handle
| Situation | Expected Behavior |
|---|---|
| Empty input | Don't trigger fetch |
| 404 Not Found | "User not found" error message |
| 403 Rate Limit | "API rate limit exceeded" message |
| No bio/location | Skip displaying empty fields |
| No public repos | Show "No repositories found" |
Challenge Yourself
- Recent activity — fetch and show the user's last 5 events from
/users/{user}/events - Follower list — show a grid of follower avatars that link to their profiles
- Compare profiles — let users input two usernames and compare stats side-by-side
- Search history — store the last 5 searched users in
localStorage - Language breakdown — build a bar chart of languages used across all repos
Best Practices
- Always check
response.okbefore parsing JSON — don't assume success - Use
Promise.all()to fetch user and repos in parallel, not sequentially - Show a loading spinner while fetching to prevent perceived freezing
- Use
try/catch/finally— thefinallyblock always hides the loader - Rate limit is 60 req/hour unauthenticated — use GitHub tokens in production
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Build a GitHub Profile Search App in JavaScript - Step by Step Tutorial.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, mini, projects, github
Related JavaScript Master Course Topics