はじめに
この記事では Claude Code を利用してアプリを開発する過程を共有します。
TL;DR GitHub の任意リポジトリを入力すると、スターを付けたユーザの所在地を世界地図にプロットする Web アプリを作りました。
デモ : https://geostarmap.pages.dev/
なぜ作ったか
OSS を開発していると「どの国の開発者に届いているのか」が気になってきます。しかし既存のソフトウェアは、Pythonでローカルで動かす必要があったり、メンテされておらず動かないなどの問題がありました。
そこで「Claude Code に作らせたら、一瞬でできるのでは?」という実験を兼ねて、自分で最小構成のアプリを構築することにしました。
短時間で作った実験アプリなので品質は重視しておりません。あらかじめご容赦いただけますと幸いです。
設計方針
-
フロントエンドで完結
バックエンドを置かず、ビルド済みの静的アセットだけで完結させる。 -
セキュリティ情報を持たない
GitHub Personal Access Token はフロントエンドで利用するのみで、どこにも送信しない。 -
レートリミットを順守
- GitHub API : 5,000 req/h(PAT 利用)
- Nominatim : 1 req/s
-
地理情報のローカルキャッシュ
- 主要都市の位置情報データをパッケージングすることでGeocodingリクエストの回数を減らす。
-
最小限の構成
軽量な Vite + React + shadcn/ui を選定。
Git ガイドラインの作成
Claude.md に指示を書くことで、Claude Code に守ってほしい開発ルールを自動的に読み込ませることができます。個人的に Git の使い方に関して指示しておきたいことを書いておきます。書いておいても必ず守ってくれるとは限らないですが。
Claude.md
- **NEVER EVER use `git add -A` or `git add .`** - ALWAYS stage specific files only
- Follow conventional commit format (fix:, feat:, docs:, etc.)
- Keep commit messages to one line unless body is absolutely necessary
- For commits fixing bugs or adding features based on user reports add:
`git commit --trailer "Reported-by:" `
Where `name>` is the name of the user
- For commits related to a Github issue, add:
`git commit --trailer "Github-Issue:#" `
- **NEVER mention co-authored-by or similar**
- **NEVER mention the tool used to create the commit message**
- **NEVER ever include *Generated with* or similar in commit messages**
- **NEVER ever include *Co-Authored-By* or similar in commit messages**
Claude Code へのプロンプトと反復
まずは作成したい成果物を明確化にする必要があります。要求事項をもとに、Claude に仕様書を作ってもらいます。仕様の肉付けは 3 往復程度 で完了しました。
Claude が作った仕様書 Markdown を Claude.md に追加。そのままコミットし、以降のタスク分割や修正指示もすべて Claude Code から行いました。これにより、コードを読む必要はまったくありませんでした。
プロンプト
> i want to create a dead simple website that displays GitHub star gazers location geography map for any give github public repository. first let's discuss the detailed specification of the project thoroughly. Requirements for this application are as follows:
project name: GeoStarMap
usecases:
- user can input github repository url
- user can see the github user's location on the map
- user can input GitHub API token
- no authentication is required
requirements:
- Create as SPA without backend
- Use pnpm
- Use Vite
- Use React and shadcn library
- Use TypeScript
- Use ESLint
- Use minimum dependencies
- Use open street map API for geo coding with rate limiting of 1 req/sec
- Do not save user's API token
- Minimulism design
- Responsive for mobile device
- Format files with prettier
- No need for writing tests for this project
- Display progress on processing users
- Cache geolocation data
ultrathink
Claude が作成した仕様書 (参考)
# GeoStarMap - GitHub Stars Geography Visualizer
## Project Overview
GeoStarMap is a minimalist single-page application that visualizes the geographic distribution of GitHub repository stargazers on an interactive world map.
## Core Requirements
### Technical Stack
- **Framework**: React with TypeScript
- **Build Tool**: Vite
- **Package Manager**: pnpm
- **UI Library**: shadcn/ui
- **Code Quality**: ESLint + Prettier
- **Map Library**: Leaflet with OpenStreetMap tiles
- **Architecture**: Client-side only SPA (no backend)
### Features
1. **Repository Input**: Accept GitHub repository URL (format: `https://github.com/owner/repo`)
2. **API Token Support**: Optional GitHub API token input (not persisted)
3. **Geographic Visualization**: Display stargazers' locations on an interactive map
4. **Progress Tracking**: Show real-time progress while processing users
5. **Caching**: Cache geocoded locations in localStorage to minimize API calls
6. **Responsive Design**: Mobile-first, works on all screen sizes
## Implementation Details
### GitHub API Integration
- **Endpoint**: `GET https://api.github.com/repos/{owner}/{repo}/stargazers`
- **Headers**:
- Accept: `application/vnd.github.v3+json`
- Authorization: `Bearer {token}` (if provided)
- **Pagination**: Handle `Link` header for repos with many stars
- **Rate Limits**:
- Unauthenticated: 60 requests/hour
- Authenticated: 5,000 requests/hour
### Geocoding Service
- **Service**: Nominatim (OpenStreetMap)
- **Endpoint**: `https://nominatim.openstreetmap.org/search`
- **Rate Limit**: 1 request per second (must be enforced client-side)
- **Query Format**: `?q={location}&format=json&limit=1`
- **User-Agent**: Required header with app name
### Caching Strategy
- **Storage**: localStorage
- **Key Format**: `geostarmap_cache_{normalized_location}`
- **Data Structure**:
{
lat: number;
lng: number;
displayName: string;
timestamp: number;
}
- **Expiry**: 30 days
- **Size Limit**: Monitor localStorage quota (~5-10MB)
### UI Components
#### 1. Header
- App title and brief description
- Minimalist design with consistent spacing
#### 2. Input Section
- Repository URL input field
- "Analyze Repository" button
- Collapsible "Advanced Options" with API token input
- Clear visual feedback for invalid inputs
#### 3. Progress Indicator
- Show current operation: "Fetching stargazers...", "Geocoding locations..."
- Progress bar with percentage
- Cancel button for long operations
#### 4. Map View
- Full-width map container
- Marker clustering for better performance
- Popup on marker click showing:
- GitHub username
- Location string
- Link to GitHub profile
- Zoom controls and fullscreen option
### Error Handling
- Invalid repository URL format
- Repository not found (404)
- Rate limit exceeded (403)
- Network errors
- Invalid/ungeocoded locations (show in a separate list)
### Performance Considerations
- Batch API requests where possible
- Implement request queue for geocoding
- Use React.memo for expensive components
- Lazy load map library
- Virtual scrolling for large user lists
### Design Principles
- **Minimalism**: Clean, uncluttered interface
- **Accessibility**: ARIA labels, keyboard navigation
- **Feedback**: Clear loading states and error messages
- **Privacy**: No data persistence beyond cache, no analytics
## File Structure
src/
├── components/
│ ├── Header.tsx
│ ├── RepoInput.tsx
│ ├── ProgressBar.tsx
│ ├── Map.tsx
│ └── ErrorBoundary.tsx
├── hooks/
│ ├── useGitHubAPI.ts
│ ├── useGeocoding.ts
│ └── useCache.ts
├── services/
│ ├── github.ts
│ ├── geocoding.ts
│ └── cache.ts
├── types/
│ └── index.ts
├── utils/
│ ├── rateLimit.ts
│ └── validation.ts
├── App.tsx
├── main.tsx
└── index.css
## Development Guidelines
- Use conventional commits (feat:, fix:, docs:, etc.)
- Format all files with Prettier on save
- Follow React best practices and hooks rules
- Keep components small and focused
- Use TypeScript strict mode
- Minimize external dependencies
## Future Enhancements (Out of Scope)
- Export visualization as image
- Historical star growth animation
- Contributor location analysis
- Repository comparison mode
- Backend API for caching/analytics
### Development Guidelines
1. Keep dependencies minimal
2. Use async/await for all asynchronous operations
3. Implement proper error boundaries
4. Use semantic HTML for accessibility
5. Follow mobile-first responsive design
6. Keep bundle size under 500KB (excluding map tiles)
### Deployment
- Static site deployment (Vercel, Netlify, GitHub Pages)
- No backend or serverless functions needed
- Environment variables not required
## Future Enhancements (Out of Scope)
- Light theme toggle
- Export map as image
- Time-based animation of stars
- Repository comparison
- User authentication
- Data persistence
Claude Code を使う上での、つまづきポイントと解決策
- 体感ですが、Claude Code に Go 言語のプログラムを書かせた時よりもミスが多い気がしました。Claudeが「できました!」→ ビルドしてみるとエラーということも多い。
→ CLAUDE.md に「必ずビルドが通ることを確認すること」という指示を追加する。 - 一気に作らせると、根本から間違えていることがある。最初は React を使わずにピュアな HTML で書いていて、途中で作り直しというパターンが発生。
→ Claudeにタスク分解をさせて、フェーズを区切る。フェーズごとに Git にコミットさせて結果を確認する。 - 最適化などは気が回らないことが多い。最初は GitHub のユーザー取得 API を使っていた。GraphQLを使ったほうが効率的に必要な情報だけを取得できるので、後からリファクタリングが必要になった。また、地理情報の取得についても、Claudeがオープンデータを使うことを提案することはなかった。AI は自発的に提案はしてくれない。
→ つくったあとに、より最適化ができないか、あらためて考えさせる。
完成
所要時間は最初のバージョンまで1時間くらいでした。最適化や調整などで結局2時間くらいかかりました。
Open Streat Map の Nominatim の API で Geocoding しています。レートリミットは 1 秒に 1 回です。
主要な都市の座標は Simplemaps の無料データを利用して、Geocoding しなくても取得できるようにしています。
過去に自分のつくったリポジトリで実験
TypeScript Deep Dive 日本語版 (Star 311)
結果が日本に集中しているので何となく正しそう。
yottahmd/donburi (Star 318)
Ebitengine用のライブラリで実験。
dagu-org/dagu (Star 2.3k)
割と大きめのリポジトリで実験。
拡大もできます。
アメリカ
ヨーロッパ
東南アジア
東アジア
Claude Code で開発した感想
要件をしっかり明確にすることで、ほぼ自動的にコーディングが可能だと感じました。
Claude 4 は相変わらずコンテキストウィンドウが貧弱ですが、Claude Code は自動的に圧縮が行われるので Cline などよりも使いやすいです。
総じて人間による手動テスト、フィードバック、追加の検討は欠かせないと感じました。それでも、このスピードで実装が終わってしまうのは驚異的です。
今後は開発者がエージェントを複数並列で使っていくことが一般的になっていきそうです。エージェントに良い仕事をさせるのに欠かせないのがコンテキストです。今後はコンテキスト管理、圧縮などの手法が急速に発達していく予感がしています。
コンテキストエンジニアリングのこれからの発展がとても楽しみです。
参考資料
告知
6 月 25 日 (水) ― DreamArts Tech Talk
個人で大きめの OSS (スター数 2,300 程度) をゼロから育ててきた経緯や OSS 開発に AI を活用する TIPS についてお話しします。
まだ席に余裕がありますので、ぜひご参加ください!
Views: 0