<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GitHub API on recca0120 Tech Notes</title><link>https://recca0120.github.io/en/tags/github-api/</link><description>Recent content in GitHub API on recca0120 Tech Notes</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 03 Apr 2026 02:57:00 +0800</lastBuildDate><atom:link href="https://recca0120.github.io/en/tags/github-api/index.xml" rel="self" type="application/rss+xml"/><item><title>I Built a Global Developer Ranking Site with Vibe Coding</title><link>https://recca0120.github.io/en/2026/04/03/codeatlas-vibe-coding-developer-ranking/</link><pubDate>Fri, 03 Apr 2026 02:57:00 +0800</pubDate><guid>https://recca0120.github.io/en/2026/04/03/codeatlas-vibe-coding-developer-ranking/</guid><description>&lt;img src="https://recca0120.github.io/" alt="Featured image of post I Built a Global Developer Ranking Site with Vibe Coding" /&gt;&lt;p&gt;GitHub has over 100 million developer accounts. But have you ever wondered — where do you rank in your own country?&lt;/p&gt;
&lt;p&gt;That thought led me to spend a few days vibe coding &lt;a class="link" href="https://recca0120.github.io/codeatlas/" target="_blank" rel="noopener"
 &gt;CodeAtlas&lt;/a&gt;, a global developer ranking platform covering 130+ countries, complete with a spinnable 3D globe.&lt;/p&gt;
&lt;h2 id="what-is-vibe-coding"&gt;&lt;a href="#what-is-vibe-coding" class="header-anchor"&gt;&lt;/a&gt;What Is Vibe Coding
&lt;/h2&gt;&lt;p&gt;Vibe coding is a concept coined by Andrej Karpathy in early 2025: describe your requirements in natural language, let AI generate the code, and focus on direction and review. The process feels more like directing a project than writing code line by line.&lt;/p&gt;
&lt;p&gt;CodeAtlas was born this way. I defined the data sources, ranking logic, and UI interactions, then let AI handle the implementation. The resulting tech stack exceeded my expectations — Astro 6 with Svelte 5 Islands, Three.js 3D globe, GitHub GraphQL API automation — the learning curve alone would have been substantial if I had to build everything from scratch.&lt;/p&gt;
&lt;h2 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h2&gt;&lt;p&gt;The project splits into two parts: a data collection pipeline and a frontend.&lt;/p&gt;
&lt;h3 id="data-collection"&gt;&lt;a href="#data-collection" class="header-anchor"&gt;&lt;/a&gt;Data Collection
&lt;/h3&gt;&lt;p&gt;The data source is the GitHub GraphQL API. Each country has configured location keywords — for example, Taiwan maps to &lt;code&gt;[&amp;quot;Taiwan&amp;quot;, &amp;quot;Taipei&amp;quot;, &amp;quot;Kaohsiung&amp;quot;, &amp;quot;Taichung&amp;quot;]&lt;/code&gt;. The collection script searches GitHub users by these keywords, paginating by follower count descending.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Search query: location-based with followers sorting
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// query: &amp;#34;location:Taiwan sort:followers-desc&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;octokit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;searchQuery&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`location:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; sort:followers-desc`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;first&lt;/span&gt;: &lt;span class="kt"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;after&lt;/span&gt;: &lt;span class="kt"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For each developer, the system collects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Public and private contribution counts&lt;/li&gt;
&lt;li&gt;Follower count&lt;/li&gt;
&lt;li&gt;Top 5 programming languages&lt;/li&gt;
&lt;li&gt;Top 5 repositories by stars&lt;/li&gt;
&lt;li&gt;Profile info (company, bio, Twitter, blog)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few things worth noting about the collection process. GitHub API has rate limits, so &lt;code&gt;@octokit/plugin-throttling&lt;/code&gt; controls request frequency with 500-1000ms delays between pages. Secondary rate limits trigger automatic retries up to 3 times. A full collection across 130+ countries takes about two hours.&lt;/p&gt;
&lt;h3 id="ambiguous-location-filtering"&gt;&lt;a href="#ambiguous-location-filtering" class="header-anchor"&gt;&lt;/a&gt;Ambiguous Location Filtering
&lt;/h3&gt;&lt;p&gt;GitHub&amp;rsquo;s location field is free-form text, which creates false positives. The classic example is Georgia — both a US state and a country. &lt;code&gt;location-filter.ts&lt;/code&gt; uses exclusion rules to handle cases like these, preventing developers from Georgia, USA from being counted under the Republic of Georgia.&lt;/p&gt;
&lt;h3 id="automated-scheduling"&gt;&lt;a href="#automated-scheduling" class="header-anchor"&gt;&lt;/a&gt;Automated Scheduling
&lt;/h3&gt;&lt;p&gt;Data collection runs daily via GitHub Actions. A checkpoint system processes a subset of countries per run, allowing interrupted runs to resume. Completed data auto-commits to the repo, and GitHub Pages updates accordingly.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# .github/workflows/collect-data.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;17 3 * * *&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Daily at UTC 3:17&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Manual trigger available&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="ranking-system"&gt;&lt;a href="#ranking-system" class="header-anchor"&gt;&lt;/a&gt;Ranking System
&lt;/h2&gt;&lt;p&gt;The ranking logic is intentionally simple. Three dimensions, each sorted independently:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Dimension&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Public Contributions&lt;/td&gt;
 &lt;td&gt;Public contributions only&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Total Contributions&lt;/td&gt;
 &lt;td&gt;Public + private contributions&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Followers&lt;/td&gt;
 &lt;td&gt;GitHub follower count&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;rankUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;: &lt;span class="kt"&gt;GitHubUser&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;dimension&lt;/span&gt;: &lt;span class="kt"&gt;RankingDimension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getRankValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dimension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;getRankValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dimension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;No weighting, no composite scores. Users can switch dimensions on the page and decide which metric matters to them. Anyone who has built a ranking system knows that weighting invites endless debates — better to give users the choice.&lt;/p&gt;
