<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: blogging</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/blogging.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2026-03-01T16:06:43+00:00</updated><author><name>Simon Willison</name></author><entry><title>My current policy on AI writing for my blog</title><link href="https://simonwillison.net/2026/Mar/1/ai-writing/#atom-tag" rel="alternate"/><published>2026-03-01T16:06:43+00:00</published><updated>2026-03-01T16:06:43+00:00</updated><id>https://simonwillison.net/2026/Mar/1/ai-writing/#atom-tag</id><summary type="html">
    &lt;p&gt;Because I write about LLMs (and maybe because of my &lt;a href="https://simonwillison.net/2026/Feb/15/em-dashes/"&gt;em dash text replacement code&lt;/a&gt;) a lot of people assume that the writing on my blog is partially or fully created by those LLMs.&lt;/p&gt;
&lt;p&gt;My current policy on this is that if text expresses opinions or has "I" pronouns attached to it then it's written by me. I don't let LLMs speak for me in this way.&lt;/p&gt;
&lt;p&gt;I'll let an LLM update code documentation or even write a README for my project but I'll edit that to ensure it doesn't express opinions or say things like "This is designed to help make code easier to maintain" - because that's an expression of a rationale that the LLM just made up.&lt;/p&gt;
&lt;p&gt;I use LLMs to proofread text I publish on my blog. I just shared &lt;a href="https://simonwillison.net/guides/agentic-engineering-patterns/prompts/#proofreader"&gt;my current prompt for that here&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/ai-ethics"&gt;ai-ethics&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/writing"&gt;writing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;&lt;/p&gt;



</summary><category term="ai-ethics"/><category term="writing"/><category term="generative-ai"/><category term="blogging"/><category term="ai"/><category term="llms"/></entry><entry><title>Writing about Agentic Engineering Patterns</title><link href="https://simonwillison.net/2026/Feb/23/agentic-engineering-patterns/#atom-tag" rel="alternate"/><published>2026-02-23T17:43:02+00:00</published><updated>2026-02-23T17:43:02+00:00</updated><id>https://simonwillison.net/2026/Feb/23/agentic-engineering-patterns/#atom-tag</id><summary type="html">
    &lt;p&gt;I've started a new project to collect and document &lt;strong&gt;&lt;a href="https://simonwillison.net/guides/agentic-engineering-patterns/"&gt;Agentic Engineering Patterns&lt;/a&gt;&lt;/strong&gt; - coding practices and patterns to help get the best results out of this new era of coding agent development we find ourselves entering.&lt;/p&gt;
&lt;p&gt;I'm using &lt;strong&gt;Agentic Engineering&lt;/strong&gt; to refer to building software using coding agents - tools like Claude Code and OpenAI Codex, where the defining feature is that they can both generate and &lt;em&gt;execute&lt;/em&gt; code - allowing them to test that code and iterate on it independently of turn-by-turn guidance from their human supervisor.&lt;/p&gt;
&lt;p&gt;I think of &lt;strong&gt;vibe coding&lt;/strong&gt; using its &lt;a href="https://simonwillison.net/2025/Mar/19/vibe-coding/"&gt;original definition&lt;/a&gt; of coding where you pay no attention to the code at all, which today is often associated with non-programmers using LLMs to write code.&lt;/p&gt;
&lt;p&gt;Agentic Engineering represents the other end of the scale: professional software engineers using coding agents to improve and accelerate their work by amplifying their existing expertise.&lt;/p&gt;
&lt;p&gt;There is so much to learn and explore about this new discipline! I've already published a lot &lt;a href="https://simonwillison.net/tags/ai-assisted-programming/"&gt;under my ai-assisted-programming tag&lt;/a&gt; (345 posts and counting) but that's been relatively unstructured. My new goal is to produce something that helps answer the question "how do I get good results out of this stuff" all in one place.&lt;/p&gt;
&lt;p&gt;I'll be developing and growing this project here on my blog as a series of chapter-shaped patterns, loosely inspired by the format popularized by &lt;a href="https://en.wikipedia.org/wiki/Design_Patterns"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt; back in 1994.&lt;/p&gt;
&lt;p&gt;I published the first two chapters today:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://simonwillison.net/guides/agentic-engineering-patterns/code-is-cheap/"&gt;Writing code is cheap now&lt;/a&gt;&lt;/strong&gt; talks about the central challenge of agentic engineering: the cost to churn out initial working code has dropped to almost nothing, how does that impact our existing intuitions about how we work, both individually and as a team?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://simonwillison.net/guides/agentic-engineering-patterns/red-green-tdd/"&gt;Red/green TDD&lt;/a&gt;&lt;/strong&gt; describes how test-first development helps agents write more succinct and reliable code with minimal extra prompting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope to add more chapters at a rate of 1-2 a week. I don't really know when I'll stop, there's a lot to cover!&lt;/p&gt;
&lt;h4 id="written-by-me-not-by-an-llm"&gt;Written by me, not by an LLM&lt;/h4&gt;
&lt;p&gt;I have a strong personal policy of not publishing AI-generated writing under my own name. That policy will hold true for Agentic Engineering Patterns as well. I'll be using LLMs for proofreading and fleshing out example code and all manner of other side-tasks, but the words you read here will be my own.&lt;/p&gt;
&lt;h4 id="chapters-and-guides"&gt;Chapters and Guides&lt;/h4&gt;
&lt;p&gt;Agentic Engineering Patterns isn't exactly &lt;em&gt;a book&lt;/em&gt;, but it's kind of book-shaped. I'll be publishing it on my site using a new shape of content I'm calling a &lt;em&gt;guide&lt;/em&gt;. A guide is a collection of chapters, where each chapter is effectively a blog post with a less prominent date that's designed to be updated over time, not frozen at the point of first publication.&lt;/p&gt;
&lt;p&gt;Guides and chapters are my answer to the challenge of publishing "evergreen" content on a blog. I've been trying to find a way to do this for a while now. This feels like a format that might stick.&lt;/p&gt;

&lt;p&gt;If you're interested in the implementation you can find the code in the &lt;a href="https://github.com/simonw/simonwillisonblog/blob/b9cd41a0ac4a232b2a6c90ca3fff9ae465263b02/blog/models.py#L262-L280"&gt;Guide&lt;/a&gt;, &lt;a href="https://github.com/simonw/simonwillisonblog/blob/b9cd41a0ac4a232b2a6c90ca3fff9ae465263b02/blog/models.py#L349-L405"&gt;Chapter&lt;/a&gt; and &lt;a href="https://github.com/simonw/simonwillisonblog/blob/b9cd41a0ac4a232b2a6c90ca3fff9ae465263b02/blog/models.py#L408-L423"&gt;ChapterChange&lt;/a&gt; models and the &lt;a href="https://github.com/simonw/simonwillisonblog/blob/b9cd41a0ac4a232b2a6c90ca3fff9ae465263b02/blog/views.py#L775-L923"&gt;associated Django views&lt;/a&gt;, almost all of which was written by Claude Opus 4.6 running in Claude Code for web accessed via my iPhone.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/design-patterns"&gt;design-patterns&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/projects"&gt;projects&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/writing"&gt;writing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/vibe-coding"&gt;vibe-coding&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/coding-agents"&gt;coding-agents&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/agentic-engineering"&gt;agentic-engineering&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="blogging"/><category term="design-patterns"/><category term="projects"/><category term="writing"/><category term="ai"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="vibe-coding"/><category term="coding-agents"/><category term="agentic-engineering"/></entry><entry><title>Adding TILs, releases, museums, tools and research to my blog</title><link href="https://simonwillison.net/2026/Feb/20/beats/#atom-tag" rel="alternate"/><published>2026-02-20T23:47:10+00:00</published><updated>2026-02-20T23:47:10+00:00</updated><id>https://simonwillison.net/2026/Feb/20/beats/#atom-tag</id><summary type="html">
    &lt;p&gt;I've been wanting to add indications of my various other online activities to my blog for a while now. I just turned on a new feature I'm calling "beats" (after story beats, naming this was hard!) which adds five new types of content to my site, all corresponding to activity elsewhere.&lt;/p&gt;
&lt;p&gt;Here's what beats look like:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2026/three-beats.jpg" alt="Screenshot of a fragment of a page showing three entries from 30th Dec 2025. First: [RELEASE] &amp;quot;datasette-turnstile 0.1a0 — Configurable CAPTCHAs for Datasette paths usin…&amp;quot; at 7:23 pm. Second: [TOOL] &amp;quot;Software Heritage Repository Retriever — Download archived Git repositories f…&amp;quot; at 11:41 pm. Third: [TIL] &amp;quot;Downloading archived Git repositories from archive.softwareheritage.org — …&amp;quot; at 11:43 pm." style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;p&gt;Those three are from &lt;a href="https://simonwillison.net/2025/Dec/30/"&gt;the 30th December 2025&lt;/a&gt; archive page.&lt;/p&gt;
&lt;p&gt;Beats are little inline links with badges that fit into different content timeline views around my site, including the homepage, search and archive pages.&lt;/p&gt;
&lt;p&gt;There are currently five types of beats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/elsewhere/release/"&gt;Releases&lt;/a&gt; are GitHub releases of my many different open source projects, imported from &lt;a href="https://github.com/simonw/simonw/blob/main/releases_cache.json"&gt;this JSON file&lt;/a&gt; that was constructed &lt;a href="https://simonwillison.net/2020/Jul/10/self-updating-profile-readme/"&gt;by GitHub Actions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/elsewhere/til/"&gt;TILs&lt;/a&gt; are the posts from my &lt;a href="https://til.simonwillison.net/"&gt;TIL blog&lt;/a&gt;, imported using &lt;a href="https://github.com/simonw/simonwillisonblog/blob/f883b92be23892d082de39dbada571e406f5cfbf/blog/views.py#L1169"&gt;a SQL query over JSON and HTTP&lt;/a&gt; against the Datasette instance powering that site.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/elsewhere/museum/"&gt;Museums&lt;/a&gt; are new posts on my &lt;a href="https://www.niche-museums.com/"&gt;niche-museums.com&lt;/a&gt; blog, imported from &lt;a href="https://github.com/simonw/museums/blob/909bef71cc8d336bf4ac1f13574db67a6e1b3166/plugins/export.py"&gt;this custom JSON feed&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/elsewhere/tool/"&gt;Tools&lt;/a&gt; are HTML and JavaScript tools I've vibe-coded on my &lt;a href="https://tools.simonwillison.net/"&gt;tools.simonwillison.net&lt;/a&gt; site, as described in &lt;a href="https://simonwillison.net/2025/Dec/10/html-tools/"&gt;Useful patterns for building HTML tools&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simonwillison.net/elsewhere/research/"&gt;Research&lt;/a&gt; is for AI-generated research projects, hosted in my &lt;a href="https://github.com/simonw/research"&gt;simonw/research repo&lt;/a&gt; and described in &lt;a href="https://simonwillison.net/2025/Nov/6/async-code-research/"&gt;Code research projects with async coding agents like Claude Code and Codex&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's five different custom integrations to pull in all of that data. The good news is that this kind of integration project is the kind of thing that coding agents &lt;em&gt;really&lt;/em&gt; excel at. I knocked most of the feature out in a single morning while working in parallel on various other things.&lt;/p&gt;
&lt;p&gt;I didn't have a useful structured feed of my Research projects, and it didn't matter because I gave Claude Code a link to &lt;a href="https://raw.githubusercontent.com/simonw/research/refs/heads/main/README.md"&gt;the raw Markdown README&lt;/a&gt; that lists them all and it &lt;a href="https://github.com/simonw/simonwillisonblog/blob/f883b92be23892d082de39dbada571e406f5cfbf/blog/importers.py#L77-L80"&gt;spun up a parser regex&lt;/a&gt;. Since I'm responsible for both the source and the destination I'm fine with a brittle solution that would be too risky against a source that I don't control myself.&lt;/p&gt;
&lt;p&gt;Claude also handled all of the potentially tedious UI integration work with my site, making sure the new content worked on all of my different page types and was handled correctly by my &lt;a href="https://simonwillison.net/2017/Oct/5/django-postgresql-faceted-search/"&gt;faceted search engine&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="prototyping-with-claude-artifacts"&gt;Prototyping with Claude Artifacts&lt;/h4&gt;
&lt;p&gt;I actually prototyped the initial concept for beats in regular Claude - not Claude Code - taking advantage of the fact that it can clone public repos from GitHub these days. I started with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Clone simonw/simonwillisonblog and tell me about the models and views&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And then later in the brainstorming session said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;use the templates and CSS in this repo to create a new artifact with all HTML and CSS inline that shows me my homepage with some of those inline content types mixed in&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After some iteration we got to &lt;a href="https://gisthost.github.io/?c3f443cc4451cf8ce03a2715a43581a4/preview.html"&gt;this artifact mockup&lt;/a&gt;, which was enough to convince me that the concept had legs and was worth handing over to full &lt;a href="https://code.claude.com/docs/en/claude-code-on-the-web"&gt;Claude Code for web&lt;/a&gt; to implement.&lt;/p&gt;
&lt;p&gt;If you want to see how the rest of the build played out the most interesting PRs are &lt;a href="https://github.com/simonw/simonwillisonblog/pull/592"&gt;Beats #592&lt;/a&gt; which implemented the core feature and &lt;a href="https://github.com/simonw/simonwillisonblog/pull/595/changes"&gt;Add Museums Beat importer #595&lt;/a&gt; which added the Museums content type.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/museums"&gt;museums&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/til"&gt;til&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-artifacts"&gt;claude-artifacts&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude-code"&gt;claude-code&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="blogging"/><category term="museums"/><category term="ai"/><category term="til"/><category term="generative-ai"/><category term="llms"/><category term="ai-assisted-programming"/><category term="claude-artifacts"/><category term="claude-code"/></entry><entry><title>Experimenting with sponsorship for my blog and newsletter</title><link href="https://simonwillison.net/2026/Feb/19/sponsorship/#atom-tag" rel="alternate"/><published>2026-02-19T05:44:29+00:00</published><updated>2026-02-19T05:44:29+00:00</updated><id>https://simonwillison.net/2026/Feb/19/sponsorship/#atom-tag</id><summary type="html">
    &lt;p&gt;I've long been resistant to the idea of accepting sponsorship for my blog. I value my credibility as an independent voice, and I don't want to risk compromising that reputation.&lt;/p&gt;
