Simon Willison's Complete Process of Building an iNaturalist Observation Gallery with Phone + Claude Code

Simon Willison built a complete web tool with just his phone and Claude Code during a camping trip.
Simon Willison built an iNaturalist observation display tool using only his phone and Claude Code while camping. The project uses a three-layer architecture: a Python CLI tool for spatiotemporal data clustering, Git Scraping via GitHub Actions for automatic data updates, and Claude Code generating a pure frontend gallery page from a precise prompt. The entire project is serverless and zero-maintenance, demonstrating how AI-assisted programming is shifting developer value from code writing to architectural design and requirements expression.
Background: A Complete Project Built During a Camping Trip
Simon Willison—renowned developer and creator of Datasette—completed a full Web tool during a weekend camping trip using nothing but his phone and Claude Code. Simon is one of the co-creators of the Django Web framework and later built Datasette—an open-source tool that instantly transforms SQLite database files into interactive APIs and data exploration interfaces. He has long championed the "small tools" philosophy, advocating for solving specific problems with the simplest possible tech stack rather than building massive systems. He's also one of the most active practitioners and chroniclers of AI-assisted programming.
This tool displays his observation records from two different accounts on iNaturalist (a global nature observation community platform), intelligently grouped by time and location. iNaturalist is one of the world's largest citizen science platforms, jointly operated by the California Academy of Sciences and the National Geographic Society, with over 200 million biological observation records. Users upload photos of flora and fauna, the platform uses computer vision models for automatic species identification, and community experts then verify the results. Observations that reach "Research Grade" are synced to the Global Biodiversity Information Facility (GBIF) for direct use in academic research. iNaturalist provides a comprehensive RESTful API supporting queries by user, geographic range, taxonomic group, and other dimensions—which forms the data foundation for Simon's project.
The entire build process demonstrates the current practical capabilities of AI-assisted programming—no need to sit at a computer, no need for a complex development environment. A phone plus an AI coding assistant is enough to complete full-stack development from backend data processing to frontend display.
Technical Architecture: A Three-Layer Progressive Design
Layer 1: Python CLI Data Processing Tool
Simon first built a Python command-line tool called inaturalist-clumper, which fetches observation data from the iNaturalist API and performs "clumping" processing.
The default clustering rules are highly intuitive: observations within 2 hours of each other and within 5 kilometers geographically are grouped together. This means all discoveries from a single outdoor activity are automatically aggregated into a complete "sighting event" record.
This spatiotemporal clustering method is essentially a threshold-based connected component clustering approach, similar to a simplified version of the classic DBSCAN (Density-Based Spatial Clustering of Applications with Noise) algorithm from data mining. DBSCAN discovers clusters of arbitrary shape by defining a neighborhood radius and minimum point count, while Simon's implementation is more streamlined—using only time difference and spatial distance thresholds to chain consecutive observations into groups. This design aligns perfectly with the actual rhythm of outdoor activities: a hike or birdwatching session typically lasts several hours within a range of a few kilometers. Geographic distance calculation typically uses the Haversine formula, which computes the great-circle distance between two points on the Earth's surface based on spherical trigonometry, accounting for the Earth's curvature.
Layer 2: Git Scraping for Automated Data Updates
With the data processing tool in place, the next step is keeping the data current. Simon employed his own popularized Git Scraping technique—using GitHub Actions to run scripts on a schedule and commit the results to a Git repository.
Git Scraping is a data tracking pattern that Simon Willison proposed and popularized in 2020. Its core idea is to "abuse" the Git version control system as a time-series database: using GitHub Actions cron scheduled tasks (based on POSIX cron syntax, with a maximum frequency of once every 5 minutes) to periodically run scraper scripts and commit the results to a repository. Since Git naturally records the diff of each commit, users can trace the complete change history of data through git log and git diff. This pattern has been widely adopted for tracking changes in government public data, monitoring website price changes, recording API response variations, and more. GitHub provides free Actions runtime for public repositories (2,000 minutes per month), making the operational cost of this approach essentially zero.
Specifically, the simonw/inaturalist-clumps repository automatically runs the clumper tool and saves the clustering results as a clumps.json file. Since this file is hosted on GitHub, it natively supports CORS cross-origin access, allowing frontend JavaScript to fetch the data directly.
CORS (Cross-Origin Resource Sharing) is a security policy enforced by browsers. By default, JavaScript in a browser can only make requests to servers that share the same origin (same protocol, domain, and port) as the current page—this is the Same-Origin Policy. When frontend code needs to fetch data from a different domain, the target server must include an Access-Control-Allow-Origin header in its HTTP response to explicitly grant authorization. GitHub's raw.githubusercontent.com domain has response headers set by default to allow access from any origin, enabling any webpage to directly fetch raw file content hosted on GitHub via the fetch API.
The elegance of this architecture lies in: using a Git repository as a free JSON API service, with no need to maintain any server or database.
Layer 3: Claude Code Generates a Pure Frontend Display Page
The final step is building the frontend display page, which was entirely handed off to Claude Code via a natural language prompt.
Claude Code is a command-line AI coding agent tool from Anthropic. Unlike traditional chat-based AI assistants, it can directly read project files, execute commands, and write and modify code within a terminal environment. Based on the Claude large language model, it supports understanding full project context and performing multi-step code generation and debugging. In Simon's case, Claude Code ran via a terminal app on his phone, receiving requirements described in natural language and automatically generating complete frontend code including HTML structure, CSS styling, and JavaScript interaction logic. This working mode shifts the bottleneck of programming from "writing code" to "expressing requirements"—the developer's core work becomes how to precisely describe the desired technical behavior.
Simon's prompt was highly precise, containing the following key technical requirements:
- Use
fetch()to retrieve JSON data from the GitHub raw file URL - Use iNaturalist's
small.jpgURL format to display thumbnails - Add
loading=lazyto implement lazy loading for images - Display
large.jpgin an HTML modal when thumbnails are clicked - Show species common names (when available)
The native HTML loading="lazy" attribute is a browser-level lazy loading solution introduced in 2019, now supported by all major browsers. It works by using the Intersection Observer API to monitor the intersection state between image elements and the viewport, only initiating network requests to load image resources when an image is about to enter the visible area. Previously, developers needed to manually write JavaScript code or import third-party libraries to achieve similar functionality. For a gallery page like Simon's with numerous nature observation photos, lazy loading can significantly reduce initial page load time and bandwidth consumption—a user might have hundreds or even thousands of thumbnails, but the first screen typically only needs to load a dozen or so.
One prompt, one complete interactive image gallery generated.
Notable Design Principles
The Ultimate Serverless Architecture in Practice
The entire project has no traditional backend server whatsoever. Data storage uses a GitHub repository, data updates use GitHub Actions, and the frontend is pure static HTML. This "zero-ops" architecture is nearly ideal for personal projects—no server costs, no downtime risk, no maintenance burden.
This pattern can also be considered a variant of Jamstack architecture. Jamstack (JavaScript, APIs, Markup) emphasizes pre-building and decoupling, delegating dynamic functionality to third-party APIs and client-side JavaScript while distributing static assets globally via CDN. Simon's implementation is even more extreme—skipping even a dedicated static site generator, completing all work with a single HTML file plus remote JSON data.
Mobile Programming: AI Is Changing How We Write Code
What makes this case special is the development environment—a phone. Simon completed the entire project during a camping trip, demonstrating that AI coding tools are redefining "when you can write code." When Claude Code can understand a structured natural language description and generate usable code, a keyboard and IDE are no longer prerequisites for programming.
The deeper significance of this shift is that programming is evolving from a skill requiring precise syntax memorization and rapid typing ability into something closer to "architectural thinking" and "requirements engineering." A developer's value is increasingly reflected in their ability to decompose problems, their judgment on technical solutions, and their ability to review and correct AI output. The small keyboard on a phone screen is no longer an obstacle, because what you need to type is no longer hundreds of lines of precise code syntax, but rather a few paragraphs of clear natural language description.
A Practical Example of Prompt Engineering
Simon's prompt to Claude Code is worth studying carefully. It's not a vague requirement description, but includes specific URL patterns, HTML features (lazy loading, modal), data fields (common species names), and other precise information. A good AI prompt is essentially a condensed technical specification document.
This prompt writing approach embodies an important principle: instructions to AI should be sufficiently specific at the "what to do" level, but retain flexibility at the "how to do it" level. Simon explicitly specified the data source URL, image size specifications, interaction behavior, and other deterministic requirements, but didn't dictate specific CSS layout schemes or JavaScript implementation details. This strategy of "constraining boundary conditions while freeing implementation space" allows AI to fully leverage its strengths in code generation while ensuring the output meets the developer's core expectations.
Conclusion
Although modest in scale, this project fully demonstrates a paradigm for modern personal tool development: process data with Python, automate with Git Scraping via GitHub Actions, generate frontend code with Claude Code, and host everything on GitHub. Throughout the entire workflow, the developer's core value lies not in how many lines of code they wrote, but in the ingenuity of architectural design and precise command of the toolchain.
For developers looking to try AI-assisted programming, this is an excellent reference case—starting from a real need, using the lightest possible tech stack, in the most constrained environment, delivering a complete, usable product. It also confirms a profound shift underway in software development: the core competitive advantage in programming is migrating from "code implementation ability" to "system design ability" and "tool orchestration ability," with AI serving as the key catalyst accelerating this transformation.
Related articles
Product ReviewsThe Programmer's Desk Setup Guide: Building a Workspace That Feels Like Home
Discover how programmers build productive, comfortable workspaces. From multi-monitor setups to ergonomic design, explore the desk philosophy that drives focus and flow.
Product ReviewsQoder vs Cursor Real-World Comparison: Which $20/Month AI IDE Is Better?
Hands-on comparison of Qoder vs Cursor AI IDEs: Agent autonomy, human interaction count, and architecture decisions. Qoder needed only 2 interactions vs Cursor's 8.
Product ReviewsCursor Cloud Agent Demo: Eliminating Bottlenecks Across the Entire Software Development Lifecycle
Deep analysis of Cursor's Cloud Agent demo showing how cloud VMs, automated test artifacts, and a full-chain control plane systematically eliminate human bottlenecks across the software development lifecycle.