<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: service-workers</title><link href="http://feeds.simonwillison.net/" rel="alternate"/><link href="http://feeds.simonwillison.net/tags/service-workers.atom" rel="self"/><id>http://feeds.simonwillison.net/</id><updated>2026-05-30T21:02:16+00:00</updated><author><name>Simon Willison</name></author><entry><title>Running Python ASGI apps in the browser via Pyodide + a service worker</title><link href="https://simonwillison.net/2026/May/30/pyodide-asgi-browser/#atom-tag" rel="alternate"/><published>2026-05-30T21:02:16+00:00</published><updated>2026-05-30T21:02:16+00:00</updated><id>https://simonwillison.net/2026/May/30/pyodide-asgi-browser/#atom-tag</id><summary type="html">
    
        &lt;p&gt;&lt;strong&gt;Research:&lt;/strong&gt; &lt;a href="https://github.com/simonw/research/tree/main/pyodide-asgi-browser#readme"&gt;Running Python ASGI apps in the browser via Pyodide + a service worker&lt;/a&gt;&lt;/p&gt;
        &lt;p&gt;&lt;a href="https://lite.datasette.io/"&gt;Datasette Lite&lt;/a&gt; is my version of Datasette that runs entirely in the browser using Pyodide in WebAssembly.&lt;/p&gt;
&lt;p&gt;When I first built it &lt;a href="https://simonwillison.net/2022/May/4/datasette-lite/"&gt;four years ago&lt;/a&gt; I used Web Workers and code that intercepts navigation operations and fetches the generated HTML by running the Python app.&lt;/p&gt;
&lt;p&gt;This worked, but had the disadvantage that any JavaScript in &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags would not be executed - breaking some Datasette functionality and a whole lot of Datasette plugins.&lt;/p&gt;
&lt;p&gt;This morning I &lt;a href="https://github.com/simonw/research/pull/112"&gt;set Claude Opus 4.8 the task&lt;/a&gt; (in Claude Code for web) of figuring out how to run Python ASGI apps in Pyodide using Service Workers instead, and it seems to work! Here's a &lt;a href="https://simonw.github.io/research/pyodide-asgi-browser/"&gt;basic ASGI FastCGI demo&lt;/a&gt; and here's &lt;a href="https://simonw.github.io/research/pyodide-asgi-browser/datasette.html"&gt;a demo that runs Datasette 1.0a31&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm still getting my head around exactly how it works, but once I've done that I plan to upgrade Datasette Lite itself.&lt;/p&gt;
    
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/datasette"&gt;datasette&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/asgi"&gt;asgi&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/service-workers"&gt;service-workers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pyodide"&gt;pyodide&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/datasette-lite"&gt;datasette-lite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-code"&gt;claude-code&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="javascript"/><category term="python"/><category term="datasette"/><category term="asgi"/><category term="service-workers"/><category term="pyodide"/><category term="datasette-lite"/><category term="claude-code"/></entry><entry><title>tiny-world-map</title><link href="https://simonwillison.net/2024/Apr/21/tiny-world-map/#atom-tag" rel="alternate"/><published>2024-04-21T22:11:14+00:00</published><updated>2024-04-21T22:11:14+00:00</updated><id>https://simonwillison.net/2024/Apr/21/tiny-world-map/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/tinyworldmap/tiny-world-map"&gt;tiny-world-map&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I love this project. It’s a JavaScript file (694K uncompressed, 283KB compressed) which can be used with the Leaflet mapping library and provides a SVG base map of the world with country borders and labels for every world city with a population more than 48,000—10,000 cities total.&lt;/p&gt;

&lt;p&gt;This means you can bundle an offline map of the world as part of any application that doesn’t need a higher level of detail. A lot of smaller island nations are missing entirely though, so this may not be right for every project.&lt;/p&gt;