&lt;p&gt;Then I learned about Troy Hunt's &lt;a href="https://www.troyhunt.com/sponsorship/"&gt;approach to sponsorship&lt;/a&gt;, which he first wrote about &lt;a href="https://www.troyhunt.com/im-now-offering-sponsorship-of-this-blog/"&gt;in 2016&lt;/a&gt;. Troy runs with a simple text row in the page banner - no JavaScript, no cookies, unobtrusive while providing value to the sponsor. I can live with that!&lt;/p&gt;
&lt;p&gt;Accepting sponsorship in this way helps me maintain my independence while offsetting the opportunity cost of not taking a full-time job.&lt;/p&gt;
&lt;p&gt;To start with I'm selling sponsorship by the week. Sponsors get that unobtrusive banner across my blog and also their sponsored message at the top of &lt;a href="https://simonw.substack.com/"&gt;my newsletter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of my blog's homepage. Below the Simon Willison's Weblog heading and list of tags is a new blue page-wide banner reading &amp;quot;Sponsored by: Teleport - Secure, Govern, and Operate Al at Engineering Scale. Learn more&amp;quot;." src="https://static.simonwillison.net/static/2026/sponsor-banner.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;I &lt;strong&gt;will not write content in exchange for sponsorship&lt;/strong&gt;. I hope the sponsors I work with understand that my credibility as an independent voice is a key reason I have an audience, and compromising that trust would be bad for everyone.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.freemanandforrest.com/"&gt;Freeman &amp;amp; Forrest&lt;/a&gt; helped me set up and sell my first slots. Thanks also to &lt;a href="https://t3.gg/"&gt;Theo Browne&lt;/a&gt; for helping me think through my approach.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/newsletter"&gt;newsletter&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/troy-hunt"&gt;troy-hunt&lt;/a&gt;&lt;/p&gt;



</summary><category term="newsletter"/><category term="blogging"/><category term="troy-hunt"/></entry><entry><title>Em dash</title><link href="https://simonwillison.net/2026/Feb/15/em-dashes/#atom-tag" rel="alternate"/><published>2026-02-15T21:40:46+00:00</published><updated>2026-02-15T21:40:46+00:00</updated><id>https://simonwillison.net/2026/Feb/15/em-dashes/#atom-tag</id><summary type="html">
    &lt;p&gt;I'm occasionally accused of using LLMs to write the content on my blog. I don't do that, and I don't think my writing has much of an LLM smell to it... with one notable exception:&lt;/p&gt;
&lt;pre&gt;    &lt;span class="pl-c"&gt;# Finally, do em dashes&lt;/span&gt;
    &lt;span class="pl-s1"&gt;s&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;s&lt;/span&gt;.&lt;span class="pl-c1"&gt;replace&lt;/span&gt;(&lt;span class="pl-s"&gt;' - '&lt;/span&gt;, &lt;span class="pl-s"&gt;u'&lt;span class="pl-cce"&gt;\u2014&lt;/span&gt;'&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;That code to add em dashes to my posts dates back to &lt;a href="https://github.com/simonw/simonwillisonblog/blob/e6d0327b37debdf820b5cfef4fb7d09a9624cea9/blog/templatetags/entry_tags.py#L145-L146"&gt;at least 2015&lt;/a&gt; when I ported my blog from an older version of Django (in a long-lost Mercurial repository) and started afresh on GitHub.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/typography"&gt;typography&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="generative-ai"/><category term="typography"/><category term="blogging"/><category term="ai"/><category term="llms"/><category term="python"/></entry><entry><title>How I automate my Substack newsletter with content from my blog</title><link href="https://simonwillison.net/2025/Nov/19/how-i-automate-my-substack-newsletter/#atom-tag" rel="alternate"/><published>2025-11-19T22:00:34+00:00</published><updated>2025-11-19T22:00:34+00:00</updated><id>https://simonwillison.net/2025/Nov/19/how-i-automate-my-substack-newsletter/#atom-tag</id><summary type="html">
    &lt;p&gt;I sent out &lt;a href="https://simonw.substack.com/p/trying-out-gemini-3-pro-with-audio"&gt;my weekly-ish Substack newsletter&lt;/a&gt; this morning and took the opportunity to record &lt;a href="https://www.youtube.com/watch?v=BoPZltKDM-s"&gt;a YouTube video&lt;/a&gt; demonstrating my process and describing the different components that make it work. There's a &lt;em&gt;lot&lt;/em&gt; of digital duct tape involved, taking the content from Django+Heroku+PostgreSQL to GitHub Actions to SQLite+Datasette+Fly.io to JavaScript+Observable and finally to Substack.&lt;/p&gt;

&lt;p&gt;&lt;lite-youtube videoid="BoPZltKDM-s" js-api="js-api"
  title="How I automate my Substack newsletter with content from my blog"
  playlabel="Play: How I automate my Substack newsletter with content from my blog"
&gt; &lt;/lite-youtube&gt;&lt;/p&gt;

&lt;p&gt;The core process is the same as I described &lt;a href="https://simonwillison.net/2023/Apr/4/substack-observable/"&gt;back in 2023&lt;/a&gt;. I have an Observable notebook called &lt;a href="https://observablehq.com/@simonw/blog-to-newsletter"&gt;blog-to-newsletter&lt;/a&gt; which fetches content from my blog's database, filters out anything that has been in the newsletter before, formats what's left as HTML and offers a big "Copy rich text newsletter to clipboard" button.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2025/copy-to-newsletter.jpg" alt="Screenshot of the interface. An item in a list says 9080: Trying out Gemini 3 Pro with audio transcription and a new pelican benchmark. A huge button reads Copy rich text newsletter to clipboard - below is a smaller button that says Copy just the links/quotes/TILs. A Last X days slider is set to 2. There are checkboxes for SKip content sent in prior newsletters and only include post content prior to the cutoff comment." style="max-width: 100%;" /&gt;&lt;/p&gt;
&lt;p&gt;I click that button, paste the result into the Substack editor, tweak a few things and hit send. The whole process usually takes just a few minutes.&lt;/p&gt;
&lt;p&gt;I make very minor edits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I set the title and the subheading for the newsletter. This is often a direct copy of the title of the featured blog post.&lt;/li&gt;
&lt;li&gt;Substack turns YouTube URLs into embeds, which often isn't what I want - especially if I have a YouTube URL inside a code example.&lt;/li&gt;
&lt;li&gt;Blocks of preformatted text often have an extra blank line at the end, which I remove.&lt;/li&gt;
&lt;li&gt;Occasionally I'll make a content edit - removing a piece of content that doesn't fit the newsletter, or fixing a time reference like "yesterday" that doesn't make sense any more.&lt;/li&gt;
&lt;li&gt;I pick the featured image for the newsletter and add some tags.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's the whole process!&lt;/p&gt;
&lt;h4 id="the-observable-notebook"&gt;The Observable notebook&lt;/h4&gt;
&lt;p&gt;The most important cell in the Observable notebook is this one:&lt;/p&gt;
&lt;div class="highlight highlight-source-js"&gt;&lt;pre&gt;&lt;span class="pl-s1"&gt;raw_content&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;return&lt;/span&gt; &lt;span class="pl-s1"&gt;await&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;
    &lt;span class="pl-k"&gt;await&lt;/span&gt; &lt;span class="pl-en"&gt;fetch&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;
      &lt;span class="pl-s"&gt;`https://datasette.simonwillison.net/simonwillisonblog.json?sql=&lt;span class="pl-s1"&gt;&lt;span class="pl-kos"&gt;${&lt;/span&gt;&lt;span class="pl-en"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;span class="pl-s1"&gt;        &lt;span class="pl-s1"&gt;sql&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;&lt;span class="pl-s1"&gt;      &lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/span&gt;&amp;amp;_shape=array&amp;amp;numdays=&lt;span class="pl-s1"&gt;&lt;span class="pl-kos"&gt;${&lt;/span&gt;&lt;span class="pl-s1"&gt;numDays&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/span&gt;`&lt;/span&gt;
    &lt;span class="pl-kos"&gt;)&lt;/span&gt;
  &lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;json&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This uses the JavaScript &lt;code&gt;fetch()&lt;/code&gt; function to pull data from my blog's Datasette instance, using a very complex SQL query that is composed elsewhere in the notebook.&lt;/p&gt;