&lt;h2 id="frontend"&gt;&lt;a href="#frontend" class="header-anchor"&gt;&lt;/a&gt;Frontend
&lt;/h2&gt;&lt;h3 id="3d-interactive-globe"&gt;&lt;a href="#3d-interactive-globe" class="header-anchor"&gt;&lt;/a&gt;3D Interactive Globe
&lt;/h3&gt;&lt;p&gt;The homepage centerpiece is a rotatable, zoomable 3D globe built with &lt;a class="link" href="https://globe.gl/" target="_blank" rel="noopener"
 &gt;Globe.gl&lt;/a&gt; and Three.js. Countries with data are highlighted on the globe — click one to jump straight to its rankings.&lt;/p&gt;
&lt;p&gt;The globe works on mobile too, with responsive handling that adjusts canvas size and interaction behavior on smaller screens to avoid performance issues.&lt;/p&gt;
&lt;h3 id="astro-islands-architecture"&gt;&lt;a href="#astro-islands-architecture" class="header-anchor"&gt;&lt;/a&gt;Astro Islands Architecture
&lt;/h3&gt;&lt;p&gt;The frontend uses Astro 6 with Svelte 5 for interactive components. Astro&amp;rsquo;s Islands architecture fits this &amp;ldquo;mostly static with some interaction&amp;rdquo; pattern well. Page HTML is generated at build time as static files — only components that need interactivity (globe, filters, search) hydrate on the client.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;src/components/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── AppRouter.svelte # Client-side SPA routing
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── HomePage.svelte # Homepage + 3D globe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── CountryPage.svelte # Country rankings
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── ProfilePage.svelte # Developer profile pages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── RankingFilter.svelte # Dimension toggle + search + language filter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── CountrySearch.svelte # Country search
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="filtering-and-search"&gt;&lt;a href="#filtering-and-search" class="header-anchor"&gt;&lt;/a&gt;Filtering and Search
&lt;/h3&gt;&lt;p&gt;The country ranking page supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search developers by name&lt;/li&gt;
&lt;li&gt;Filter by programming language (12 most common listed)&lt;/li&gt;
&lt;li&gt;Filter by city/region&lt;/li&gt;
&lt;li&gt;Switch between three ranking dimensions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All filter states sync to URL query strings, so shared links preserve the exact view.&lt;/p&gt;
&lt;h3 id="developer-profiles"&gt;&lt;a href="#developer-profiles" class="header-anchor"&gt;&lt;/a&gt;Developer Profiles
&lt;/h3&gt;&lt;p&gt;Clicking any developer opens their profile page showing rank, contribution stats, programming languages (with colored badges), top repos by stars, and links to GitHub, Twitter, and personal websites.&lt;/p&gt;
&lt;h2 id="internationalization-and-dark-mode"&gt;&lt;a href="#internationalization-and-dark-mode" class="header-anchor"&gt;&lt;/a&gt;Internationalization and Dark Mode
&lt;/h2&gt;&lt;p&gt;The site supports English and Traditional Chinese. Translation files are managed in TypeScript with type checking. Language preference is stored in localStorage and auto-redirects on return visits.&lt;/p&gt;
&lt;p&gt;Dark mode follows system preferences by default, with a manual toggle available. State is also persisted in localStorage.&lt;/p&gt;
&lt;h2 id="automatic-og-image-generation"&gt;&lt;a href="#automatic-og-image-generation" class="header-anchor"&gt;&lt;/a&gt;Automatic OG Image Generation
&lt;/h2&gt;&lt;p&gt;Social sharing requires Open Graph images. &lt;a class="link" href="https://github.com/vercel/satori" target="_blank" rel="noopener"
 &gt;Satori&lt;/a&gt; converts HTML templates to SVG then PNG at build time — each country page and developer profile gets an auto-generated OG image.&lt;/p&gt;
