Skip to content

Commit 7c67ef6

Browse files
committed
feat: implement 5 upgrades to GitHub API Handbook\n\nAdd curl examples, workflows, pagination, error docs, and API vs scraping.
1 parent bbff395 commit 7c67ef6

2 files changed

Lines changed: 233 additions & 1 deletion

File tree

components/content.tsx

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const contentMap: Record<
1313
breadcrumb: string[]
1414
description: string
1515
syntax?: string
16+
curl?: string
1617
parameters?: Array<{
1718
name: string
1819
type: string
@@ -106,6 +107,7 @@ const contentMap: Record<
106107
'Retrieves public profile information for a GitHub user.',
107108
syntax:
108109
'GET https://api.github.com/users/{username}\nHeaders:\nAuthorization: Bearer YOUR_GITHUB_TOKEN',
110+
curl: 'curl -H "Authorization: Bearer YOUR_GITHUB_TOKEN" \\\n https://api.github.com/users/octocat',
109111
parameters: [
110112
{ name: 'username', type: 'string', desc: 'GitHub username (required)' },
111113
],
@@ -222,6 +224,7 @@ const contentMap: Record<
222224
'Retrieves all public repositories of a user.',
223225
syntax:
224226
'GET https://api.github.com/users/{username}/repos\nQuery Parameters: sort, order, per_page, page',
227+
curl: 'curl -H "Authorization: Bearer YOUR_GITHUB_TOKEN" \\\n "https://api.github.com/users/octocat/repos?sort=updated&per_page=10"',
225228
parameters: [
226229
{ name: 'username', type: 'string', desc: 'GitHub username' },
227230
{ name: 'sort', type: 'string', desc: 'created, updated, pushed, full_name' },
@@ -278,6 +281,7 @@ const contentMap: Record<
278281
'Retrieves commit history for a repository.',
279282
syntax:
280283
'GET https://api.github.com/repos/{owner}/{repo}/commits\nQuery Parameters: sha, path, author, since, until, per_page',
284+
curl: 'curl -H "Authorization: Bearer YOUR_GITHUB_TOKEN" \\\n "https://api.github.com/repos/torvalds/linux/commits?per_page=5"',
281285
parameters: [
282286
{ name: 'owner', type: 'string', desc: 'Repository owner username' },
283287
{ name: 'repo', type: 'string', desc: 'Repository name' },
@@ -344,6 +348,7 @@ const contentMap: Record<
344348
'Retrieves all issues in a repository.',
345349
syntax:
346350
'GET https://api.github.com/repos/{owner}/{repo}/issues\nQuery Parameters: state, labels, sort, direction, per_page',
351+
curl: 'curl -H "Authorization: Bearer YOUR_GITHUB_TOKEN" \\\n "https://api.github.com/repos/facebook/react/issues?state=open&per_page=5"',
347352
parameters: [
348353
{ name: 'owner', type: 'string', desc: 'Repository owner username' },
349354
{ name: 'repo', type: 'string', desc: 'Repository name' },
@@ -460,6 +465,204 @@ const contentMap: Record<
460465
'Track developer interest',
461466
],
462467
},
468+
pagination: {
469+
title: 'Pagination',
470+
subtitle: 'Handling paginated API responses',
471+
breadcrumb: ['Home', 'Getting Started', 'Pagination'],
472+
description:
473+
'Most GitHub API endpoints that return lists are paginated. By default, the API returns 30 items per page. You can request up to 100 items per page, and navigate through results using query parameters.',
474+
sections: [
475+
{
476+
heading: 'Basic Pagination',
477+
content:
478+
'Add per_page and page query parameters:\n\n?per_page=50&page=2\n\n• per_page: Number of results per page (1-100, default: 30)\n• page: Page number (starts at 1)',
479+
},
480+
{
481+
heading: 'Example: List Repos with Pagination',
482+
content:
483+
'Get the first 50 repos:\nhttps://api.github.com/users/octocat/repos?per_page=50&page=1\n\nGet the next 50 repos:\nhttps://api.github.com/users/octocat/repos?per_page=50&page=2',
484+
},
485+
{
486+
heading: 'Link Headers',
487+
content:
488+
'GitHub includes Link headers in responses with URLs for first, last, next, and previous pages.\n\nExample header:\nLink: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next", <https://api.github.com/user/repos?page=50&per_page=100>; rel="last"',
489+
},
490+
{
491+
heading: 'Best Practices',
492+
content:
493+
'• Always check the Link header for pagination info\n• Use per_page=100 for most queries\n• Cache results when possible to avoid repeated requests\n• Implement backoff if you hit rate limits\n• Avoid over-paginating through thousands of results',
494+
},
495+
],
496+
},
497+
'api-vs-scraping': {
498+
title: 'API vs Web Scraping',
499+
subtitle: 'Why use the GitHub API instead of scraping',
500+
breadcrumb: ['Home', 'Getting Started', 'API vs Web Scraping'],
501+
description:
502+
'While it\'s technically possible to scrape GitHub\'s website with tools like BeautifulSoup or Selenium, using the official API is always the better choice for developers.',
503+
sections: [
504+
{
505+
heading: 'Why Use the API',
506+
content:
507+
'✓ Structured Data: JSON format is easy to parse\n✓ Reliable: Consistent endpoint behavior\n✓ Legal: Official and authorized method\n✓ Performant: Optimized for high throughput\n✓ Rate Limits: Fair usage through authentication\n✓ Real-time: Webhooks available for live updates\n✓ Complete: Access to all GitHub data\n✓ Future-proof: Won\'t break when UI changes',
508+
},
509+
{
510+
heading: 'Why Web Scraping is Bad',
511+
content:
512+
'✗ Fragile: Breaks whenever GitHub changes HTML\n✗ Slow: Must load entire webpage and parse\n✗ Blocked: GitHub blocks automated scrapers\n✗ Terms: Violates GitHub\'s Terms of Service\n✗ Limited: Only public page content available\n✗ Wasteful: Consumes unnecessary bandwidth\n✗ Detection: Can get your IP banned\n✗ Maintenance: High ongoing development cost',
513+
},
514+
{
515+
heading: 'Real Example',
516+
content:
517+
'Scraping: Load HTML page → Find div classes → Extract text → Repeat for pagination\nAPI: Single JSON request → Parse structured data → Done\n\nAPI is faster and more reliable.',
518+
},
519+
],
520+
},
521+
'workflow-profile-dashboard': {
522+
title: 'Build a GitHub Profile Dashboard',
523+
subtitle: 'Complete workflow example',
524+
breadcrumb: ['Home', 'Common Workflows', 'Build Profile Dashboard'],
525+
description:
526+
'Learn how to build a complete GitHub profile dashboard by combining multiple API endpoints.',
527+
sections: [
528+
{
529+
heading: 'Step 1: Get User Profile',
530+
content:
531+
'GET https://api.github.com/users/{username}\n\nReturns: Name, bio, avatar, followers, following, public repos count',
532+
},
533+
{
534+
heading: 'Step 2: List Repositories',
535+
content:
536+
'GET https://api.github.com/users/{username}/repos?per_page=10&sort=stars\n\nReturns: Recent and starred repos with star counts',
537+
},
538+
{
539+
heading: 'Step 3: Get Contributor Stats',
540+
content:
541+
'GET https://api.github.com/repos/{owner}/{repo}/stats/contributors\n\nReturns: Contribution history for each repo',
542+
},
543+
{
544+
heading: 'Step 4: Combine and Display',
545+
content:
546+
'Now you have all the data to create a dashboard showing:\n• User profile card with avatar\n• Top repositories with star counts\n• Contribution statistics\n• Activity timeline\n• Follower/following counts\n\nCache this data since contributors endpoint is slow on first request.',
547+
},
548+
],
549+
},
550+
'workflow-track-growth': {
551+
title: 'Track Repo Growth',
552+
subtitle: 'Monitor repository metrics over time',
553+
breadcrumb: ['Home', 'Common Workflows', 'Track Repo Growth'],
554+
description:
555+
'Build a system to track how your repository grows by monitoring stars, forks, and issues over time.',
556+
sections: [
557+
{
558+
heading: 'Step 1: Fetch Current Stats',
559+
content:
560+
'GET https://api.github.com/repos/{owner}/{repo}\n\nExtract:\n• stargazers_count\n• forks_count\n• watchers_count\n• open_issues_count',
561+
},
562+
{
563+
heading: 'Step 2: Store Historical Data',
564+
content:
565+
'Save the current stats to your database with a timestamp:\n\n{\n "date": "2024-01-15",\n "stars": 1250,\n "forks": 340,\n "issues": 45\n}',
566+
},
567+
{
568+
heading: 'Step 3: Schedule Daily Updates',
569+
content:
570+
'Use a cron job or GitHub Actions to run this check daily.\n\nExample GitHub Actions:\n\n- cron: "0 0 * * *"\n\nThis runs at midnight every day.',
571+
},
572+
{
573+
heading: 'Step 4: Visualize Growth',
574+
content:
575+
'Plot the data over time:\n• Line chart: Stars trending up/down\n• Bar chart: Monthly growth\n• Metrics: Growth rate percentage\n\nThis shows if your project is gaining or losing momentum.',
576+
},
577+
],
578+
},
579+
'workflow-analyze-contributions': {
580+
title: 'Analyze Contributions',
581+
subtitle: 'Understand developer contribution patterns',
582+
breadcrumb: ['Home', 'Common Workflows', 'Analyze Contributions'],
583+
description:
584+
'Discover which developers are most active, what they\'re working on, and how to recognize contributions.',
585+
sections: [
586+
{
587+
heading: 'Step 1: Get Contributor Statistics',
588+
content:
589+
'GET https://api.github.com/repos/{owner}/{repo}/stats/contributors\n\nReturns an array of contributors with commit counts per week',
590+
},
591+
{
592+
heading: 'Step 2: Identify Top Contributors',
593+
content:
594+
'Sort by total contributions:\n\nconst topContributors = stats\n .sort((a, b) => b.total - a.total)\n .slice(0, 10)',
595+
},
596+
{
597+
heading: 'Step 3: Get Individual Commit History',
598+
content:
599+
'For each top contributor:\n\nGET https://api.github.com/repos/{owner}/{repo}/commits?author={username}\n\nThis shows their specific commits and impact',
600+
},
601+
{
602+
heading: 'Step 4: Create Contributor Recognition',
603+
content:
604+
'Build a "Contributors" page showing:\n• Top 10 all-time contributors\n• Recent active contributors\n• Contribution count\n• Links to their profiles\n• Lines added/removed\n\nThis recognizes valuable community members.',
605+
},
606+
],
607+
},
608+
'common-errors': {
609+
title: 'Common Errors',
610+
subtitle: 'Debug and fix API errors',
611+
breadcrumb: ['Home', 'Errors & Debugging', 'Common Errors'],
612+
description:
613+
'Understanding common GitHub API errors and how to fix them.',
614+
sections: [
615+
{
616+
heading: '401 Unauthorized',
617+
content:
618+
'Problem: Invalid or missing authentication token\n\nSolutions:\n• Check your token is correct\n• Verify token hasn\'t expired\n• Generate a new token if needed\n• Make sure you\'re sending Authorization header',
619+
},
620+
{
621+
heading: '403 Forbidden',
622+
content:
623+
'Problem: Usually rate limit exceeded\n\nSolutions:\n• Check X-RateLimit-Remaining header\n• Wait for reset time (X-RateLimit-Reset)\n• Use personal access token (higher limits)\n• Implement caching to reduce requests\n• Use GitHub Apps for even higher limits',
624+
},
625+
{
626+
heading: '404 Not Found',
627+
content:
628+
'Problem: Repository, user, or endpoint doesn\'t exist\n\nSolutions:\n• Verify username spelling\n• Check repository name\n• Ensure the repo is public (or you have access)\n• Confirm the endpoint path is correct',
629+
},
630+
{
631+
heading: '422 Unprocessable Entity',
632+
content:
633+
'Problem: Invalid parameters\n\nSolutions:\n• Check query parameter names\n• Verify parameter types (string vs number)\n• Ensure per_page is between 1-100\n• Review required vs optional parameters',
634+
},
635+
],
636+
},
637+
'status-codes': {
638+
title: 'Status Codes',
639+
subtitle: 'Understanding HTTP status codes',
640+
breadcrumb: ['Home', 'Errors & Debugging', 'Status Codes'],
641+
description:
642+
'GitHub API uses standard HTTP status codes to indicate request success or failure.',
643+
sections: [
644+
{
645+
heading: '2xx Success',
646+
content:
647+
'200 OK: Request succeeded, data returned\n201 Created: Resource successfully created\n204 No Content: Request succeeded, no data to return',
648+
},
649+
{
650+
heading: '3xx Redirection',
651+
content:
652+
'301 Moved Permanently: Resource moved to new location\n304 Not Modified: Resource hasn\'t changed since last request\n307 Temporary Redirect: Request redirected temporarily',
653+
},
654+
{
655+
heading: '4xx Client Error',
656+
content:
657+
'400 Bad Request: Invalid request format\n401 Unauthorized: Authentication required\n403 Forbidden: No permission/rate limited\n404 Not Found: Resource doesn\'t exist\n422 Unprocessable Entity: Invalid parameters',
658+
},
659+
{
660+
heading: '5xx Server Error',
661+
content:
662+
'500 Internal Server Error: GitHub server error\n502 Bad Gateway: GitHub service temporarily down\n503 Service Unavailable: GitHub maintenance/overload\n\nFor 5xx errors, retry after a delay.',
663+
},
664+
],
665+
},
463666
}
464667

465668
export function Content({ pageId }: ContentProps) {
@@ -470,6 +673,7 @@ export function Content({ pageId }: ContentProps) {
470673
breadcrumb,
471674
description,
472675
syntax,
676+
curl,
473677
parameters,
474678
response,
475679
useCases,
@@ -528,6 +732,18 @@ export function Content({ pageId }: ContentProps) {
528732
</section>
529733
)}
530734

735+
{/* cURL Example */}
736+
{curl && (
737+
<section className="mb-10">
738+
<h2 className="text-lg font-semibold text-slate-100 mb-3">cURL Example</h2>
739+
<pre className="bg-slate-900 border border-slate-800 rounded-lg p-4 overflow-x-auto">
740+
<code className="text-green-400 font-mono text-sm whitespace-pre-wrap">
741+
{curl}
742+
</code>
743+
</pre>
744+
</section>
745+
)}
746+
531747
{/* Parameters */}
532748
{parameters && parameters.length > 0 && (
533749
<section className="mb-10">

components/sidebar.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ const sections: SidebarSection[] = [
2020
{ id: 'intro', label: 'Introduction' },
2121
{ id: 'auth', label: 'Authentication' },
2222
{ id: 'rate-limits', label: 'Rate Limits' },
23+
{ id: 'pagination', label: 'Pagination' },
24+
{ id: 'api-vs-scraping', label: 'API vs Web Scraping' },
2325
],
2426
},
2527
{
@@ -66,7 +68,21 @@ const sections: SidebarSection[] = [
6668
items: [
6769
{ id: 'repo-views', label: 'Repo Views' },
6870
{ id: 'repo-clones', label: 'Repo Clones' },
69-
{ id: 'traffic-sources', label: 'Traffic Sources' },
71+
],
72+
},
73+
{
74+
title: 'Common Workflows',
75+
items: [
76+
{ id: 'workflow-profile-dashboard', label: 'Build Profile Dashboard' },
77+
{ id: 'workflow-track-growth', label: 'Track Repo Growth' },
78+
{ id: 'workflow-analyze-contributions', label: 'Analyze Contributions' },
79+
],
80+
},
81+
{
82+
title: 'Errors & Debugging',
83+
items: [
84+
{ id: 'common-errors', label: 'Common Errors' },
85+
{ id: 'status-codes', label: 'Status Codes' },
7086
],
7187
},
7288
]

0 commit comments

Comments
 (0)