&lt;p&gt;Here's a link to &lt;a href="https://datasette.simonwillison.net/simonwillisonblog?sql=with+content+as+%28%0D%0A++select%0D%0A++++id%2C%0D%0A++++%27entry%27+as+type%2C%0D%0A++++title%2C%0D%0A++++created%2C%0D%0A++++slug%2C%0D%0A++++%27%3Ch3%3E%3Ca+href%3D%22%27+%7C%7C+%27https%3A%2F%2Fsimonwillison.net%2F%27+%7C%7C+strftime%28%27%25Y%2F%27%2C+created%29%0D%0A++++++%7C%7C+substr%28%27JanFebMarAprMayJunJulAugSepOctNovDec%27%2C+%28strftime%28%27%25m%27%2C+created%29+-+1%29+*+3+%2B+1%2C+3%29+%0D%0A++++++%7C%7C+%27%2F%27+%7C%7C+cast%28strftime%28%27%25d%27%2C+created%29+as+integer%29+%7C%7C+%27%2F%27+%7C%7C+slug+%7C%7C+%27%2F%27+%7C%7C+%27%22%3E%27+%0D%0A++++++%7C%7C+title+%7C%7C+%27%3C%2Fa%3E+-+%27+%7C%7C+date%28created%29+%7C%7C+%27%3C%2Fh3%3E%27+%7C%7C+body%0D%0A++++++as+html%2C%0D%0A++++%27null%27+as+json%2C%0D%0A++++%27%27+as+external_url%0D%0A++from+blog_entry%0D%0A++union+all%0D%0A++select%0D%0A++++id%2C%0D%0A++++%27blogmark%27+as+type%2C%0D%0A++++link_title%2C%0D%0A++++created%2C%0D%0A++++slug%2C%0D%0A++++%27%3Cp%3E%3Cstrong%3ELink%3C%2Fstrong%3E+%27+%7C%7C+date%28created%29+%7C%7C+%27+%3Ca+href%3D%22%27%7C%7C+link_url+%7C%7C+%27%22%3E%27%0D%0A++++++%7C%7C+link_title+%7C%7C+%27%3C%2Fa%3E%3A%3C%2Fp%3E%3Cp%3E%27+%7C%7C+%27+%27+%7C%7C+replace%28commentary%2C+%27%0D%0A%27%2C+%27%3Cbr%3E%27%29+%7C%7C+%27%3C%2Fp%3E%27%0D%0A++++++as+html%2C%0D%0A++++json_object%28%0D%0A++++++%27created%27%2C+date%28created%29%2C%0D%0A++++++%27link_url%27%2C+link_url%2C%0D%0A++++++%27link_title%27%2C+link_title%2C%0D%0A++++++%27commentary%27%2C+commentary%2C%0D%0A++++++%27use_markdown%27%2C+use_markdown%0D%0A++++%29+as+json%2C%0D%0A++link_url+as+external_url%0D%0A++from+blog_blogmark%0D%0A++union+all%0D%0A++select%0D%0A++++id%2C%0D%0A++++%27quotation%27+as+type%2C%0D%0A++++source%2C%0D%0A++++created%2C%0D%0A++++slug%2C%0D%0A++++%27%3Cstrong%3Equote%3C%2Fstrong%3E+%27+%7C%7C+date%28created%29+%7C%7C%0D%0A++++%27%3Cblockquote%3E%3Cp%3E%3Cem%3E%27+%7C%7C%0D%0A++++replace%28quotation%2C+%27%0D%0A%27%2C+%27%3Cbr%3E%27%29+%7C%7C+%0D%0A++++%27%3C%2Fem%3E%3C%2Fp%3E%3C%2Fblockquote%3E%3Cp%3E%3Ca+href%3D%22%27+%7C%7C%0D%0A++++coalesce%28source_url%2C+%27%23%27%29+%7C%7C+%27%22%3E%27+%7C%7C+source+%7C%7C+%27%3C%2Fa%3E%27+%7C%7C%0D%0A++++case+%0D%0A++++++++when+nullif%28trim%28context%29%2C+%27%27%29+is+not+null+%0D%0A++++++++then+%27%2C+%27+%7C%7C+context+%0D%0A++++++++else+%27%27+%0D%0A++++end+%7C%7C%0D%0A++++%27%3C%2Fp%3E%27+as+html%2C%0D%0A++++%27null%27+as+json%2C%0D%0A++++source_url+as+external_url%0D%0A++from+blog_quotation%0D%0A++union+all%0D%0A++select%0D%0A++++id%2C%0D%0A++++%27note%27+as+type%2C%0D%0A++++case%0D%0A++++++when+title+is+not+null+and+title+%3C%3E+%27%27+then+title%0D%0A++++++else+%27Note+on+%27+%7C%7C+date%28created%29%0D%0A++++end%2C%0D%0A++++created%2C%0D%0A++++slug%2C%0D%0A++++%27No+HTML%27%2C%0D%0A++++json_object%28%0D%0A++++++%27created%27%2C+date%28created%29%2C%0D%0A++++++%27link_url%27%2C+%27https%3A%2F%2Fsimonwillison.net%2F%27+%7C%7C+strftime%28%27%25Y%2F%27%2C+created%29%0D%0A++++++%7C%7C+substr%28%27JanFebMarAprMayJunJulAugSepOctNovDec%27%2C+%28strftime%28%27%25m%27%2C+created%29+-+1%29+*+3+%2B+1%2C+3%29+%0D%0A++++++%7C%7C+%27%2F%27+%7C%7C+cast%28strftime%28%27%25d%27%2C+created%29+as+integer%29+%7C%7C+%27%2F%27+%7C%7C+slug+%7C%7C+%27%2F%27%2C%0D%0A++++++%27link_title%27%2C+%27%27%2C%0D%0A++++++%27commentary%27%2C+body%2C%0D%0A++++++%27use_markdown%27%2C+1%0D%0A++++%29%2C%0D%0A++++%27%27+as+external_url%0D%0A++from+blog_note%0D%0A++union+all%0D%0A++select%0D%0A++++rowid%2C%0D%0A++++%27til%27+as+type%2C%0D%0A++++title%2C%0D%0A++++created%2C%0D%0A++++%27null%27+as+slug%2C%0D%0A++++%27%3Cp%3E%3Cstrong%3ETIL%3C%2Fstrong%3E+%27+%7C%7C+date%28created%29+%7C%7C+%27+%3Ca+href%3D%22%27%7C%7C+%27https%3A%2F%2Ftil.simonwillison.net%2F%27+%7C%7C+topic+%7C%7C+%27%2F%27+%7C%7C+slug+%7C%7C+%27%22%3E%27+%7C%7C+title+%7C%7C+%27%3C%2Fa%3E%3A%27+%7C%7C+%27+%27+%7C%7C+substr%28html%2C+1%2C+instr%28html%2C+%27%3C%2Fp%3E%27%29+-+1%29+%7C%7C+%27+%26%238230%3B%3C%2Fp%3E%27+as+html%2C%0D%0A++++%27null%27+as+json%2C%0D%0A++++%27https%3A%2F%2Ftil.simonwillison.net%2F%27+%7C%7C+topic+%7C%7C+%27%2F%27+%7C%7C+slug+as+external_url%0D%0A++from+til%0D%0A%29%2C%0D%0Acollected+as+%28%0D%0A++select%0D%0A++++id%2C%0D%0A++++type%2C%0D%0A++++title%2C%0D%0A++++case%0D%0A++++++when+type+%3D+%27til%27%0D%0A++++++then+external_url%0D%0A++++++else+%27https%3A%2F%2Fsimonwillison.net%2F%27+%7C%7C+strftime%28%27%25Y%2F%27%2C+created%29%0D%0A++++++%7C%7C+substr%28%27JanFebMarAprMayJunJulAugSepOctNovDec%27%2C+%28strftime%28%27%25m%27%2C+created%29+-+1%29+*+3+%2B+1%2C+3%29+%7C%7C+%0D%0A++++++%27%2F%27+%7C%7C+cast%28strftime%28%27%25d%27%2C+created%29+as+integer%29+%7C%7C+%27%2F%27+%7C%7C+slug+%7C%7C+%27%2F%27%0D%0A++++++end+as+url%2C%0D%0A++++created%2C%0D%0A++++html%2C%0D%0A++++json%2C%0D%0A++++external_url%2C%0D%0A++++case%0D%0A++++++when+type+%3D+%27entry%27+then+%28%0D%0A++++++++select+json_group_array%28tag%29%0D%0A++++++++from+blog_tag%0D%0A++++++++join+blog_entry_tags+on+blog_tag.id+%3D+blog_entry_tags.tag_id%0D%0A++++++++where+blog_entry_tags.entry_id+%3D+content.id%0D%0A++++++%29%0D%0A++++++when+type+%3D+%27blogmark%27+then+%28%0D%0A++++++++select+json_group_array%28tag%29%0D%0A++++++++from+blog_tag%0D%0A++++++++join+blog_blogmark_tags+on+blog_tag.id+%3D+blog_blogmark_tags.tag_id%0D%0A++++++++where+blog_blogmark_tags.blogmark_id+%3D+content.id%0D%0A++++++%29%0D%0A++++++when+type+%3D+%27quotation%27+then+%28%0D%0A++++++++select+json_group_array%28tag%29%0D%0A++++++++from+blog_tag%0D%0A++++++++join+blog_quotation_tags+on+blog_tag.id+%3D+blog_quotation_tags.tag_id%0D%0A++++++++where+blog_quotation_tags.quotation_id+%3D+content.id%0D%0A++++++%29%0D%0A++++++else+%27%5B%5D%27%0D%0A++++end+as+tags%0D%0A++from+content%0D%0A++where+created+%3E%3D+date%28%27now%27%2C+%27-%27+%7C%7C+%3Anumdays+%7C%7C+%27+days%27%29+++%0D%0A++order+by+created+desc%0D%0A%29%0D%0Aselect+id%2C+type%2C+title%2C+url%2C+created%2C+html%2C+json%2C+external_url%2C+tags%0D%0Afrom+collected+%0D%0Aorder+by+%0D%0A++case+type+%0D%0A++++when+%27entry%27+then+0+%0D%0A++++else+1+%0D%0A++end%2C%0D%0A++case+type+%0D%0A++++when+%27entry%27+then+created+%0D%0A++++else+-strftime%28%27%25s%27%2C+created%29+%0D%0A++end+desc%3B&amp;amp;numdays=7"&gt;see and execute that query&lt;/a&gt; directly in Datasette. It's 143 lines of convoluted SQL that assembles most of the HTML for the newsletter using SQLite string concatenation! An illustrative snippet:&lt;/p&gt;
&lt;div class="highlight highlight-source-sql"&gt;&lt;pre&gt;with content &lt;span class="pl-k"&gt;as&lt;/span&gt; (
  &lt;span class="pl-k"&gt;select&lt;/span&gt;
    id,
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;entry&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;as&lt;/span&gt; type,
    title,
    created,
    slug,
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&amp;lt;h3&amp;gt;&amp;lt;a href="&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;||&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;https://simonwillison.net/&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;||&lt;/span&gt; strftime(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;%Y/&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;, created)
      &lt;span class="pl-k"&gt;||&lt;/span&gt; substr(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;JanFebMarAprMayJunJulAugSepOctNovDec&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;, (strftime(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;%m&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;, created) &lt;span class="pl-k"&gt;-&lt;/span&gt; &lt;span class="pl-c1"&gt;1&lt;/span&gt;) &lt;span class="pl-k"&gt;*&lt;/span&gt; &lt;span class="pl-c1"&gt;3&lt;/span&gt; &lt;span class="pl-k"&gt;+&lt;/span&gt; &lt;span class="pl-c1"&gt;1&lt;/span&gt;, &lt;span class="pl-c1"&gt;3&lt;/span&gt;) 
      &lt;span class="pl-k"&gt;||&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;/&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;||&lt;/span&gt; cast(strftime(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;%d&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;, created) &lt;span class="pl-k"&gt;as&lt;/span&gt; &lt;span class="pl-k"&gt;integer&lt;/span&gt;) &lt;span class="pl-k"&gt;||&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;/&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;||&lt;/span&gt; slug &lt;span class="pl-k"&gt;||&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;/&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;||&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;"&amp;gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; 
      &lt;span class="pl-k"&gt;||&lt;/span&gt; title &lt;span class="pl-k"&gt;||&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&amp;lt;/a&amp;gt; - &lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;||&lt;/span&gt; &lt;span class="pl-k"&gt;date&lt;/span&gt;(created) &lt;span class="pl-k"&gt;||&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&amp;lt;/h3&amp;gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;||&lt;/span&gt; body
      &lt;span class="pl-k"&gt;as&lt;/span&gt; html,
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;null&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;as&lt;/span&gt; json,
    &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;as&lt;/span&gt; external_url
  &lt;span class="pl-k"&gt;from&lt;/span&gt; blog_entry
  &lt;span class="pl-k"&gt;union all&lt;/span&gt;
  &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; ...&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;My blog's URLs look like &lt;code&gt;/2025/Nov/18/gemini-3/&lt;/code&gt; - this SQL constructs that three letter month abbreviation from the month number using a substring operation.&lt;/p&gt;
&lt;p&gt;This is a &lt;em&gt;terrible&lt;/em&gt; way to assemble HTML, but I've stuck with it because it amuses me.&lt;/p&gt;
&lt;p&gt;The rest of the Observable notebook takes that data, filters out anything that links to content mentioned in the previous newsletters and composes it into a block of HTML that can be copied using that big button.&lt;/p&gt;
&lt;p&gt;Here's the recipe it uses to turn HTML into rich text content on a clipboard suitable for Substack. I can't remember how I figured this out but it's very effective:&lt;/p&gt;
&lt;div class="highlight highlight-source-js"&gt;&lt;pre&gt;&lt;span class="pl-v"&gt;Object&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;assign&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;
  &lt;span class="pl-en"&gt;html&lt;/span&gt;&lt;span class="pl-s"&gt;`&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;button&lt;/span&gt; &lt;span class="pl-c1"&gt;style&lt;/span&gt;="&lt;span class="pl-s"&gt;font-size: 1.4em; padding: 0.3em 1em; font-weight: bold;&lt;/span&gt;"&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;Copy rich text newsletter to clipboard`&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    &lt;span class="pl-en"&gt;onclick&lt;/span&gt;: &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
      &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;htmlContent&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;newsletterHTML&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-c"&gt;// Create a temporary element to hold the HTML content&lt;/span&gt;
      &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;tempElement&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-smi"&gt;document&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;createElement&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;"div"&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-s1"&gt;tempElement&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;innerHTML&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;htmlContent&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-smi"&gt;document&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;body&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;appendChild&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;tempElement&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-c"&gt;// Select the HTML content&lt;/span&gt;
      &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;range&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-smi"&gt;document&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;createRange&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-s1"&gt;range&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;selectNode&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;tempElement&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-c"&gt;// Copy the selected HTML content to the clipboard&lt;/span&gt;
      &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;selection&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-smi"&gt;window&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;getSelection&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-s1"&gt;selection&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;removeAllRanges&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-s1"&gt;selection&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;addRange&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;range&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-smi"&gt;document&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;execCommand&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;"copy"&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-s1"&gt;selection&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;removeAllRanges&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
      &lt;span class="pl-smi"&gt;document&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;body&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;removeChild&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;tempElement&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
    &lt;span class="pl-kos"&gt;}&lt;/span&gt;
  &lt;span class="pl-kos"&gt;}&lt;/span&gt;