&lt;p&gt;It even includes a service worker to help implement offline mapping support, plus several variants of the map with less cities that are even smaller.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=40104774"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/geospatial"&gt;geospatial&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mapping"&gt;mapping&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/svg"&gt;svg&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/service-workers"&gt;service-workers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/leaflet"&gt;leaflet&lt;/a&gt;&lt;/p&gt;



</summary><category term="geospatial"/><category term="javascript"/><category term="mapping"/><category term="svg"/><category term="service-workers"/><category term="leaflet"/></entry><entry><title>servefolder.dev</title><link href="https://simonwillison.net/2021/Dec/12/servefolder/#atom-tag" rel="alternate"/><published>2021-12-12T18:32:38+00:00</published><updated>2021-12-12T18:32:38+00:00</updated><id>https://simonwillison.net/2021/Dec/12/servefolder/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://servefolder.dev/"&gt;servefolder.dev&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Absurdly clever application of service workers and the file system API: you can select a folder from your computer and the contents of that folder will be served (just to you) from a path on this website—all without uploading any content. The code is on GitHub and offers a useful, succinct introduction to how to use those APIs.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://github.com/AshleyScirra/servefolder.dev"&gt;AshleyScirra/servefolder.dev&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/browsers"&gt;browsers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/service-workers"&gt;service-workers&lt;/a&gt;&lt;/p&gt;



</summary><category term="browsers"/><category term="javascript"/><category term="service-workers"/></entry><entry><title>Introducing Partytown 🎉: Run Third-Party Scripts From a Web Worker</title><link href="https://simonwillison.net/2021/Sep/23/partytown/#atom-tag" rel="alternate"/><published>2021-09-23T18:29:14+00:00</published><updated>2021-09-23T18:29:14+00:00</updated><id>https://simonwillison.net/2021/Sep/23/partytown/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://dev.to/adamdbradley/introducing-partytown-run-third-party-scripts-from-a-web-worker-2cnp"&gt;Introducing Partytown 🎉: Run Third-Party Scripts From a Web Worker&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
This is just spectacularly clever. Partytown is a 6KB JavaScript library that helps you move gnarly poorly performing third-party scripts out of your main page and into a web worker, so they won’t destroy your page performance. The really clever bit is in how it provides sandboxed access to the page DOM: it uses a devious trick where a proxy object provides getters and setters which then make blocking API calls to a separate service worker, using the mostly-forgotten xhr.open(..., false) parameter that turns off the async default for an XMLHttpRequest call.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/Rich_Harris/status/1441101927798820869"&gt;@Rich_Harris&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/async"&gt;async&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webworkers"&gt;webworkers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/service-workers"&gt;service-workers&lt;/a&gt;&lt;/p&gt;



</summary><category term="async"/><category term="javascript"/><category term="webworkers"/><category term="service-workers"/></entry><entry><title>Everyone can now run JavaScript on Cloudflare with Workers</title><link href="https://simonwillison.net/2018/Mar/13/javascript-on-cloudflare-with-workers/#atom-tag" rel="alternate"/><published>2018-03-13T16:36:53+00:00</published><updated>2018-03-13T16:36:53+00:00</updated><id>https://simonwillison.net/2018/Mar/13/javascript-on-cloudflare-with-workers/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://blog.cloudflare.com/cloudflare-workers-unleashed/amp/?__twitter_impression=true"&gt;Everyone can now run JavaScript on Cloudflare with Workers&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
This is such a brilliant piece of software design: Cloudflare took the service workers spec and used it as the basis for their edge-executed JacaScript feature. This means you can run server-side JavaScript in hundreds of edge locations worldwide, applying custom dynamic logic (including additional async cached fetch() calls) with only around 1ms if additional overhead. The pricing model is a steal: $0.50 per million requests with a $5/month minimum.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/cdn"&gt;cdn&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/cloudflare"&gt;cloudflare&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/service-workers"&gt;service-workers&lt;/a&gt;&lt;/p&gt;



</summary><category term="cdn"/><category term="javascript"/><category term="cloudflare"/><category term="service-workers"/></entry></feed>