Simon Willison's Full Process of Fixing a Datasette Map Bug with GPT-5.5 + Codex

Datasette map bug leads to Referrer-Policy plugin development with AI-assisted programming
Datasette's demo page map stopped working due to two independent bugs: Cloudflare CAPTCHA incorrectly blocking JSON requests, and Datasette's default no-referrer policy causing OpenStreetMap to reject tile requests. Rather than changing the default, Simon Willison used GPT-5.5 + Codex to rapidly develop the datasette-referrer-policy plugin, demonstrating AI-assisted programming's efficiency in well-defined scenarios.
A Map Display Bug Uncovers a Chain of Problems
Datasette creator Simon Willison recently released a new plugin, datasette-referrer-policy 0.1, for customizing the HTTP Referrer-Policy header. Behind this seemingly simple plugin lies a fascinating chain of bug investigations that also showcases how GPT-5.5 and Codex perform in real-world plugin development.
Datasette is an open-source Python tool for quickly publishing SQLite databases as interactive web interfaces and APIs. Simon Willison, as one of the co-creators of the Django framework, designed Datasette with a highly plugin-based architecture. Through a hooks mechanism, developers can extend functionality without modifying core code, and there are now over 100 community plugins covering visualization, authentication, export, and many other scenarios.
The story began when the OpenStreetMap tile map on Datasette's official global-power-plants demo page suddenly stopped displaying properly. After investigation, Simon discovered two independent bugs hiding behind the issue.
Bug #1: Cloudflare CAPTCHA Incorrectly Blocking JSON Requests
The first problem stemmed from the Cloudflare Turnstile CAPTCHA verification Simon had added to the site a few weeks earlier. The map plugin needed to fetch data through a .json endpoint during loading, but the CAPTCHA mechanism was erroneously intercepting these JSON requests. Since the response wasn't an HTML page, users never had the opportunity to complete the verification, and the requests simply failed.
Cloudflare Turnstile is a frictionless verification solution designed to distinguish human users from automated bots. Unlike traditional CAPTCHAs, Turnstile typically completes verification in the background without requiring users to manually identify images. However, its verification flow depends on returning an HTML page to embed the verification script—when the request is for non-HTML resources like JSON, the verification flow can't complete normally, and the request gets blocked outright. The frontend JavaScript receives an unparseable error response.
This is a classic case of "security mechanism conflicting with functionality"—adding security protections without fully considering all request types. Simon resolved this by adjusting the CAPTCHA configuration to exclude JSON requests from the verification scope.
Bug #2: Referrer-Policy Causing OpenStreetMap to Reject Tile Requests
The second problem was more subtle. OpenStreetMap has a reasonable security policy: it rejects tile requests from sites that set the Referrer-Policy: no-referrer header. OSM needs to track tile usage through the Referer header to prevent resource abuse.
To understand this issue, you need to know how HTTP Referrer-Policy works. It's a security response header that controls whether the browser includes Referer header information when making cross-origin requests. The Referer header tells the target server which page the request originated from. The policy has multiple levels: no-referrer (never send origin information), origin (send only the domain), strict-origin-when-cross-origin (send only the domain for cross-origin requests, send nothing on HTTP downgrade), and more. no-referrer is the strictest privacy protection level, but it also means third-party services have no way of knowing where requests come from.
OpenStreetMap, as the world's largest open-source mapping project, provides free map base tiles to a vast number of websites through its tile servers. But OSM's tile usage policy explicitly requires users to allow sending valid HTTP Referer headers, enabling the operations team to track tile usage sources, identify abuse, and perform capacity planning. If a request is detected without Referer information, OSM servers return a 403 error or blank tiles. This policy helps OSM maintain free service to global users with limited server resources.
Datasette's default is precisely Referrer-Policy: no-referrer—the strictest privacy policy. All requests originating from Datasette pages carry no origin information, so OpenStreetMap servers simply rejected the tile requests.
Why Not Just Change Datasette's Default?
Simon's reasoning was thoughtful: no-referrer is a privacy-focused default, and rashly changing it could affect existing users' security expectations. Many Datasette users chose this tool precisely because of its commitment to privacy—for example, in internal data analysis scenarios where administrators don't want internal page URL structures leaked to external services through Referer headers. So he chose the safer approach—developing a standalone Datasette plugin that lets users who need to adjust the Referrer-Policy configure it themselves.
GPT-5.5 + Codex in Action: Developing a Datasette Plugin
This plugin was built collaboratively using Codex + GPT-5.5. Simon publicly shared the complete AI-assisted development process, offering a window into how AI programming tools perform in real projects.
GPT-5.5 is a model released by OpenAI in mid-2025, featuring significant improvements in reasoning depth and context understanding compared to GPT-4o. Codex is OpenAI's agent product specifically optimized for code generation and software engineering tasks, capable of autonomously executing code, running tests, and iterating on fixes within a sandbox environment. When used together, GPT-5.5 provides high-quality code generation and architecture design capabilities, while Codex handles the end-to-end engineering execution flow—including creating project structures, writing test cases, running validations, and automatically fixing issues based on results.
This was an ideal scenario for AI-assisted development:
- Clear requirements: Set an HTTP response header
- Well-defined patterns: Datasette plugins have standard development patterns and hook mechanisms (such as the
asgi_wrapperhook for modifying HTTP responses) - Manageable scope: Single-purpose functionality with minimal code
From Simon's experience, GPT-5.5 paired with Codex is highly efficient at handling tasks with "clear requirements + mature frameworks." Developers only need to describe the requirements and constraints, and the AI generates structurally complete, ready-to-use plugin code, including setup.py configuration, plugin hook implementation, test files, and README documentation.
Key Takeaways for Developers
This case offers several noteworthy insights:
- Security policies require a holistic perspective: When adding CAPTCHAs or modifying HTTP headers, consider the impact on all types of requests within the page, including AJAX calls, resource loading, and other non-page requests. In modern web applications, a single page may simultaneously initiate dozens of different request types, and the impact of security policies extends far beyond the page itself.
- Watch for implicit requirements from third-party services: When using external services like OpenStreetMap, pay attention to their special HTTP header requirements—this information is often not in the most prominent documentation location. Similar implicit requirements are common in CDN, font service, analytics tool, and other third-party integrations.
- Plugins over changing defaults: When default behavior has its own rationale, providing optional configuration through plugins is a more responsible approach for users. This also reflects the Unix philosophy of "do one thing well" applied to modern software architecture.
- The sweet spot for AI-assisted programming: Small tools and plugin development with clear boundaries and mature patterns is currently where AI programming assistants deliver the most efficiency. When requirements are ambiguous, architecture is undecided, or complex business logic is involved, AI performance drops significantly, and developers still need to lead design decisions.
Key Takeaways
- The Datasette map demo page failed to display tiles due to two bugs: CAPTCHA incorrectly blocking JSON requests and the Referrer-Policy header causing OSM rejections
- OpenStreetMap rejects tile requests from sites with a no-referrer policy, which conflicts with Datasette's default privacy settings
- Simon Willison used GPT-5.5 + Codex to rapidly develop the datasette-referrer-policy plugin to solve the problem
- Choosing to develop a plugin rather than changing the default reflects respect for existing users' security expectations
- This case demonstrates the high efficiency of AI-assisted programming in scenarios with clear requirements and mature frameworks
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.