&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="from-django-postgresql-to-datasette-sqlite"&gt;From Django+Postgresql to Datasette+SQLite&lt;/h4&gt;
&lt;p&gt;My blog itself is a Django application hosted on Heroku, with data stored in Heroku PostgreSQL. Here's &lt;a href="https://github.com/simonw/simonwillisonblog"&gt;the source code for that Django application&lt;/a&gt;. I use the Django admin as my CMS.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://datasette.io/"&gt;Datasette&lt;/a&gt; provides a JSON API over a SQLite database... which means something needs to convert that PostgreSQL database into a SQLite database that Datasette can use.&lt;/p&gt;
&lt;p&gt;My system for doing that lives in the &lt;a href="https://github.com/simonw/simonwillisonblog-backup"&gt;simonw/simonwillisonblog-backup&lt;/a&gt; GitHub repository. It uses GitHub Actions on a schedule that executes every two hours, fetching the latest data from PostgreSQL and converting that to SQLite.&lt;/p&gt;
&lt;p&gt;My &lt;a href="https://github.com/simonw/db-to-sqlite"&gt;db-to-sqlite&lt;/a&gt; tool is responsible for that conversion. I call it &lt;a href="https://github.com/simonw/simonwillisonblog-backup/blob/dc5b9df272134ce051a5280b4de6d4daa9b2a9fc/.github/workflows/backup.yml#L44-L62"&gt;like this&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;db-to-sqlite \
  &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;$(&lt;/span&gt;heroku config:get DATABASE_URL -a simonwillisonblog &lt;span class="pl-k"&gt;|&lt;/span&gt; sed s/postgres:/postgresql+psycopg2:/&lt;span class="pl-pds"&gt;)&lt;/span&gt;&lt;/span&gt; \
  simonwillisonblog.db \
  --table auth_permission \
  --table auth_user \
  --table blog_blogmark \
  --table blog_blogmark_tags \
  --table blog_entry \
  --table blog_entry_tags \
  --table blog_quotation \
  --table blog_quotation_tags \
  --table blog_note \
  --table blog_note_tags \
  --table blog_tag \
  --table blog_previoustagname \
  --table blog_series \
  --table django_content_type \
  --table redirects_redirect&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That &lt;code&gt;heroku config:get DATABASE_URL&lt;/code&gt; command uses Heroku credentials in an environment variable to fetch the database connection URL for my blog's PostgreSQL database (and fixes a small difference in the URL scheme).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;db-to-sqlite&lt;/code&gt; can then export that data and write it to a SQLite database file called &lt;code&gt;simonwillisonblog.db&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;--table&lt;/code&gt; options specify the tables that should be included in the export.&lt;/p&gt;
&lt;p&gt;The repository does more than just that conversion: it also exports the resulting data to JSON files that live in the repository, which gives me a &lt;a href="https://github.com/simonw/simonwillisonblog-backup/commits/main/simonwillisonblog"&gt;commit history&lt;/a&gt; of changes I make to my content. This is a cheap way to get a revision history of my blog content without having to mess around with detailed history tracking inside the Django application itself.&lt;/p&gt;
&lt;p&gt;At the &lt;a href="https://github.com/simonw/simonwillisonblog-backup/blob/dc5b9df272134ce051a5280b4de6d4daa9b2a9fc/.github/workflows/backup.yml#L200-L204"&gt;end of my GitHub Actions workflow&lt;/a&gt; is this code that publishes the resulting database to Datasette running on &lt;a href="https://fly.io/"&gt;Fly.io&lt;/a&gt; using the &lt;a href="https://datasette.io/plugins/datasette-publish-fly"&gt;datasette publish fly&lt;/a&gt; plugin:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;datasette publish fly simonwillisonblog.db \
  -m metadata.yml \
  --app simonwillisonblog-backup \
  --branch 1.0a2 \
  --extra-options &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;--setting sql_time_limit_ms 15000 --setting truncate_cells_html 10000 --setting allow_facet off&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; \
  --install datasette-block-robots \
  &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; ... more plugins&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, there are a lot of moving parts! Surprisingly it all mostly just works - I rarely have to intervene in the process, and the cost of those different components is pleasantly low.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/django"&gt;django&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/postgresql"&gt;postgresql&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sql"&gt;sql&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite"&gt;sqlite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/youtube"&gt;youtube&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/heroku"&gt;heroku&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/datasette"&gt;datasette&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/observable"&gt;observable&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/github-actions"&gt;github-actions&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/fly"&gt;fly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/newsletter"&gt;newsletter&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/substack"&gt;substack&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="blogging"/><category term="django"/><category term="javascript"/><category term="postgresql"/><category term="sql"/><category term="sqlite"/><category term="youtube"/><category term="heroku"/><category term="datasette"/><category term="observable"/><category term="github-actions"/><category term="fly"/><category term="newsletter"/><category term="substack"/></entry><entry><title>Curiosity-driven blogging</title><link href="https://simonwillison.net/2025/Oct/31/curiosity-driven/#atom-tag" rel="alternate"/><published>2025-10-31T17:09:56+00:00</published><updated>2025-10-31T17:09:56+00:00</updated><id>https://simonwillison.net/2025/Oct/31/curiosity-driven/#atom-tag</id><summary type="html">
    &lt;p&gt;My piece this morning &lt;a href="https://simonwillison.net/2025/Oct/31/coreweave-acquires-marimo/"&gt;about the Marimo acquisition&lt;/a&gt; is an example of a variant of a &lt;a href="https://til.simonwillison.net"&gt;TIL&lt;/a&gt; - I didn't know much about CoreWeave, the acquiring company, so I poked around to answer my own questions and then wrote up what I learned as a short post. Curiosity-driven blogging if you like.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/til"&gt;til&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;&lt;/p&gt;



