Building an iNaturalist Observation Display Tool Over a Weekend with a Phone + Claude Code: Full Workflow

Simon Willison built an iNaturalist display tool using just a phone and Claude Code, showcasing a new AI-assisted mobile dev paradigm.
While camping, Simon Willison built a complete iNaturalist nature observation display tool using only his phone and Claude Code. The project employs a three-layer architecture: a Python CLI tool for data scraping and spatiotemporal clustering, Git Scraping for zero-cost automated data updates, and Claude Code to generate a frontend single-page application. The project demonstrates the viability of AI-assisted programming on mobile devices and an efficient development paradigm using free GitHub infrastructure for personal data tools.
Background
Simon Willison—renowned open-source developer and creator of Datasette—recently shared an interesting weekend project: while camping, he built a web tool for displaying iNaturalist nature observation records entirely using his phone and Claude Code. This project not only demonstrates the viability of AI-assisted programming on mobile devices but also showcases an elegant data pipeline design approach.
Simon Willison has deep influence in the open-source community. He is one of the co-creators of the Django framework and later created Datasette—a tool that instantly transforms SQLite databases into interactive APIs and web interfaces. Datasette's design philosophy emphasizes "data as publication"—the idea that any structured data should be publishable as a browsable, queryable web service at minimal cost. Understanding this background helps us appreciate the series of architectural decisions he made in this project—they all point toward the same goal: turning data into a usable product in the most lightweight way possible.
Why Build This Project
iNaturalist is one of the world's largest citizen science platforms, where users can upload photos of wildlife and plants they observe in the field, with the community helping to identify species. As of 2024, the platform has accumulated over 200 million observation records, covering more than 400,000 species, with millions of active users. iNaturalist employs a unique "community consensus" mechanism for species identification: when multiple users agree on the species identification for the same observation record, it gets marked as "Research Grade," and these high-quality data are synced to scientific research databases like the Global Biodiversity Information Facility (GBIF), truly enabling citizen science contributions to professional research. iNaturalist provides a fairly open RESTful API that supports queries by user, location, taxonomic classification, and other dimensions, with each record containing rich structured data including photo URLs, GPS coordinates, timestamps, and taxonomic information.
Simon has two iNaturalist accounts and wanted to merge the observation records from both accounts, displaying them grouped by time and location.
This requirement seems simple, but iNaturalist doesn't officially provide a cross-account aggregation view. So Simon decided to build the entire toolchain from scratch over a weekend.
Technical Architecture: Three-Layer Data Pipeline Design
The entire project consists of three layers, each solving a specific problem, combining to form a complete data pipeline.
Python CLI Tool: Data Scraping and Spatiotemporal Clustering
Simon first built a Python command-line tool called inaturalist-clumper. The core functionality of this tool is to pull observation records from the iNaturalist API and then perform "clumping" based on spatiotemporal proximity—the default rule groups observations within 2 hours and 5 kilometers into the same cluster.
Spatiotemporal clustering is a classic problem in geographic information science. Traditional clustering algorithms like K-Means only consider spatial distance, while spatiotemporal clustering needs to measure the "proximity" between data points simultaneously in both spatial and temporal dimensions. Common approaches include using spatiotemporal extensions of the DBSCAN (Density-Based Spatial Clustering of Applications with Noise) algorithm, or the simpler, more intuitive threshold method that Simon adopted here—setting a time window and spatial radius, grouping records that satisfy both conditions together. Simon's chosen thresholds of 2 hours / 5 kilometers are empirical values that roughly correspond to the range of a single nature observation outing on foot or by short drive. While this rule-based clustering method isn't as flexible as machine learning algorithms, it excels in interpretability and simplicity of implementation, making it highly suitable for personal project scenarios like this.
This clustering strategy is very practical: when you're conducting a nature observation activity at a certain location, you typically photograph multiple species within a short period, and grouping them together corresponds nicely to the concept of a single "outing."
Git Scraping: Zero-Cost Automated Data Updates
With the data scraping tool in place, how do you keep the data updated? Simon employed the "Git Scraping" technique he himself popularized—using GitHub Actions to run scripts on a schedule and commit results to a Git repository.
The core idea of Git Scraping is to "repurpose" the Git version control system as a time-series database. GitHub Actions is GitHub's free CI/CD service that supports scheduled triggers via cron expressions (e.g., running once per hour or once per day). Each execution pulls the latest data from an external API, writes it to a file in the repository, then commits the changes via git commit and git push. Since Git naturally records the complete diff of each commit, you not only have the latest data snapshot but also automatically gain a complete history of changes—extremely useful for tracking data trends. Since Simon first systematically proposed this pattern in 2020, the community has produced hundreds of Git Scraping projects covering everything from pandemic data tracking to government open data monitoring.
Specifically, he created the simonw/inaturalist-clumps repository, which periodically runs the clumper tool and writes clustering results to a clumps.json file. Since GitHub's Raw file service supports CORS cross-origin access, this JSON file naturally serves as a free, auto-updating API endpoint.
CORS (Cross-Origin Resource Sharing) is a browser security mechanism. By default, JavaScript on a webpage can only make requests to same-origin servers (same protocol, domain, and port). If a frontend page is hosted on simonw.github.io while the data file is on raw.githubusercontent.com, the browser would block the request due to cross-origin restrictions—unless the server includes the Access-Control-Allow-Origin header in its response. GitHub's Raw file service happens to set response headers that allow cross-origin access, meaning any webpage can directly read repository file contents via fetch() without needing to set up an intermediate proxy server.
The elegance of this pattern lies in: zero-cost hosting, built-in version history, no server maintenance required. The Git repository itself is the database, GitHub Actions is the scheduler, and GitHub Raw is the CDN.
Frontend Display: Claude Code Generates a Single-Page Application
The final step was building the frontend page. Simon used Claude Code on his phone to send a prompt to his simonw/tools repository:
Build inat-sightings.html - an app that does a fetch() against the clumps.json and then displays all of the observations on one page using the small.jpg URLs for the thumbnails - with loading=lazy - but when a thumbnail is clicked showing the large.jpg in an HTML modal.
Claude Code is a terminal-based AI programming agent tool from Anthropic that can understand natural language instructions directly in the command-line environment, read project context, generate code, and perform file operations. Unlike traditional code completion tools, Claude Code has full project awareness—it can browse directory structures, read existing files, understand project conventions, and then generate new files consistent with the existing code style. Since it runs in the terminal, any device that supports a terminal emulator can theoretically use it, including Termux on Android phones or SSH connections to remote servers. This is the technical foundation that enabled Simon to complete development on his phone.
This prompt is concise yet complete, containing key technical details: the data source URL, thumbnail strategy (lazy loading), interaction pattern (click-to-enlarge modal), and content requirements (displaying species common names). The loading=lazy attribute is a native HTML lazy-loading attribute that tells the browser to only start loading images when they're about to enter the viewport—crucial for pages with many images. iNaturalist observation records might contain hundreds of thumbnails, and loading them all at once would severely impact page performance and user bandwidth consumption. Based on this prompt, Claude Code generated a complete single-page application.
Key Highlights of This Project
Mobile AI Programming Is Now Viable
The entire project was completed on a phone while camping, demonstrating that Claude Code already has sufficient capability to handle moderately complex development tasks. For developers, this means you can start building whenever inspiration strikes, without waiting to get back to a computer.
The significance of this goes deeper than it appears on the surface. Traditional software development is highly dependent on large screens, physical keyboards, and complex IDE environments—mobile programming has long been considered "impractical." But AI programming agents change this equation: when you no longer need to type code line by line but instead describe requirements in natural language, a phone's small screen and touch keyboard are no longer bottlenecks. The developer's role shifts from "code writer" to "intent expresser," and expressing intent doesn't require an IDE—a terminal window is sufficient. Simon's practice here can be seen as an early signal of this paradigm shift.
Git Scraping Remains a Powerhouse for Personal Projects
Git Scraping is a concept Simon proposed in 2020, and years later, this pattern still demonstrates tremendous vitality. It's particularly suited for personal projects and small-scale data collection scenarios—no database needed, no server needed, no operations needed, just a GitHub repository and a scheduled task.
It's worth noting that Git Scraping's "free" tier isn't unlimited. GitHub Actions provides 2,000 minutes of execution time per month for free accounts, which is more than sufficient for most personal data collection projects. However, if script execution frequency is too high or individual runs take too long, you may hit limits. Additionally, GitHub repositories have a 100MB limit per file and recommend keeping total repository size under 1GB, meaning Git Scraping is better suited for small-to-medium structured data (like JSON and CSV) rather than storing large binary files or massive datasets. Within these constraints, it's arguably the lowest-friction data pipeline solution available to individual developers.
A Good Prompt Is a Product Specification
Simon's prompt to Claude Code is essentially a concise product specification. It doesn't specify particular implementation approaches (what framework, what CSS solution) but instead focuses on functional requirements and user experience. This "declarative programming" approach is becoming a best practice in AI-assisted development.
"Declarative" vs. "imperative" is a classic pair of concepts in programming paradigms. Imperative programming tells the computer "how to do it"—describing specific operations step by step; declarative programming tells the computer "what to do"—only describing the desired result, letting the system determine the implementation path. SQL is declarative (you describe what data you want, and the database engine decides how to query it), while most general-purpose programming languages are imperative. AI-assisted programming is taking this declarative philosophy to new heights: developers declare requirements in natural language, and AI agents handle choosing the tech stack, designing code structure, and handling edge cases. Simon's prompt works precisely because it describes requirements at the right level of abstraction—neither too vague ("make a webpage") nor too specific ("create a React component"), but precisely conveying the data flow, interaction patterns, and performance requirements that represent the truly important product decisions.
Conclusion
Though modest in scale, this project demonstrates an efficient modern development paradigm: use AI to rapidly generate code, use Git Scraping to implement a zero-cost data pipeline, and use GitHub infrastructure for hosting and automation. For developers looking to quickly build personal data tools, this combination is well worth learning from.
From a broader perspective, this project embodies an emerging "personal infrastructure" philosophy: individual developers no longer need to mimic enterprise-grade architectures to build their own tools. Instead, they can cleverly combine free cloud services (GitHub Actions for scheduling, GitHub Pages for hosting, GitHub Raw for APIs) with AI programming agents to turn ideas into usable products at extremely low cost and high speed. This pattern lowers the barrier to software development, enabling more people to customize tools for their specific needs rather than being forced to adapt to the functional boundaries of general-purpose software.
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.