&lt;h2 id="the-vibe-coding-experience"&gt;&lt;a href="#the-vibe-coding-experience" class="header-anchor"&gt;&lt;/a&gt;The Vibe Coding Experience
&lt;/h2&gt;&lt;p&gt;Looking back at this project, vibe coding&amp;rsquo;s biggest advantage is lowering the cost of experimentation. A 3D globe sounds cool but I&amp;rsquo;m not familiar with Three.js — no problem, let AI generate a first pass, then iterate. GraphQL queries need cursor pagination and rate limiting — let AI write the initial version, I&amp;rsquo;ll review and add edge cases.&lt;/p&gt;
&lt;p&gt;A few observations from the experience:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Speed is real.&lt;/strong&gt; From idea to working first version took about two days. Manually writing Three.js globe integration plus GitHub API handling would have taken longer just for documentation research.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quality is still your job.&lt;/strong&gt; AI-generated code that runs doesn&amp;rsquo;t mean it&amp;rsquo;s well-written. Code review is essential, especially for error handling and edge cases. GitHub API secondary rate limits, ambiguous location filtering — these were all added during review.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Architecture decisions are yours.&lt;/strong&gt; AI won&amp;rsquo;t proactively suggest whether a feature should be static or use Islands architecture. Technical choices and architectural decisions remain the developer&amp;rsquo;s responsibility.&lt;/p&gt;
&lt;h2 id="tech-stack-overview"&gt;&lt;a href="#tech-stack-overview" class="header-anchor"&gt;&lt;/a&gt;Tech Stack Overview
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Category&lt;/th&gt;
 &lt;th&gt;Technology&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Framework&lt;/td&gt;
 &lt;td&gt;Astro 6 (SSG) + Svelte 5&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3D&lt;/td&gt;
 &lt;td&gt;Globe.gl + Three.js&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Styling&lt;/td&gt;
 &lt;td&gt;Tailwind CSS v4&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Data&lt;/td&gt;
 &lt;td&gt;GitHub GraphQL API + Octokit&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Validation&lt;/td&gt;
 &lt;td&gt;Zod v4&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Testing&lt;/td&gt;
 &lt;td&gt;Vitest + Testing Library + Playwright&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Images&lt;/td&gt;
 &lt;td&gt;Satori + Resvg-js&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CI/CD&lt;/td&gt;
 &lt;td&gt;GitHub Actions + GitHub Pages&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Language&lt;/td&gt;
 &lt;td&gt;TypeScript 5.9, Node.js 22+&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://recca0120.github.io/codeatlas/" target="_blank" rel="noopener"
 &gt;CodeAtlas Live Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.astro.build/" target="_blank" rel="noopener"
 &gt;Astro Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://globe.gl/" target="_blank" rel="noopener"
 &gt;Globe.gl — WebGL Globe Data Visualization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/vercel/satori" target="_blank" rel="noopener"
 &gt;Satori — Enlightened library to convert HTML and CSS to SVG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.github.com/en/graphql" target="_blank" rel="noopener"
 &gt;GitHub GraphQL API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://svelte.dev/docs" target="_blank" rel="noopener"
 &gt;Svelte 5 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>