</summary><category term="til"/><category term="blogging"/></entry><entry><title>The SIFT method</title><link href="https://simonwillison.net/2025/Sep/7/the-sift-method/#atom-tag" rel="alternate"/><published>2025-09-07T20:51:31+00:00</published><updated>2025-09-07T20:51:31+00:00</updated><id>https://simonwillison.net/2025/Sep/7/the-sift-method/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://guides.lib.uchicago.edu/c.php?g=1241077&amp;amp;p=9082322"&gt;The SIFT method&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
The SIFT method is "an evaluation strategy developed by digital literacy expert, Mike Caulfield, to help determine whether online content can be trusted for credible or reliable sources of information."&lt;/p&gt;
&lt;p&gt;This looks &lt;em&gt;extremely&lt;/em&gt; useful as a framework for helping people more effectively consume information online (increasingly gathered with &lt;a href="https://simonwillison.net/tags/ai-assisted-search/"&gt;the help of LLMs&lt;/a&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stop&lt;/strong&gt;. "Be aware of your emotional response to the headline or information in the article" to protect against clickbait, and don't read further or share until you've applied the other three steps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Investigate the Source&lt;/strong&gt;. Apply &lt;a href="https://pressbooks.pub/webliteracy/chapter/what-reading-laterally-means/"&gt;lateral reading&lt;/a&gt;, checking what others say about the source rather than just trusting their "about" page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Find Better Coverage&lt;/strong&gt;. "Use lateral reading to see if you can find other sources corroborating the same information or disputing it" and consult trusted fact checkers if necessary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trace Claims, Quotes, and Media to their Original Context&lt;/strong&gt;. Try to find the original report or referenced material to learn more and check it isn't being represented out of context.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This framework really resonates with me: it formally captures and improves on a bunch of informal techniques I've tried to apply in my own work.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://bsky.app/profile/anildash.com/post/3lyavuu6ku22r"&gt;@anildash.com&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/research"&gt;research&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-search"&gt;ai-assisted-search&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/digital-literacy"&gt;digital-literacy&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="research"/><category term="ai-assisted-search"/><category term="digital-literacy"/></entry><entry><title>New tags</title><link href="https://simonwillison.net/2025/Jul/19/new-tags/#atom-tag" rel="alternate"/><published>2025-07-19T02:02:54+00:00</published><updated>2025-07-19T02:02:54+00:00</updated><id>https://simonwillison.net/2025/Jul/19/new-tags/#atom-tag</id><summary type="html">
    &lt;p&gt;A few months ago I &lt;a href="https://github.com/simonw/simonwillisonblog/commit/12da4167396c2d54526bf690add14aebbb244148"&gt;added a tool&lt;/a&gt; to my blog for bulk-applying tags to old content. It works as an extension to my existing search interface, letting me run searches and then quickly apply a tag to relevant results.&lt;/p&gt;
&lt;p&gt;Since adding this I've been much more aggressive in categorizing my older content, including adding new tags when I spot an interesting trend that warrants its own page.&lt;/p&gt;
&lt;p&gt;Today I added &lt;a href="https://simonwillison.net/tags/system-prompts/"&gt;system-prompts&lt;/a&gt; and applied it to 41 existing posts that talk about system prompts for LLM systems, including a bunch that directly quote system prompts that have been deliberately published or leaked.&lt;/p&gt;
&lt;p&gt;Other tags I've added recently include &lt;a href="https://simonwillison.net/tags/press-quotes/"&gt;press-quotes&lt;/a&gt; for times I've been quoted in the press, &lt;a href="https://simonwillison.net/tags/agent-definitions/"&gt;agent-definitions&lt;/a&gt; for my ongoing collection of different ways people define "agents" and 
&lt;a href="https://simonwillison.net/tags/paper-review/"&gt;paper-review&lt;/a&gt; for posts where I review an academic paper.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tagging"&gt;tagging&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="tagging"/></entry><entry><title>Generationship: Ep. #39, Simon Willison</title><link href="https://simonwillison.net/2025/Jul/11/generationship/#atom-tag" rel="alternate"/><published>2025-07-11T05:33:06+00:00</published><updated>2025-07-11T05:33:06+00:00</updated><id>https://simonwillison.net/2025/Jul/11/generationship/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.heavybit.com/library/podcasts/generationship/ep-39-simon-willison-i-coined-prompt-injection"&gt;Generationship: Ep. #39, Simon Willison&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I recorded this podcast episode with Rachel Chalmers a few weeks ago. We talked about the resurgence of blogging, the legacy of Google Reader, learning in public, LLMs as weirdly confident interns, AI-assisted search, prompt injection, human augmentation over replacement and we finished with this delightful aside about pelicans which I'll quote here in full:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Rachel&lt;/strong&gt;: My last question, my favorite question. If you had a generation ship, a star ship that takes more than a human generation to get to Alpha Centauri, what would you call it?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simon&lt;/strong&gt;: I'd call it &lt;a href="https://simonwillison.net/2025/Mar/4/squadron/"&gt;Squadron&lt;/a&gt;, because that is the collective noun for pelicans. And I love pelicans.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rachel&lt;/strong&gt;: Pelicans are the best.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simon&lt;/strong&gt;: They're the best. I live in Half Moon Bay. We have the second largest mega roost of the California brown pelican in the world, in our local harbor [...] last year we had over a thousand pelicans diving into the water at the same time at peak anchovy season or whatever it was.&lt;/p&gt;
&lt;p&gt;The largest mega roost, because I know you want to know, is in Alameda, over by the aircraft carrier.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rachel&lt;/strong&gt;: The hornet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simon&lt;/strong&gt;: Yeah. It's got the largest mega roost of the California brown pelican at certain times of the year. They're so photogenic. They've got charisma. They don't look properly shaped for flying.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rachel&lt;/strong&gt;: They look like the &lt;a href="https://en.wikipedia.org/wiki/Hughes_H-4_Hercules"&gt;Spruce Goose&lt;/a&gt;. They've got the big front. And they look like they're made of wood.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simon&lt;/strong&gt;: That's such a great comparison, because I saw the Spruce Goose a couple of years ago. Up in Portland, there's &lt;a href="https://www.niche-museums.com/24"&gt;this museum that has the Spruce Goose&lt;/a&gt;, and I went to see it. And it's incredible. Everyone makes fun of the Spruce Goose until you see the thing. And it's this colossal, beautiful wooden aircraft. Until recently it was the largest aircraft in the world. And it's such a stunning vehicle.&lt;/p&gt;
&lt;p&gt;So yeah, pelicans and the Spruce Goose. I'm going to go with that one.&lt;/p&gt;
&lt;/blockquote&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai"&gt;ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/llms"&gt;llms&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/half-moon-bay"&gt;half-moon-bay&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/podcast-appearances"&gt;podcast-appearances&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="ai"/><category term="generative-ai"/><category term="llms"/><category term="half-moon-bay"/><category term="podcast-appearances"/></entry><entry><title>Disclosures</title><link href="https://simonwillison.net/2025/Jun/23/disclosures/#atom-tag" rel="alternate"/><published>2025-06-23T18:06:02+00:00</published><updated>2025-06-23T18:06:02+00:00</updated><id>https://simonwillison.net/2025/Jun/23/disclosures/#atom-tag</id><summary type="html">
    &lt;p&gt;I've added a &lt;a href="https://simonwillison.net/about/#disclosures"&gt;Disclosures section&lt;/a&gt; to my about page, listing my various sources of income and the companies that directly sponsor my work or have supported it in the recent past.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I do not receive any compensation writing about specific topics on this blog - no sponsored content! I plan to continue this policy. If I ever change this I will disclose that both here and in the post itself. [...]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I see my credibility as one of my most valuable assets, so it's important to be transparent about how financial interests may influence my writing here.&lt;/p&gt;
&lt;p&gt;I took inspiration from &lt;a href="https://www.mollywhite.net/crypto-disclosures/"&gt;Molly White's disclosures page&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/molly-white"&gt;molly-white&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="molly-white"/></entry><entry><title>Blogging about papers</title><link href="https://simonwillison.net/2025/Jun/13/blogging-about-papers/#atom-tag" rel="alternate"/><published>2025-06-13T16:22:05+00:00</published><updated>2025-06-13T16:22:05+00:00</updated><id>https://simonwillison.net/2025/Jun/13/blogging-about-papers/#atom-tag</id><summary type="html">
    &lt;p&gt;My post this morning about &lt;a href="https://simonwillison.net/2025/Jun/13/prompt-injection-design-patterns/"&gt;Design Patterns for Securing LLM Agents against Prompt Injections&lt;/a&gt; is an example of a blogging format I'd love to see more of: informal but informed commentary on academic papers.&lt;/p&gt;
&lt;p&gt;Academic papers are generally &lt;em&gt;hard to read&lt;/em&gt;. Sadly that's almost a requirement of the format: the incentives for publishing papers that make it through peer review are often at odds with producing text that's easy for non-academics to digest.&lt;/p&gt;
&lt;p&gt;(This &lt;a href="https://arxiv.org/abs/2506.08837"&gt;new Design Patterns paper&lt;/a&gt; bucks that trend, the writing is clear, it’s enjoyable to read and the target audience clearly includes practitioners, not just other researchers.)&lt;/p&gt;
&lt;p&gt;In addition to breaking a paper down into more digestible chunks, writing about papers offers an extremely valuable filter. There are hundreds of new papers published every day: seeing someone who's work you respect confirm that a paper is worth your time is a really strong signal.&lt;/p&gt;
&lt;p&gt;I added a &lt;a href="https://simonwillison.net/tags/paper-review/"&gt;paper-review tag&lt;/a&gt; this morning, gathering six posts where I’ve attempted this kind of review. &lt;a href="https://simonwillison.net/2022/Sep/1/sqlite-duckdb-paper/"&gt;Notes on the SQLite DuckDB paper&lt;/a&gt; in September 2022 was my first.&lt;/p&gt;
&lt;p&gt;I apply the same principle to these as my link blog: 
&lt;a href="https://simonwillison.net/2024/Dec/22/link-blog/#trying-to-add-something-extra"&gt;try to add something extra&lt;/a&gt;, so that anyone who reads both my post &lt;em&gt;and&lt;/em&gt; the paper itself gets a little bit of extra value from my notes.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/paper-review"&gt;paper-review&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;&lt;/p&gt;



</summary><category term="paper-review"/><category term="blogging"/></entry><entry><title>It's this blog's 23rd birthday</title><link href="https://simonwillison.net/2025/Jun/12/blog-birthday/#atom-tag" rel="alternate"/><published>2025-06-12T21:31:14+00:00</published><updated>2025-06-12T21:31:14+00:00</updated><id>https://simonwillison.net/2025/Jun/12/blog-birthday/#atom-tag</id><summary type="html">
    &lt;p&gt;It's this blog's 23rd birthday today!&lt;/p&gt;
&lt;p&gt;On June 12th 2022 I celebrated &lt;a href="https://simonwillison.net/2022/Jun/12/twenty-years/"&gt;Twenty years of my blog&lt;/a&gt; with a big post full of highlights. Looking back now I'm amused to notice that my 20th birthday post came within two weeks of my earliest writing about LLMs: &lt;a href="https://simonwillison.net/2022/May/31/a-datasette-tutorial-written-by-gpt-3/"&gt;A Datasette tutorial written by GPT-3&lt;/a&gt; and &lt;a href="https://simonwillison.net/2022/Jun/5/play-with-gpt3/"&gt;How to use the GPT-3 language model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My &lt;a href="https://simonwillison.net/tags/generative-ai/"&gt;generative-ai tag&lt;/a&gt; has reached 1,184 posts now.&lt;/p&gt;
&lt;p&gt;I really do feel like blogging is onto its second wind. The amount of influence you can have on the world by consistently blogging about a subject is just as high today as it was back in the 2000s when blogging first started.&lt;/p&gt;
&lt;p&gt;The best time to start a blog may have been twenty years ago, but the second best time to start a blog is today.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/generative-ai"&gt;generative-ai&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;&lt;/p&gt;



</summary><category term="generative-ai"/><category term="blogging"/></entry><entry><title>First monthly sponsor newsletter tomorrow</title><link href="https://simonwillison.net/2025/May/29/newsletter-tomorrow/#atom-tag" rel="alternate"/><published>2025-05-29T04:33:32+00:00</published><updated>2025-05-29T04:33:32+00:00</updated><id>https://simonwillison.net/2025/May/29/newsletter-tomorrow/#atom-tag</id><summary type="html">
    &lt;p&gt;I'll be sending out my first &lt;a href="https://simonwillison.net/2025/May/25/sponsors-only-newsletter/"&gt;curated monthly highlights newsletter&lt;/a&gt; tomorrow, only to $10/month and up sponsors. &lt;a href="https://github.com/sponsors/simonw/"&gt;Sign up now&lt;/a&gt; if you want to pay me to send you less!&lt;/p&gt;
&lt;p&gt;My &lt;a href="https://simonw.substack.com/"&gt;weekly-ish&lt;/a&gt; newsletter remains free, in fact I just sent out &lt;a href="https://simonw.substack.com/p/large-language-models-can-run-tools"&gt;the latest edition&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/newsletter"&gt;newsletter&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="newsletter"/></entry><entry><title>Subscribe to my sponsors-only monthly newsletter.</title><link href="https://simonwillison.net/2025/May/25/sponsors-only-newsletter/#atom-tag" rel="alternate"/><published>2025-05-25T06:06:17+00:00</published><updated>2025-05-25T06:06:17+00:00</updated><id>https://simonwillison.net/2025/May/25/sponsors-only-newsletter/#atom-tag</id><summary type="html">
    &lt;h3 style="margin-top: 0"&gt;Subscribe to my sponsors-only monthly newsletter&lt;/h3&gt;

&lt;p&gt;I’ve never liked the idea of charging for my content. I get enormous value from putting all of my writing and research out there for free.&lt;/p&gt;
&lt;p&gt;So I’m trying something a little different: &lt;strong&gt;pay me to send you less&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I’m starting a sponsors-only monthly newsletter featuring just my heavily curated and edited highlights. If you only have ten minutes, what are the most important things not to miss from the last month?&lt;/p&gt;
&lt;p&gt;Don’t want to pay? That’s fine, you can continue to follow my firehose for free!&lt;/p&gt;
&lt;p&gt;Anyone who sponsors me for &lt;a href="https://github.com/sponsors/simonw"&gt;$10/month (or $50/month or more) on GitHub sponsors&lt;/a&gt; will receive my new newsletter on approximately the last day of the month. I’ll be sending out the first edition next week.&lt;/p&gt;
&lt;p&gt;This blog and &lt;a href="https://simonw.substack.com/"&gt;my newsletter&lt;/a&gt; will continue at their same breakneck pace. Paying subscribers can get a &lt;em&gt;lower&lt;/em&gt; volume of stuff.&lt;/p&gt;
&lt;p&gt;I'm cautiously optimistic that this could work. I've never liked the idea of business models that incentivize me to publish less. This feels like it encourages me to do what I'm doing already while giving people a rational reason to support my work, at a relatively small incremental cost to myself.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/projects"&gt;projects&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/github"&gt;github&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/email"&gt;email&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/newsletter"&gt;newsletter&lt;/a&gt;&lt;/p&gt;



</summary><category term="projects"/><category term="blogging"/><category term="github"/><category term="email"/><category term="newsletter"/></entry><entry><title>Quoting dynomight</title><link href="https://simonwillison.net/2025/Apr/26/dynomight/#atom-tag" rel="alternate"/><published>2025-04-26T17:05:04+00:00</published><updated>2025-04-26T17:05:04+00:00</updated><id>https://simonwillison.net/2025/Apr/26/dynomight/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://dynomight.net/jaccuse/"&gt;&lt;p&gt;I don’t have a “mission” for this blog, but if I did, it would be to slightly increase the space in which people are calm and respectful and care about getting the facts right. I think we need more of this, and I’m worried that society is devolving into “trench warfare” where facts are just tools to be used when convenient for your political coalition, and everyone assumes everyone is distorting everything, all the time.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://dynomight.net/jaccuse/"&gt;dynomight&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/></entry><entry><title>Another rant about companies not spying on you through your phone's microphone to serve you ads</title><link href="https://simonwillison.net/2025/Apr/26/rant/#atom-tag" rel="alternate"/><published>2025-04-26T02:07:00+00:00</published><updated>2025-04-26T02:07:00+00:00</updated><id>https://simonwillison.net/2025/Apr/26/rant/#atom-tag</id><summary type="html">
    &lt;p&gt;Last September I posted &lt;a href="https://lobste.rs/s/mf7guc/leak_facebook_partner_brags_about"&gt;a series of long ranty comments on Lobste.rs&lt;/a&gt; about the latest instance of the &lt;a href="https://simonwillison.net/2025/Jan/2/they-spy-on-you-but-not-like-that/"&gt;immortal conspiracy theory&lt;/a&gt; (here &lt;a href="https://news.ycombinator.com/item?id=43799802"&gt;it goes again&lt;/a&gt;) about apps spying on you through your microphone to serve you targeted ads.&lt;/p&gt;
&lt;p&gt;On the basis that it's always a great idea to &lt;a href="https://simonwillison.net/2025/Apr/25/backfill-your-blog/"&gt;backfill content on your blog&lt;/a&gt;, I just extracted my best comments from that thread and turned them into &lt;a href="https://simonwillison.net/2024/Sep/2/facebook-cmg/"&gt;this full post here&lt;/a&gt;, back-dated to September 2nd which is when I wrote the comments.&lt;/p&gt;
&lt;p&gt;My rant was in response to the story &lt;a href="https://futurism.com/the-byte/facebook-partner-phones-listening-microphone"&gt;In Leak, Facebook Partner Brags About Listening to Your Phone’s Microphone to Serve Ads for Stuff You Mention&lt;/a&gt;. Here's how it starts:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Which is more likely?&lt;/p&gt;
&lt;ol style="margin-bottom: 1em"&gt;
&lt;li&gt;All of the conspiracy theories are real! The industry managed to keep the evidence from us for decades, but finally a marketing agency of a local newspaper chain has blown the lid off the whole thing, in a bunch of blog posts and PDFs and on a podcast.&lt;/li&gt;
&lt;li&gt;Everyone believed that their phone was listening to them even when it wasn’t. The marketing agency of a local newspaper chain were the first group to be caught taking advantage of that widespread paranoia and use it to try and dupe people into spending money with them, despite the tech not actually working like that.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My money continues to be on number 2.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can &lt;a href="https://simonwillison.net/2024/Sep/2/facebook-cmg/"&gt;read the rest here&lt;/a&gt;. Or skip straight to why I think this matters so much:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Privacy is important. People who are sufficiently engaged need to be able to understand exactly what’s going on, so they can e.g. campaign for legislators to reign in the most egregious abuses.&lt;/p&gt;
&lt;p&gt;I think it’s harmful letting people continue to believe things about privacy that are not true, when we should instead be helping them understand the things that are true.&lt;/p&gt;
&lt;/blockquote&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/privacy"&gt;privacy&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/microphone-ads-conspiracy"&gt;microphone-ads-conspiracy&lt;/a&gt;&lt;/p&gt;



</summary><category term="privacy"/><category term="blogging"/><category term="microphone-ads-conspiracy"/></entry><entry><title>Backfill your blog</title><link href="https://simonwillison.net/2025/Apr/25/backfill-your-blog/#atom-tag" rel="alternate"/><published>2025-04-25T15:30:37+00:00</published><updated>2025-04-25T15:30:37+00:00</updated><id>https://simonwillison.net/2025/Apr/25/backfill-your-blog/#atom-tag</id><summary type="html">
    &lt;p&gt;Fun fact: there's no rule that says you can't create a new blog today and backfill (and backdate) it with your writing from other platforms or sources, even going back many years.&lt;/p&gt;
&lt;p&gt;I'd love to see more people do this!&lt;/p&gt;
&lt;p&gt;&lt;small&gt;(Inspired by &lt;a href="https://twitter.com/jwuphysics/status/1915422889224147335"&gt;this tweet&lt;/a&gt; by John F. Wu introducing &lt;a href="https://jwuphysics.github.io/blog/"&gt;his new blog&lt;/a&gt;. I did this myself when I &lt;a href="https://simonwillison.net/2017/Oct/1/ship/"&gt;relaunched this blog&lt;/a&gt; back in 2017.)&lt;/small&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/></entry><entry><title>Working Through the Fear of Being Seen</title><link href="https://simonwillison.net/2025/Apr/22/working-through-the-fear-of-being-seen/#atom-tag" rel="alternate"/><published>2025-04-22T06:40:49+00:00</published><updated>2025-04-22T06:40:49+00:00</updated><id>https://simonwillison.net/2025/Apr/22/working-through-the-fear-of-being-seen/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://ashley.dev/posts/fear-of-being-seen/"&gt;Working Through the Fear of Being Seen&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Heartfelt piece by Ashley Willis about the challenge of overcoming self-doubt in publishing online:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Part of that is knowing who might read it. A lot of the folks who follow me are smart, opinionated, and not always generous. Some are friends. Some are people I’ve looked up to. And some are just really loud on the internet. I saw someone the other day drag a certain writing style. That kind of judgment makes me want to shrink back and say, never mind.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Try to avoid being somebody who discourages others from sharing their thoughts.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://bsky.app/profile/ashley.dev/post/3lneixhjamk2i"&gt;@ashley.dev&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/></entry><entry><title>Quoting Matt Webb</title><link href="https://simonwillison.net/2025/Apr/5/matt-webb/#atom-tag" rel="alternate"/><published>2025-04-05T04:56:31+00:00</published><updated>2025-04-05T04:56:31+00:00</updated><id>https://simonwillison.net/2025/Apr/5/matt-webb/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://manuelmoreale.com/pb-matt-webb"&gt;&lt;p&gt;Blogging is small-p political again, today. It’s come back round. It’s a statement to put your words in a place where they are not subject to someone else’s algorithm telling you what success looks like; when you blog, your words are not a vote for the values of someone else’s platform.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://manuelmoreale.com/pb-matt-webb"&gt;Matt Webb&lt;/a&gt;, Interview for People and Blogs&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/matt-webb"&gt;matt-webb&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;&lt;/p&gt;



</summary><category term="matt-webb"/><category term="blogging"/></entry><entry><title>Note on 26th March 2025</title><link href="https://simonwillison.net/2025/Mar/26/notes/#atom-tag" rel="alternate"/><published>2025-03-26T06:11:30+00:00</published><updated>2025-03-26T06:11:30+00:00</updated><id>https://simonwillison.net/2025/Mar/26/notes/#atom-tag</id><summary type="html">
    &lt;p&gt;I've added a new content type to my blog: &lt;strong&gt;notes&lt;/strong&gt;. These join my existing types: &lt;a href="https://simonwillison.net/search/?type=entry"&gt;entries&lt;/a&gt;, &lt;a href="https://simonwillison.net/search/?type=blogmark"&gt;bookmarks&lt;/a&gt; and &lt;a href="https://simonwillison.net/search/?type=quotation"&gt;quotations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A note is a little bit like a bookmark without a link. They're for short form writing - thoughts or images that don't warrant a full entry with a title. The kind of things I used to post to Twitter, but that don't feel right to cross-post to multiple social networks (Mastodon and Bluesky, for example.)&lt;/p&gt;
&lt;p&gt;I was partly inspired by Molly White's &lt;a href="https://www.mollywhite.net/micro"&gt;short thoughts, notes, links, and musings&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I've been thinking about this for a while, but the amount of work involved in modifying all of the parts of my site that handle the three different content types was daunting. Then this evening I tried running my blog's source code (using &lt;a href="https://github.com/simonw/files-to-prompt"&gt;files-to-prompt&lt;/a&gt; and &lt;a href="https://llm.datasette.io/"&gt;LLM&lt;/a&gt;) through &lt;a href="https://simonwillison.net/2025/Mar/25/gemini/"&gt;the new Gemini 2.5 Pro&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;files-to-prompt &lt;span class="pl-c1"&gt;.&lt;/span&gt; -e py -c &lt;span class="pl-k"&gt;|&lt;/span&gt; \
  llm -m gemini-2.5-pro-exp-03-25 -s \
  &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;I want to add a new type of content called a Note,&lt;/span&gt;
&lt;span class="pl-s"&gt;  similar to quotation and bookmark and entry but it&lt;/span&gt;
&lt;span class="pl-s"&gt;  only has a markdown text body. Output all of the&lt;/span&gt;
&lt;span class="pl-s"&gt;  code I need to add for that feature and tell me&lt;/span&gt;
&lt;span class="pl-s"&gt;  which files to add  the code to.&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Gemini gave me &lt;a href="https://gist.github.com/simonw/6d9fb3e33e7105d391a31367d6a235de#response"&gt;a detailed 13 step plan&lt;/a&gt; covering all of the tedious changes I'd been avoiding having to figure out!&lt;/p&gt;
&lt;p&gt;The code &lt;a href="https://github.com/simonw/simonwillisonblog/pull/527"&gt;is in this PR&lt;/a&gt;, which touched 18 different files. The whole project took around 45 minutes start to finish.&lt;/p&gt;
&lt;p&gt;(I used Claude to &lt;a href="https://claude.ai/share/17656d59-6f52-471e-8aeb-6abbe1464471"&gt;brainstorm names&lt;/a&gt; for the feature - I had it come up with possible nouns and then "rank those by least pretentious to most pretentious", and "notes" came out on top.)&lt;/p&gt;
&lt;p&gt;This is now far too long for a note and should really be upgraded to an entry, but I need to post a first note to make sure everything is working as it should.&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/projects"&gt;projects&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gemini"&gt;gemini&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ai-assisted-programming"&gt;ai-assisted-programming&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/claude"&gt;claude&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/molly-white"&gt;molly-white&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/files-to-prompt"&gt;files-to-prompt&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="projects"/><category term="gemini"/><category term="ai-assisted-programming"/><category term="claude"/><category term="molly-white"/><category term="files-to-prompt"/></entry><entry><title>Calling a wrap on my weeknotes</title><link href="https://simonwillison.net/2025/Mar/20/calling-a-wrap-on-my-weeknotes/#atom-tag" rel="alternate"/><published>2025-03-20T04:12:32+00:00</published><updated>2025-03-20T04:12:32+00:00</updated><id>https://simonwillison.net/2025/Mar/20/calling-a-wrap-on-my-weeknotes/#atom-tag</id><summary type="html">
    &lt;p&gt;After &lt;a href="https://simonwillison.net/tags/weeknotes/"&gt;192 posts&lt;/a&gt; that ranged from weekly to roughly once-a-month, I've decided to call a wrap on my weeknotes habit. The &lt;a href="https://simonwillison.net/2019/Sep/13/weeknotestwitter-sqlite-datasette-rure/"&gt;original goal&lt;/a&gt; was to stay transparent during my 2019-2020 JSK fellowship, and I kept them up after that as an accountability mechanism and to get into a habit of writing regularly.&lt;/p&gt;
&lt;p&gt;Over the past two years I've adopted new posting habits which are solving those problems in other ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I post something here almost every day. I actually maintained a daily posting streak throughout 2024, which I &lt;a href="https://simonwillison.net/2025/Jan/2/ending-a-year-long-posting-streak/"&gt;ended in January&lt;/a&gt;, but I'm still posting most days and plan to keep that up.&lt;/li&gt;
&lt;li&gt;Every time I ship a new release of one of my projects I link to it from here. This replaces the "recent releases" section of my weeknotes.&lt;/li&gt;
&lt;li&gt;I try to have a longer form piece of writing that's suitable for inclusion in &lt;a href="https://simonw.substack.com/"&gt;my newsletter&lt;/a&gt; at least once every two weeks. That's another accountability mechanism that's working well for me.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One downside of weeknotes is that I'd sometimes save something to include in them, which could lead to several items getting bundled together in a way that reduced their potential impact as standalone posts.&lt;/p&gt;
&lt;p&gt;I got to the point with weeknotes where I was feeling guilty about not keeping them up. Given the volume of content I'm publishing already that felt like a sign that they were no longer providing the value they once did!&lt;/p&gt;
&lt;p&gt;I still think weeknotes are an excellent habit for anyone who wants to write more frequently and be more transparent about their work. It feels healthy to be able to end a habit that's finished serving its purpose.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/weeknotes"&gt;weeknotes&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/streaks"&gt;streaks&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="blogging"/><category term="weeknotes"/><category term="streaks"/></entry><entry><title>Quoting Matt Webb</title><link href="https://simonwillison.net/2025/Feb/19/matt-webb/#atom-tag" rel="alternate"/><published>2025-02-19T13:50:16+00:00</published><updated>2025-02-19T13:50:16+00:00</updated><id>https://simonwillison.net/2025/Feb/19/matt-webb/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://interconnected.org/home/2025/02/19/reflections"&gt;&lt;p&gt;Meanwhile blogging has become small-p political again.&lt;/p&gt;
&lt;p&gt;Slowly, slowly, the web was taken over by platforms. Your feeling of success is based on your platform’s algorithm, which may not have your interests at heart. Feeding your words to a platform is a vote for its values, whether you like it or not. And they roach-motel you by owning your audience, making you feel that it’s a good trade because you get “discovery.” (Though I know that chasing popularity is a fool’s dream.)&lt;/p&gt;
&lt;p&gt;Writing a blog on your own site is a way to escape all of that. Plus your words build up over time. That’s unique. Nobody else values your words like you do.&lt;/p&gt;
&lt;p&gt;Blogs are a backwater (the web itself is a backwater) but keeping one is a statement of how being online can work. Blogging as a kind of Amish performance of a better life.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://interconnected.org/home/2025/02/19/reflections"&gt;Matt Webb&lt;/a&gt;, Reflections on 25 years of Interconnected&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/matt-webb"&gt;matt-webb&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/social-media"&gt;social-media&lt;/a&gt;&lt;/p&gt;



</summary><category term="matt-webb"/><category term="blogging"/><category term="social-media"/></entry><entry><title>tc39/proposal-regex-escaping</title><link href="https://simonwillison.net/2025/Feb/18/tc39proposal-regex-escaping/#atom-tag" rel="alternate"/><published>2025-02-18T21:53:56+00:00</published><updated>2025-02-18T21:53:56+00:00</updated><id>https://simonwillison.net/2025/Feb/18/tc39proposal-regex-escaping/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/tc39/proposal-regex-escaping"&gt;tc39/proposal-regex-escaping&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I just heard &lt;a href="https://social.coop/@kriskowal/114026510846190089"&gt;from Kris Kowal&lt;/a&gt; that this proposal for ECMAScript has been approved for ECMA TC-39:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Almost 20 years later, @simon’s RegExp.escape idea comes to fruition. This reached “Stage 4” at ECMA TC-39 just now, which formalizes that multiple browsers have shipped the feature and it’s in the next revision of the JavaScript specification.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'll be honest, I had completely forgotten about my 2006 blog entry &lt;a href="https://simonwillison.net/2006/Jan/20/escape/"&gt;Escaping regular expression characters in JavaScript&lt;/a&gt; where I proposed that JavaScript should have an equivalent of the Python &lt;a href="https://docs.python.org/3/library/re.html#re.escape"&gt;re.escape()&lt;/a&gt; function.&lt;/p&gt;
&lt;p&gt;It turns out my post was referenced in &lt;a href="https://esdiscuss.org/topic/regexp-escape"&gt;this 15 year old thread&lt;/a&gt; on the esdiscuss mailing list, which evolved over time into a proposal which turned into &lt;a href="https://caniuse.com/mdn-javascript_builtins_regexp_escape"&gt;implementations&lt;/a&gt; in Safari, Firefox and soon Chrome - here's &lt;a href="https://github.com/v8/v8/commit/b5c08badc7b3d4b85b2645b1a4d9973ee6efaa91"&gt;the commit landing it in v8&lt;/a&gt; on February 12th 2025.&lt;/p&gt;
&lt;p&gt;One of the best things about having a long-running blog is that sometimes posts you forgot about over a decade ago turn out to have a life of their own.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ecmascript"&gt;ecmascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/regular-expressions"&gt;regular-expressions&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/standards"&gt;standards&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="ecmascript"/><category term="javascript"/><category term="regular-expressions"/><category term="standards"/></entry><entry><title>Build a link blog</title><link href="https://simonwillison.net/2025/Feb/4/build-a-link-blog/#atom-tag" rel="alternate"/><published>2025-02-04T16:14:33+00:00</published><updated>2025-02-04T16:14:33+00:00</updated><id>https://simonwillison.net/2025/Feb/4/build-a-link-blog/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://xuanwo.io/links/2025/01/link-blog/"&gt;Build a link blog&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Xuanwo started &lt;a href="https://xuanwo.io/links/"&gt;a link blog&lt;/a&gt; inspired by my article &lt;a href="https://simonwillison.net/2024/Dec/22/link-blog/"&gt;My approach to running a link blog&lt;/a&gt;, and in a delightful piece of recursion his first post is a link blog entry about my post about link blogging, following my tips on quoting liberally and including extra commentary.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I decided to follow simon's approach to creating a link blog, where I can share interesting links I find on the internet along with my own comments and thoughts about them.&lt;/p&gt;
&lt;/blockquote&gt;

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


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/></entry><entry><title>Friday Squid Blogging: Anniversary Post</title><link href="https://simonwillison.net/2025/Jan/4/friday-squid-blogging-anniversary-post/#atom-tag" rel="alternate"/><published>2025-01-04T16:21:51+00:00</published><updated>2025-01-04T16:21:51+00:00</updated><id>https://simonwillison.net/2025/Jan/4/friday-squid-blogging-anniversary-post/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.schneier.com/blog/archives/2025/01/friday-squid-blogging-anniversary-post.html"&gt;Friday Squid Blogging: Anniversary Post&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Bruce Schneier:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I made my &lt;a href="https://www.schneier.com/blog/archives/2006/01/friday_squid_bl.html"&gt;first squid post&lt;/a&gt; nineteen years ago this week. Between then and now, I posted something about squid every week (with maybe only a few exceptions). There is a &lt;em&gt;lot&lt;/em&gt; out there about squid, even more if you count the other meanings of the word.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think that's &lt;a href="https://www.schneier.com/tag/squid/"&gt;1,004 posts about squid&lt;/a&gt; in 19 years. Talk about a &lt;a href="https://simonwillison.net/2024/Jan/2/escalating-streaks/"&gt;legendary streak&lt;/a&gt;!


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/bruce-schneier"&gt;bruce-schneier&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/streaks"&gt;streaks&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="bruce-schneier"/><category term="streaks"/></entry><entry><title>Ending a year long posting streak</title><link href="https://simonwillison.net/2025/Jan/2/ending-a-year-long-posting-streak/#atom-tag" rel="alternate"/><published>2025-01-02T00:25:34+00:00</published><updated>2025-01-02T00:25:34+00:00</updated><id>https://simonwillison.net/2025/Jan/2/ending-a-year-long-posting-streak/#atom-tag</id><summary type="html">
    &lt;p&gt;A year ago today I wrote about &lt;a href="https://simonwillison.net/2024/Jan/2/escalating-streaks/"&gt;Tom Scott's legendary 10 year YouTube streak&lt;/a&gt;, in which he posted a new video once a week for the next ten years. Inspired by that, I also started my own.&lt;/p&gt;
&lt;p&gt;I set myself the goal of posting something to my blog every day for a year.&lt;/p&gt;
&lt;p&gt;Given how much happened in my chosen field of &lt;a href="https://simonwillison.net/2024/Dec/31/llms-in-2024/"&gt;Large Language Models over the course of 2024&lt;/a&gt; this wasn't as hard as I had expected!&lt;/p&gt;
&lt;p&gt;One of the lessons I learned from Tom is that it's much healthier for a streak to have a predetermined end - that way the streak can act as a goal that doesn't turn into an ongoing imposition.&lt;/p&gt;
&lt;p&gt;I'm calling it: this streak is done. According to &lt;a href="https://simonwillison.net/dashboard/streaks-with-post-count/"&gt;my custom dashboard&lt;/a&gt; I hit 367 days - December 31st 2023 to December 31st 2024, inclusive (it was a leap year) - 1,151 posts in total.&lt;/p&gt;

&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2025/jan-streak.jpg" style="max-width: 100%" alt="Table of data. Row 1 has duration in days=1, start date=2025-01-02, end date=2025-01-02, num posts=1. Row 2 has duration in days=367, start date=2023-12-31, end date=2024-12-31, num posts=1151. Row 3 has duration in days=1, start date=2023-12-23, end date=2023-12-23, num posts=1. Row 4 has duration in days=4, start date=2023-12-18, end date=2023-12-21, num posts=6." /&gt;&lt;/p&gt;

&lt;p&gt;I'm going to drop back to a much more reasonable target of at least one long-form post per week and at least three days per week with a link or quote - see &lt;a href="https://simonwillison.net/2024/Dec/22/link-blog/"&gt;My approach to running a link blog&lt;/a&gt; for how I think about that kind of content.&lt;/p&gt;
&lt;p&gt;Posting daily has been fun, but it definitely impacted my productivity on my other projects. My blog runs on UTC so it also resulted in a minor panic coming up to 4pm Pacific coast time if I hadn't posted anything yet!&lt;/p&gt;

&lt;p&gt;Almost every post in the streak came out in 2024, so my &lt;a href="https://simonwillison.net/search/?year=2024"&gt;faceted search engine for 2024&lt;/a&gt; provides a way to explore them.&lt;/p&gt;

&lt;p&gt;My &lt;a href="https://simonwillison.net/2024/"&gt;2024 archive page&lt;/a&gt; also serves up this illustrative tag cloud:&lt;/p&gt;

&lt;p&gt;&lt;img src="https://static.simonwillison.net/static/2025/2024-tag-cloud.jpg" style="max-width: 100%" alt="A tag cloud with llms and ai as the central largest terms, surrounded by technology-related words: nomic, datasette, security, rag, projects, llama, openai, gemini, edge-llms, psf, sql, open-source, json, javascript, ethics, python, google, plugins, gis, django, apple, sqlite, aws, tools, rust, golang, c, uv, s3, css, git, ocr" /&gt;&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tom-scott"&gt;tom-scott&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/streaks"&gt;streaks&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="blogging"/><category term="tom-scott"/><category term="streaks"/></entry><entry><title>My approach to running a link blog</title><link href="https://simonwillison.net/2024/Dec/22/link-blog/#atom-tag" rel="alternate"/><published>2024-12-22T18:37:16+00:00</published><updated>2024-12-22T18:37:16+00:00</updated><id>https://simonwillison.net/2024/Dec/22/link-blog/#atom-tag</id><summary type="html">
    &lt;p&gt;I started running a basic link blog on this domain &lt;a href="https://simonwillison.net/2003/Nov/24/blogmarks/"&gt;back in November 2003&lt;/a&gt; - publishing links (which I called "blogmarks") with a title, URL, short snippet of commentary and a "via" link where appropriate.&lt;/p&gt;
&lt;p&gt;So far I've published &lt;a href="https://simonwillison.net/search/?type=blogmark"&gt;7,607 link blog posts&lt;/a&gt; and counting.&lt;/p&gt;
&lt;p&gt;In April of this year I finally &lt;a href="https://simonwillison.net/2024/Apr/25/blogmarks-that-use-markdown/"&gt;upgraded my link blog to support Markdown&lt;/a&gt;, allowing me to expand my link blog into something with a lot more room.&lt;/p&gt;
&lt;p&gt;The way I use my link blog has evolved substantially in the eight months since then. I'm going to describe the informal set of guidelines I've set myself for how I link blog, in the hope that it might encourage other people to give this a try themselves.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2024/Dec/22/link-blog/#writing-about-things-i-ve-found"&gt;Writing about things I've found&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2024/Dec/22/link-blog/#trying-to-add-something-extra"&gt;Trying to add something extra&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2024/Dec/22/link-blog/#the-technology"&gt;The technology&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://simonwillison.net/2024/Dec/22/link-blog/#more-people-should-do-this"&gt;More people should do this&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="writing-about-things-i-ve-found"&gt;Writing about things I've found&lt;/h4&gt;
&lt;p&gt;Back in November 2022 I wrote &lt;a href="https://simonwillison.net/2022/Nov/6/what-to-blog-about/"&gt;What to blog about&lt;/a&gt;, which started with this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You should start a blog. Having your own little corner of the internet is good for the soul!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The point of that article was to emphasize that blogging doesn't have to be about unique insights. The value is in writing frequently and having something to show for it over time - worthwhile even if you don't attract much of an audience (or any audience at all).&lt;/p&gt;
&lt;p&gt;In that article I proposed two categories of content that are low stakes and high value: &lt;strong&gt;things I learned&lt;/strong&gt; and &lt;strong&gt;descriptions of my projects&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I realize now that link blogging deserves to be included a third category of low stakes, high value writing. We could think of that category as &lt;strong&gt;things I've found&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That's the purpose of my link blog: it's an ongoing log of things I've found - effectively a combination of public bookmarks and my own thoughts and commentary on why those things are interesting.&lt;/p&gt;
&lt;h4 id="trying-to-add-something-extra"&gt;Trying to add something extra&lt;/h4&gt;
&lt;p&gt;When I first started link blogging I would often post a link with a one sentence summary of the linked content, and maybe a tiny piece of opinionated commentary.&lt;/p&gt;
&lt;p&gt;After I upgraded my link blog to support additional markup (links, images, quotations) I decided to be more ambitious. Here are some of the things I try to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I always include &lt;strong&gt;the names of the people&lt;/strong&gt; who created the content I am linking to, if I can figure that out. Credit is really important, and it's also useful for myself because I can later search for someone's name and find other interesting things they have created that I linked to in the past. If I've linked to someone's work three or more times I also try to notice and upgrade them to &lt;a href="https://simonwillison.net/tags/"&gt;a dedicated tag&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I try to &lt;strong&gt;add something extra&lt;/strong&gt;. My goal with any link blog post is that if you read both my post and the source material you'll have an enhanced experience over if you read just the source material itself.
&lt;ul&gt;
&lt;li&gt;Ideally I'd like you to take something useful away even if you don't follow the link itself. This can be a slightly tricky balance: I don't want to steal attention from the authors and plagiarize their message. Generally I'll try to find some key idea that's worth emphasizing. Slightly cynically, I may try to capture that idea as backup against the original source vanishing from the internet. Link rot is real!&lt;/li&gt;
&lt;li&gt;My most basic version of this is trying to provide context as to why I think this particular thing is worth reading - especially important for longer content. A good recent example is my post about Anthropic's &lt;a href="https://simonwillison.net/2024/Dec/20/building-effective-agents/"&gt;Building effective agents&lt;/a&gt; essay the other day.&lt;/li&gt;
&lt;li&gt;I might tie it together to other similar concepts, including things I've written about in the past, for example linking &lt;a href="https://simonwillison.net/2024/Aug/14/prompt-caching-with-claude/"&gt;Prompt caching with Claude&lt;/a&gt; to my coverage of &lt;a href="https://simonwillison.net/2024/May/14/context-caching-for-google-gemini/"&gt;Context caching for Google Gemini&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If part of the material is a video, I might &lt;strong&gt;quote a snippet of the transcript&lt;/strong&gt; (often extracted using MacWhisper) like I did in &lt;a href="https://simonwillison.net/2024/Dec/12/clio/"&gt;this post about Anthropic's Clio&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A lot of stuff I link to involves programming. I'll often include a &lt;strong&gt;direct link to relevant code&lt;/strong&gt;, using the GitHub feature where I can link to a snippet as-of a particular commit. One example is the &lt;a href="https://simonwillison.net/2024/Oct/5/uv-with-github-actions-to-run-an-rss-to-readme-project/"&gt;fetch-rss.py link in this post&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I'm liberal with &lt;strong&gt;quotations&lt;/strong&gt;. Finding and quoting a paragraph that captures the key theme of a post is a very quick and effective way to summarize it and help people decide if it's worth reading the whole thing. My post on &lt;a href="https://simonwillison.net/2024/Dec/20/openai-o3-breakthrough/"&gt;François Chollet's o3 ARC-AGI analysis&lt;/a&gt; is an example of that.&lt;/li&gt;
&lt;li&gt;If the original author reads my post, I want them to &lt;strong&gt;feel good about it&lt;/strong&gt;. I know from my own experience that often when you publish something online the silence can be deafening. Knowing that someone else read, appreciated, understood and then shared your work can be very pleasant.&lt;/li&gt;
&lt;li&gt;A slightly self-involved concern I have is that I like to &lt;strong&gt;prove that I've read it&lt;/strong&gt;. This is more for me than for anyone else: I don't like to recommend something if I've not read that thing myself, and sticking in a detail that shows I read past the first paragraph helps keep me honest about that.&lt;/li&gt;
&lt;li&gt;I've started leaning more into &lt;strong&gt;screenshots&lt;/strong&gt; and even short video or audio clips. A screenshot can be considered a visual quotation - I'll sometimes snap these from interesting frames in a YouTube video or live demo associated with the content I'm linking to. I used a screenshot of the Clay debugger in &lt;a href="https://simonwillison.net/2024/Dec/21/clay-ui-library/"&gt;my post about Clay&lt;/a&gt;.&lt;/li&gt;
&lt;p style="margin-top: 0.5em"&gt;There are a lot of great link blogs out there, but the one that has influenced me the most in how I approach my own is John Gruber's &lt;a href="https://daringfireball.net/"&gt;Daring Fireball&lt;/a&gt;. I really like the way he mixes commentary, quotations and value-added relevant information.&lt;/p&gt;
&lt;/ul&gt;
&lt;h4 id="the-technology"&gt;The technology&lt;/h4&gt;
&lt;p&gt;The technology behind my link blog is probably the least interesting thing about it. It's part of my &lt;a href="https://github.com/simonw/simonwillisonblog"&gt;simonwillisonblog&lt;/a&gt; Django application - the main model is called &lt;a href="https://github.com/simonw/simonwillisonblog/blob/c781a1a42ab0a0237f75c7790f069bacc2d70d3f/blog/models.py#L328-L337"&gt;Blogmark&lt;/a&gt; and it inherits from a &lt;a href="https://github.com/simonw/simonwillisonblog/blob/c781a1a42ab0a0237f75c7790f069bacc2d70d3f/blog/models.py#L172-L203"&gt;BaseModel&lt;/a&gt; defining things like tags and draft modes that are shared across my other types of content (entries and quotations).&lt;/p&gt;
&lt;p&gt;I use the Django Admin to create and edit entries, &lt;a href="https://github.com/simonw/simonwillisonblog/blob/c781a1a42ab0a0237f75c7790f069bacc2d70d3f/blog/admin.py#L73-L76"&gt;configured here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The most cumbersome part of link blogging for me right now is images. I convert these into smaller JPEGs using a &lt;a href="https://tools.simonwillison.net/image-resize-quality"&gt;tiny custom tool&lt;/a&gt; I built (&lt;a href="https://gist.github.com/simonw/58a06a8028515999e5949a0166cd4c4f"&gt;with Claude&lt;/a&gt;), then upload them to my &lt;code&gt;static.simonwillison.net&lt;/code&gt; S3 bucket using Transmit and drop them into my posts using a Markdown image reference. I generate a first draft of the alt text using a Claude Project with &lt;a href="https://gist.github.com/simonw/1fa7e4e3dcb18fdeca2b3d6ac2c6c628"&gt;these custom instructions&lt;/a&gt;, then usually make a few changes  before including that in the markup. At some point I'll wire together a UI that makes this process a little smoother.&lt;/p&gt;
&lt;p&gt;That &lt;code&gt;static.simonwillison.net&lt;/code&gt; bucket is then served via Cloudflare's free tier, which means I effectively never have to think about the cost of serving up those image files.&lt;/p&gt;
&lt;p&gt;I wrote up a TIL about &lt;a href="https://til.simonwillison.net/django/building-a-blog-in-django"&gt;Building a blog in Django&lt;/a&gt; a while ago which describes a similar setup to the one I'm using for my link blog, including how the RSS feed works (using &lt;a href="https://docs.djangoproject.com/en/4.2/ref/contrib/syndication/"&gt;Django's syndication framework&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The most technically interesting component is my &lt;a href="https://simonwillison.net/search/?type=blogmark"&gt;search feature&lt;/a&gt;. I wrote about how that works in &lt;a href="https://simonwillison.net/2017/Oct/5/django-postgresql-faceted-search/"&gt;Implementing faceted search with Django and PostgreSQL&lt;/a&gt; - the most recent code for that can be found in &lt;a href="https://github.com/simonw/simonwillisonblog/blob/main/blog/search.py"&gt;blog/search.py&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;One of the most useful small enhancements I added was &lt;a href="https://github.com/simonw/simonwillisonblog/issues/488"&gt;draft mode&lt;/a&gt;, which lets me assign a URL to an item and preview it in my browser without publishing it to the world. This really helps when I am editing posts on my mobile phone as it gives me a reliable preview so I can check for any markup mistakes.&lt;/p&gt;
&lt;p&gt;I also send out an approximately weekly &lt;a href="https://simonw.substack.com/"&gt;email newsletter&lt;/a&gt; version of my blog, for people who want to subscribe in their inbox. This is a straight copy of content from my blog - Substack doesn't have an API for this but their editor does accept copy and paste, so I have a delightful digital duct tape solution for assembling the newsletter which I described in &lt;a href="https://simonwillison.net/2023/Apr/4/substack-observable/"&gt;Semi-automating a Substack newsletter with an Observable notebook&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="more-people-should-do-this"&gt;More people should do this&lt;/h4&gt;
&lt;p&gt;I posted this on Bluesky &lt;a href="https://bsky.app/profile/simonwillison.net/post/3ldu6jywnos2j"&gt;last night&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I wish people would post more links to interesting things&lt;/p&gt;
&lt;p&gt;I feel like Twitter and LinkedIn and Instagram and TikTok have pushed a lot of people out of the habit of doing that, by penalizing shared links in the various "algorithms"&lt;/p&gt;
&lt;p&gt;Bluesky doesn't have that misfeature, thankfully!&lt;/p&gt;
&lt;p&gt;(In my ideal world everyone would get their own link blog too, but sharing links on Bluesky and Mastodon is almost as good)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sharing interesting links with commentary is a low effort, high value way to contribute to internet life at large.&lt;/p&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/django"&gt;django&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/django-admin"&gt;django-admin&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/john-gruber"&gt;john-gruber&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="blogging"/><category term="django"/><category term="django-admin"/><category term="john-gruber"/></entry><entry><title>Please publish and share more</title><link href="https://simonwillison.net/2024/Nov/2/please-publish-and-share-more/#atom-tag" rel="alternate"/><published>2024-11-02T15:17:07+00:00</published><updated>2024-11-02T15:17:07+00:00</updated><id>https://simonwillison.net/2024/Nov/2/please-publish-and-share-more/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://micro.webology.dev/2024/11/02/please-publish-and.html"&gt;Please publish and share more&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
💯 to all of this by Jeff Triplett:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Friends, I encourage you to publish more, indirectly meaning you should write more and then share it. [...]&lt;/p&gt;
&lt;p&gt;You don’t have to change the world with every post. You might publish a quick thought or two that helps encourage someone else to try something new, listen to a new song, or binge-watch a new series.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jeff shares my opinion on conclusions: giving myself permission to hit publish even when I haven't wrapped everything up neatly was a huge productivity boost for me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Our posts are done when you say they are. You do not have to fret about sticking to landing and having a perfect conclusion. Your posts, like this post, are done after we stop writing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And another 💯 to this footnote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PS: Write and publish before you write your own static site generator or perfect blogging platform. We have lost billions of good writers to this side quest because they spend all their time working on the platform instead of writing.&lt;/p&gt;
&lt;/blockquote&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jeff-triplett"&gt;jeff-triplett&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="jeff-triplett"/></entry><entry><title>Matt Webb's Colophon</title><link href="https://simonwillison.net/2024/Oct/29/matt-webbs-colophon/#atom-tag" rel="alternate"/><published>2024-10-29T04:59:47+00:00</published><updated>2024-10-29T04:59:47+00:00</updated><id>https://simonwillison.net/2024/Oct/29/matt-webbs-colophon/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://interconnected.org/home/2024/10/28/colophon"&gt;Matt Webb&amp;#x27;s Colophon&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I love a good colophon (&lt;a href="https://simonwillison.net/about/#about-site"&gt;here's mine&lt;/a&gt;, I should really expand it). Matt Webb has been publishing his thoughts online for 24 years, so his colophon is a delightful accumulation of ideas and principles.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So following the principles of web longevity, what matters is the data, i.e. the posts, and simplicity. I want to minimise maintenance, not panic if a post gets popular, and be able to add new features without thinking too hard. [...]&lt;/p&gt;
&lt;p&gt;I don’t deliberately &lt;a href="https://boringtechnology.club/"&gt;choose boring technology&lt;/a&gt; but I think a lot about &lt;a href="https://interconnected.org/home/2017/08/17/upsideclown"&gt;longevity on the web&lt;/a&gt; &lt;em&gt;(that’s me writing about it in 2017)&lt;/em&gt; and boring technology is a consequence.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'm tempted to adopt Matt's &lt;a href="https://github.com/genmon/aboutfeeds/blob/main/tools/pretty-feed-v3.xsl"&gt;XSL template&lt;/a&gt; that he uses to style &lt;a href="https://interconnected.org/home/feed"&gt;his RSS feed&lt;/a&gt; for my own sites.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/blogging"&gt;blogging&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/matt-webb"&gt;matt-webb&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rss"&gt;rss&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/xslt"&gt;xslt&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/boring-technology"&gt;boring-technology&lt;/a&gt;&lt;/p&gt;



</summary><category term="blogging"/><category term="matt-webb"/><category term="rss"/><category term="xslt"/><category term="boring-technology"/></entry></feed>