<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Field Notes</title>
    <link>http://localhost:3000/</link>
    <description>Notes on building software, published from markdown files.</description>
    <language>en</language>
    <lastBuildDate>Sun, 06 Sep 2026 00:00:00 GMT</lastBuildDate>
    <atom:link href="http://localhost:3000/feed.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Hello, Field Notes</title>
      <link>http://localhost:3000/hello-field-notes/</link>
      <guid isPermaLink="true">http://localhost:3000/hello-field-notes/</guid>
      <pubDate>Sun, 06 Sep 2026 00:00:00 GMT</pubDate>
      <category>meta</category>
      <category>writing</category>
      <description><![CDATA[What this site is, how it is built, and what to expect here.]]></description>
      <content:encoded><![CDATA[<p>This is a small site of notes: things learned while building software, written down before they are forgotten.</p>
      <h2 id="how-it-is-built">How it is built</h2>
      <p>Every post is a markdown file with a little YAML front matter at the top. The build reads the files, renders them once to HTML, and writes one static page per post — no server, no database, nothing to keep running.</p>
      <ul>
      <li>Posts live in <code>content/posts/</code></li>
      <li>The build runs <code>npm run build</code> and writes <code>dist/</code></li>
      <li><code>dist/</code> goes to any static host</li>
      </ul>
      <h2 id="what-to-expect">What to expect</h2>
      <p>Short notes, mostly. A longer piece now and then. Every post is also available as raw markdown at the same path with a <code>.md</code> extension, and there is an <a href="/feed.xml">RSS feed</a> if you would rather read from a feed reader.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>Writing the first draft fast</title>
      <link>http://localhost:3000/writing-the-first-draft-fast/</link>
      <guid isPermaLink="true">http://localhost:3000/writing-the-first-draft-fast/</guid>
      <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
      <category>writing</category>
      <category>process</category>
      <description><![CDATA[Why the first draft should be written in one sitting, and how to make that possible.]]></description>
      <content:encoded><![CDATA[<p>The first draft has one job: to exist. Everything else — structure, precision, the good sentence — comes from editing, and you cannot edit a blank page.</p>
      <h2 id="lower-the-bar-on-purpose">Lower the bar on purpose</h2>
      <p>Write badly, on purpose, and quickly. Leave placeholders like <em>[example here]</em> instead of stopping to find the example. Keep a list of questions at the bottom of the file instead of answering them inline.</p>
      <h2 id="separate-the-two-modes">Separate the two modes</h2>
      <p>Drafting and editing use different parts of the mind. Mixing them means doing both slowly. Draft in one sitting; edit tomorrow.</p>
      <blockquote>
      <p>The draft is for you. The edit is for the reader.</p>
      </blockquote>
      ]]></content:encoded>
    </item>
    <item>
      <title>A note on naming things</title>
      <link>http://localhost:3000/a-note-on-naming-things/</link>
      <guid isPermaLink="true">http://localhost:3000/a-note-on-naming-things/</guid>
      <pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate>
      <category>code</category>
      <category>craft</category>
      <description><![CDATA[Names are the cheapest documentation you will ever write.]]></description>
      <content:encoded><![CDATA[<p>A good name answers the question the reader was about to ask. A bad one makes them open the file.</p>
      <h2 id="three-tests">Three tests</h2>
      <ol>
      <li><strong>Could it mean something else?</strong> If a name fits two things, it describes neither.</li>
      <li><strong>Does it say what the thing is, not what it is near?</strong> <code>userHelper</code> is near users; <code>formatUserName</code> is a thing.</li>
      <li><strong>Would a stranger place it?</strong> Read the name out of context. If it needs the folder to make sense, it is not finished.</li>
      </ol>
      <pre><code class="language-ts">// before
      const data = await get(id)
      // after
      const invoice = await fetchInvoice(id)
      </code></pre>
      <p>Renaming is cheap early and expensive late — a published API name is forever.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>Keeping a changelog by hand</title>
      <link>http://localhost:3000/keeping-a-changelog-by-hand/</link>
      <guid isPermaLink="true">http://localhost:3000/keeping-a-changelog-by-hand/</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <category>process</category>
      <category>writing</category>
      <description><![CDATA[Generated changelogs list commits; a written one tells the reader what changed for them.]]></description>
      <content:encoded><![CDATA[<p>A generated changelog is a list of commits. A written one is a list of consequences: what a user can do now that they could not do before, and what they must change.</p>
      <h2 id="one-line-per-change-for-strangers">One line per change, for strangers</h2>
      <p>Write each entry for someone who has never seen the code. Say what changed and why it matters, in their words. Internal narrative — which gate was wrong, what confused whom — does not belong there.</p>
      <h2 id="keep-it-as-you-go">Keep it as you go</h2>
      <p>An entry written the day of the change takes a minute. The same entry reconstructed a month later takes an hour and is worse.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>The case for static sites</title>
      <link>http://localhost:3000/the-case-for-static-sites/</link>
      <guid isPermaLink="true">http://localhost:3000/the-case-for-static-sites/</guid>
      <pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate>
      <category>web</category>
      <category>meta</category>
      <description><![CDATA[A site that is only files has nothing to break at three in the morning.]]></description>
      <content:encoded><![CDATA[<p>A static site is a directory of files. That sentence is the whole operations manual.</p>
      <h2 id="what-you-give-up">What you give up</h2>
      <ul>
      <li>No per-request logic: personalisation happens in the browser or not at all.</li>
      <li>No database: content is files in the repository, edited like code.</li>
      </ul>
      <h2 id="what-you-get">What you get</h2>
      <ul>
      <li>Nothing to patch, restart, scale or back up.</li>
      <li>Every page is cacheable forever and served from the edge.</li>
      <li>The build is the only moving part, and it runs on your machine or in CI where you can watch it.</li>
      </ul>
      <p>For notes, documentation and most marketing pages, that trade is not close.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>Markdown is enough</title>
      <link>http://localhost:3000/markdown-is-enough/</link>
      <guid isPermaLink="true">http://localhost:3000/markdown-is-enough/</guid>
      <pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate>
      <category>writing</category>
      <category>web</category>
      <description><![CDATA[Plain text with a little structure outlives every editor that tried to replace it.]]></description>
      <content:encoded><![CDATA[<p>Every few years a new editor promises rich blocks, embeds and collaboration. Every few years the notes written in it become hard to move. The markdown files from fifteen years ago still open.</p>
      <h2 id="structure-you-can-see">Structure you can see</h2>
      <p>Headings, lists, emphasis, links and code — that is the structure of almost every document worth reading, and markdown spells each one with a character you can type.</p>
      <table>
      <thead>
      <tr>
      <th>Need</th>
      <th>Markdown</th>
      </tr>
      </thead>
      <tbody><tr>
      <td>A heading</td>
      <td><code>## Title</code></td>
      </tr>
      <tr>
      <td>Emphasis</td>
      <td><code>*this*</code></td>
      </tr>
      <tr>
      <td>A link</td>
      <td><code>[text](url)</code></td>
      </tr>
      <tr>
      <td>Code</td>
      <td>backticks</td>
      </tr>
      </tbody></table>
      <h2 id="everything-else-is-a-plugin">Everything else is a plugin</h2>
      <p>Tables, footnotes and task lists are extensions; use them when the renderer supports them and the text still reads without them.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>Reading logs before guessing</title>
      <link>http://localhost:3000/reading-logs-before-guessing/</link>
      <guid isPermaLink="true">http://localhost:3000/reading-logs-before-guessing/</guid>
      <pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate>
      <category>code</category>
      <category>debugging</category>
      <description><![CDATA[One observed value beats thirty minutes of plausible theories.]]></description>
      <content:encoded><![CDATA[<p>The most expensive debugging session is the one that starts with a theory. The cheapest starts with a log line.</p>
      <h2 id="start-at-the-entry-point">Start at the entry point</h2>
      <p>Print the actual input where it enters the system. Not what the docs say it should be — what it is. Half the bugs end right there.</p>
      <h2 id="then-work-inward">Then work inward</h2>
      <p>Follow the value one step at a time, printing as you go, until it stops being what you expect. That step is the bug. Everything before it was fine.</p>
      <pre><code class="language-ts">console.log(&#39;[handler] body =&#39;, JSON.stringify(req.body))
      </code></pre>
      <p>Delete the line afterwards. Keep the habit.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>Small commits</title>
      <link>http://localhost:3000/small-commits/</link>
      <guid isPermaLink="true">http://localhost:3000/small-commits/</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <category>process</category>
      <category>code</category>
      <description><![CDATA[The commit is the undo button; keep it within reach.]]></description>
      <content:encoded><![CDATA[<p>A commit is a point you can return to. Hours of uncommitted work is hours you cannot get back if the next command goes wrong.</p>
      <h2 id="one-logical-change">One logical change</h2>
      <p>If the message needs the word &quot;and&quot;, it is two commits. A reviewer can hold one idea in their head; a reverter can remove one idea without collateral.</p>
      <h2 id="commit-before-the-risky-step">Commit before the risky step</h2>
      <p>About to run a script over two hundred files? Commit first. Recovering from a bad sweep is a one-line <code>git revert</code> — if the good state was committed.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>Feeds still work</title>
      <link>http://localhost:3000/feeds-still-work/</link>
      <guid isPermaLink="true">http://localhost:3000/feeds-still-work/</guid>
      <pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate>
      <category>web</category>
      <category>meta</category>
      <description><![CDATA[RSS and Atom are the quietest, most durable way to publish.]]></description>
      <content:encoded><![CDATA[<p>No algorithm decides who sees a feed. A reader subscribes, the site publishes, and that is the entire relationship.</p>
      <h2 id="publish-both">Publish both</h2>
      <p>RSS 2.0 and Atom 1.0 are both a few hundred bytes of XML per post. Readers handle either, so publish both and let them choose. This site does: <a href="/feed.xml">feed.xml</a> and <a href="/atom.xml">atom.xml</a>.</p>
      <h2 id="put-the-whole-post-in-the-feed">Put the whole post in the feed</h2>
      <p>A feed that holds only the first paragraph trains readers to leave. Put the full text in; the reader who wants the page will click anyway.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>Tests for the next person</title>
      <link>http://localhost:3000/tests-for-the-next-person/</link>
      <guid isPermaLink="true">http://localhost:3000/tests-for-the-next-person/</guid>
      <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
      <category>code</category>
      <category>craft</category>
      <description><![CDATA[A test is a sentence about behaviour that a machine keeps true.]]></description>
      <content:encoded><![CDATA[<p>The best tests read like the documentation you wish existed: <em>a signed-up user can log out and log back in</em>. The name says what is true; the body proves it.</p>
      <h2 id="test-the-outcome-not-the-mechanism">Test the outcome, not the mechanism</h2>
      <p>A test that asserts a function was called passes when the function does the wrong thing. A test that asserts the result the user sees fails when it should.</p>
      <h2 id="anchor-to-something-visible">Anchor to something visible</h2>
      <p>For user interfaces, at least one assertion per test should touch the screen — a heading, a button, a URL. A suite that only hits the API stays green while the page is blank.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>Deploying a directory</title>
      <link>http://localhost:3000/deploying-a-directory/</link>
      <guid isPermaLink="true">http://localhost:3000/deploying-a-directory/</guid>
      <pubDate>Thu, 30 Jul 2026 00:00:00 GMT</pubDate>
      <category>web</category>
      <category>process</category>
      <description><![CDATA[How this site ships: build, then copy a folder.]]></description>
      <content:encoded><![CDATA[<p>The deploy for this site is two steps, and the second one is <code>cp</code>.</p>
      <h2 id="build">Build</h2>
      <pre><code class="language-sh">npm run build
      </code></pre>
      <p>The build type-checks, bundles the app, then prerenders every route to <code>dist/&lt;route&gt;/index.html</code> — in Node, with no browser involved — and writes the feeds, the sitemap and <code>llms.txt</code> next to them.</p>
      <h2 id="copy">Copy</h2>
      <p>Upload <code>dist/</code> to any static host. If the site lives under a sub-path, build with <code>BASE_PATH=/notes</code> and every link, asset and feed URL follows.</p>
      ]]></content:encoded>
    </item>
    <item>
      <title>What llms.txt is for</title>
      <link>http://localhost:3000/what-llms-txt-is-for/</link>
      <guid isPermaLink="true">http://localhost:3000/what-llms-txt-is-for/</guid>
      <pubDate>Sun, 26 Jul 2026 00:00:00 GMT</pubDate>
      <category>web</category>
      <category>meta</category>
      <description><![CDATA[A short index that tells a language model where the readable versions of your pages are.]]></description>
      <content:encoded><![CDATA[<p><code>llms.txt</code> is a plain-text file at the root of a site: a title, a line about the site, and a list of links to markdown versions of its pages.</p>
      <h2 id="why-markdown">Why markdown</h2>
      <p>A language model reading HTML spends most of its attention on navigation, scripts and markup. The same page as markdown is a tenth of the size and all signal.</p>
      <h2 id="this-site39s-copy">This site&#39;s copy</h2>
      <p>Every post here is served twice: as a page, and as the original markdown at <code>/&lt;slug&gt;.md</code>. <a href="/llms.txt">llms.txt</a> lists the markdown copies with a one-line description each.</p>
      ]]></content:encoded>
    </item>
  </channel>
</rss>