Building an iNaturalist Observation Tool with Claude Code on a Phone: A Serverless Git Scraping Architecture in Practice

Simon Willison built a three-layer serverless nature observation data pipeline using his phone and Claude Code.
During a camping trip, Simon Willison used only his phone and Claude Code to build a display tool consolidating iNaturalist observation records. The project employs a three-layer architecture: a Python CLI for data retrieval and spatiotemporal clustering, GitHub Actions running Git Scraping for zero-cost data persistence, and a pure static frontend for display and interaction. The entire system requires no traditional backend server with operational costs approaching zero, demonstrating the practical value of AI-assisted programming and lightweight architecture design.
Simon Willison, during a camping trip, built a complete nature observation display tool using nothing but his phone and Claude Code. This project not only demonstrates the practical usability of AI programming assistants on mobile devices but also presents a lightweight data pipeline design pattern worth learning from.
Project Background: Consolidating Scattered iNaturalist Observation Data
iNaturalist is one of the world's largest citizen science platforms, jointly operated by the California Academy of Sciences and the National Geographic Society. As of 2024, it has accumulated over 200 million observation records covering more than 400,000 species. Users can upload photos of wildlife and plants observed in the field, with the community assisting in species identification. The platform uses a crowdsourced identification mechanism—after users upload photos, community members and AI models (trained on computer vision) collaboratively assist with species identification. When multiple experts reach consensus, a record is marked as "Research Grade" and can be directly cited by academic institutions. The platform provides a comprehensive RESTful API that allows developers to query data by user, geographic range, taxonomic group, and other dimensions, returning JSON structures containing species information, GPS coordinates, timestamps, and multi-resolution image URLs.
Simon Willison has two separate accounts on the platform and wanted to consolidate observations from both accounts, displaying them grouped by time and location.
The requirement seems simple, but it involves data retrieval, aggregation processing, persistent storage, and frontend display—multiple layers of work. And the entire development process was completed during camping, entirely on a phone via Claude Code for web. Claude Code is an AI programming agent tool released by Anthropic, initially running as a terminal command-line tool before expanding to the web. Unlike traditional AI code completion tools (such as GitHub Copilot), Claude Code is more like a "conversational development partner"—developers describe requirements, and the AI generates complete code files, project structures, and even configuration files. This interaction mode is naturally suited for mobile devices because it replaces extensive keyboard input with natural language descriptions, dramatically reducing the friction of programming on a small screen.
Technical Architecture: A Three-Layer Serverless Data Pipeline
The project's architecture is divided into three layers, each kept as simple as possible.
Python CLI: Data Retrieval and Clump Processing
Simon built a Python command-line tool called inaturalist-clumper, responsible for pulling observation records from the iNaturalist API and grouping them by spatiotemporal proximity ("clumping"). The default rule is: observations within 2 hours and 5 kilometers are grouped together.
Clumping is essentially a density-based spatiotemporal clustering algorithm, similar in concept to the classic DBSCAN algorithm in data science. DBSCAN discovers clusters of arbitrary shape by defining a neighborhood radius (eps) and minimum number of points, while Simon's implementation is more simplified—using only a time window and spatial radius as two thresholds to group qualifying observation records together. Geographic distance calculations typically use the Haversine formula, which is based on spherical trigonometry and can accurately calculate the great-circle distance on the Earth's surface given two points' latitude and longitude. This simplified clustering approach avoids complex machine learning dependencies and can be implemented in just a few dozen lines of Python code, perfectly suited for a lightweight CLI tool.
This design closely matches real-world usage scenarios—when you're conducting nature observations at a location, the multiple photos you take are naturally clustered in time and space, and the clumping algorithm can automatically group all records from a single "outing."
GitHub Actions: Scheduled Automated Data Updates
The second step is setting up the inaturalist-clumps repository, using Git Scraping technology—running the aforementioned CLI tool on a schedule via GitHub Actions and committing the output to a clumps.json file in the repository.
Git Scraping is a data engineering pattern that Simon Willison first systematically proposed in 2020. Its technical implementation relies on GitHub Actions' cron scheduling capability—defining a YAML workflow file in the repository's .github/workflows directory with a timed trigger rule (e.g., once per hour). The Actions runner automatically executes the data scraping script, then commits the results back to the repository via git add, git commit, and git push. GitHub provides unlimited free Actions minutes for public repositories, with 2,000 free minutes per month for private repositories. More critically, GitHub's raw.githubusercontent.com domain supports CORS headers by default, meaning any frontend page can directly request JSON files from the repository via fetch() without configuring a proxy server.
Pure Frontend Page: Static Display and Interaction
The final step is building the frontend display page. Simon gave Claude Code a clear prompt requesting an HTML page with the following features:
- Fetch JSON data from GitHub via
fetch() - Display observation records using iNaturalist small thumbnails (
small.jpg) - Implement lazy loading with
loading=lazy - Show large images (
large.jpg) in a modal when thumbnails are clicked - Display species common names
The native HTML loading="lazy" attribute is a browser-level lazy loading implementation, first supported in Chrome in 2019 and now adopted by all major browsers. When this attribute is set on an image element, the browser uses the Intersection Observer API to automatically detect whether the image is approaching the viewport (typically beginning to load a few hundred pixels in advance), only initiating the HTTP request when it's about to become visible. For pages like iNaturalist observation records that might contain hundreds of thumbnails, lazy loading can reduce initial page load time from dozens of seconds to a few seconds while significantly reducing bandwidth consumption. Combined with iNaturalist's multi-resolution image URLs (small.jpg at approximately 75×75 pixels, large.jpg at approximately 1024 pixels wide), the total data volume of the thumbnail list can be kept within a reasonable range.
A single prompt completed the entire frontend page, with the final product published at tools.simonwillison.net/inat-sightings.
Git Scraping Pattern Deep Dive: Zero-Cost Data Persistence
Git Scraping is a data engineering pattern that Simon Willison has long promoted, and this project is a textbook application of it. Simon himself maintains dozens of Git Scraping projects, tracking everything from California fire data to vaccination statistics and other public data sources. Its core advantages include:
- Free hosting and CDN distribution: GitHub provides free static file hosting with CORS cross-origin access support, allowing JSON files to be directly fetched by frontends
- Built-in version control: Every data update has a Git commit record, making data changes fully traceable. This means you have not only the latest data but also complete historical snapshots—using
git logandgit diff, you can precisely see which records changed in each update - Zero operational cost: No servers or databases to maintain; GitHub Actions handles scheduled script execution
This pattern is particularly suited for "periodic scraping, static display" scenarios, such as monitoring price changes, tracking public dataset updates, or aggregating multi-source information. For individual developers, it virtually eliminates the burden of backend infrastructure.
Real-World Insights from AI-Assisted Development
This project reflects several noteworthy trends:
Serverless architecture taken to its extreme: The entire system has no traditional backend server. Data processing is delegated to GitHub Actions, storage relies on a Git repository, and the frontend is a purely static page. Operational costs approach zero. The serverless architecture concept was first popularized by AWS Lambda in 2014, with the core idea that developers need not manage server infrastructure. Simon's project pushes this concept to a more extreme direction—not even Lambda functions are needed, relying entirely on GitHub's free infrastructure. This "ultra-lightweight serverless" pattern has clear boundaries of applicability: data update frequency can't be too high (GitHub Actions' cron minimum interval is 5 minutes, with potential execution delays), individual JSON files shouldn't exceed a few dozen MB (otherwise frontend parsing will lag), and it doesn't support user write operations. But for personal projects, data dashboards, monitoring panels, and other read-only display scenarios, this architecture's cost-effectiveness is nearly unbeatable.
Mobile programming is no longer a gimmick: Completing development on a phone while camping wasn't a deliberate show of skill. When developers have clear requirements and a well-thought-out architecture, AI programming tools like Claude Code can efficiently handle the concrete coding implementation, making device form factor no longer a bottleneck. The key is the shift in interaction paradigm—traditional programming relies on precise keyboard input and multi-file switching, while AI-assisted programming simplifies core interaction to natural language descriptions, which effectively bridges the input efficiency gap between phones and computers.
Architectural thinking matters more than coding ability: The technical difficulty of this project isn't high; what's truly valuable is the architectural decision to decompose the problem into three clean components. AI excels at executing well-defined coding tasks, while architecture design and requirement decomposition still rely on the developer's experience and judgment. Simon's choices—using a CLI tool for data processing, Git Scraping for persistence, and a pure frontend for display—minimize complexity at each step while maintaining the system's maintainability and extensibility.
Conclusion: A Lightweight Architecture Template for Individual Developers
From Python CLI to Git Scraping to pure frontend display, Simon Willison built a complete data pipeline with three simple components. This project proves that with sound architectural design combined with an AI programming assistant, individual developers can rapidly build practical tools in extremely short timeframes—even in non-traditional development environments.
For developers looking to try similar projects, the Git Scraping + static frontend combination is a solution worth prioritizing. It's simple enough, costs virtually nothing, and is perfectly adequate for scenarios with modest data volumes.
Related articles
TutorialsChatGPT Plus Subscription Guide: Are GPT-5.5, image-2, and Codex Worth the Upgrade?
A detailed look at ChatGPT Plus features — GPT-5.5, image-2, and Codex — with a Plus vs Pro comparison and a complete step-by-step subscription guide for users outside the US.
TutorialsHarness AI Engineering in Practice: Using Claude Code to Master Enterprise-Level E-Commerce Development
Deep dive into Harness AI Engineering: master enterprise e-commerce development with Claude Code using the Rules, Skills, Wiki, and Changes framework.
TutorialsCursor + Codex Dual-IDE Collaboration: A Practical Methodology for Open-Source Project Customization
A complete methodology for open-source project customization based on real-world experience, detailing the Cursor+Codex dual-IDE workflow, seven-stage process, MVP validation, and AI source code reading techniques.