<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Cedar Piano</title>
    <link>https://cedarpiano.fyi/</link>
    <description>Recent content on Cedar Piano</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <copyright>Public domain (CC0)</copyright>
    <lastBuildDate>Sat, 03 Oct 2026 10:00:00 +0200</lastBuildDate>
    <atom:link href="https://cedarpiano.fyi/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Setting Up a Meshtastic Node on Wi-Fi from the Linux Command Line</title>
      <link>https://cedarpiano.fyi/posts/meshtastic/</link>
      <pubDate>Sat, 03 Oct 2026 10:00:00 +0200</pubDate>
      <guid>https://cedarpiano.fyi/posts/meshtastic/</guid>
      <description>&lt;p&gt;This tutorial flashes a Meshtastic node — a Heltec WiFi LoRa 32 V3 in my
case — puts it on a Wi-Fi network, and manages it from Linux with the
&lt;code&gt;meshtastic&lt;/code&gt; and &lt;code&gt;esptool&lt;/code&gt; CLIs. Both run through &lt;code&gt;uvx&lt;/code&gt;, so nothing is
installed globally; uv downloads and caches them on first use.&lt;/p&gt;
&lt;p&gt;There are two ways to run the node:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;Wi-Fi (the main path here)&lt;/th&gt;
					&lt;th&gt;Bluetooth + phone (see &lt;a href=&#34;#10-use-case-follow-along-on-your-phone-bluetooth&#34;&gt;Section 10&lt;/a&gt;)&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Best for&lt;/td&gt;
					&lt;td&gt;A fixed node at home: base station, rooftop, gateway&lt;/td&gt;
					&lt;td&gt;A portable node you carry, controlled from the phone app&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;How you reach it&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;--host &amp;lt;ip&amp;gt;&lt;/code&gt; from any computer on the LAN, web client, phone app over the network&lt;/td&gt;
					&lt;td&gt;Meshtastic app over Bluetooth&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Internet / public map&lt;/td&gt;
					&lt;td&gt;Direct, no phone needed&lt;/td&gt;
					&lt;td&gt;Through the phone app, only while it is connected&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Location&lt;/td&gt;
					&lt;td&gt;Fixed position&lt;/td&gt;
					&lt;td&gt;Phone&amp;rsquo;s GPS&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;On ESP32 boards, Meshtastic cannot run Wi-Fi and Bluetooth at the same
time.&lt;/strong&gt; Turning Wi-Fi on disables Bluetooth.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Adding a Tip Jar to a Webpage</title>
      <link>https://cedarpiano.fyi/posts/tipjar-webpage/</link>
      <pubDate>Sat, 15 Aug 2026 11:30:00 +0200</pubDate>
      <guid>https://cedarpiano.fyi/posts/tipjar-webpage/</guid>
      <description>&lt;p&gt;The previous tutorials drove the &lt;code&gt;TipJar&lt;/code&gt; contract entirely from the shell. This
one puts it behind a webpage: a Connect button, a tip form, a live balance, and
a withdraw button that only appears for the owner.&lt;/p&gt;
&lt;p&gt;The browser flow is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Webpage → ethers.js → MetaMask → Anvil → TipJar contract
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;MetaMask holds the keys and signs the transactions. &lt;strong&gt;No private key goes
anywhere near the JavaScript.&lt;/strong&gt; Frontend source is visible to anyone who visits
the page, so a key in it is a key you have given away.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Invariant Testing with Foundry</title>
      <link>https://cedarpiano.fyi/posts/invariant-testing-foundry/</link>
      <pubDate>Sat, 15 Aug 2026 11:00:00 +0200</pubDate>
      <guid>https://cedarpiano.fyi/posts/invariant-testing-foundry/</guid>
      <description>&lt;p&gt;Unit tests check that a function does what you expected. Invariant tests check
something harder: that a property of your contract holds no matter what anybody
does to it. This tutorial writes both kinds against a &lt;code&gt;TipJar&lt;/code&gt; contract, watches
the invariant catch a bug every unit test missed, and then shows why the
obvious invariant is still wrong.&lt;/p&gt;
&lt;p&gt;It follows on from
&lt;a href=&#34;https://cedarpiano.fyi/posts/smart-contract-foundry/&#34;&gt;Writing a Smart Contract with Foundry&lt;/a&gt;, and
picks up exactly where that one ends. Its sibling,
&lt;a href=&#34;https://cedarpiano.fyi/posts/tipjar-webpage/&#34;&gt;Adding a Tip Jar to a Webpage&lt;/a&gt;, takes the same contract
in the other direction and puts a browser frontend on it. Neither depends on the
other.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Writing a Smart Contract with Foundry</title>
      <link>https://cedarpiano.fyi/posts/smart-contract-foundry/</link>
      <pubDate>Sat, 15 Aug 2026 10:30:00 +0200</pubDate>
      <guid>https://cedarpiano.fyi/posts/smart-contract-foundry/</guid>
      <description>&lt;p&gt;This tutorial writes, tests, deploys, and drives a &lt;code&gt;TipJar&lt;/code&gt; smart contract
entirely from the command line.&lt;/p&gt;
&lt;p&gt;It follows on from
&lt;a href=&#34;https://cedarpiano.fyi/posts/ethereum-command-line/&#34;&gt;Ethereum from the Command Line&lt;/a&gt;, which covers
Anvil, accounts, transactions, and blocks. You do not have to have read it —
the Prerequisites below get you to the same starting point — but it explains
most of what this one assumes. Two tutorials follow on from this one:
&lt;a href=&#34;https://cedarpiano.fyi/posts/tipjar-webpage/&#34;&gt;Adding a Tip Jar to a Webpage&lt;/a&gt; puts a frontend on the
contract, and &lt;a href=&#34;https://cedarpiano.fyi/posts/invariant-testing-foundry/&#34;&gt;Invariant Testing with Foundry&lt;/a&gt;
tests it harder.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Ethereum from the Command Line</title>
      <link>https://cedarpiano.fyi/posts/ethereum-command-line/</link>
      <pubDate>Sat, 15 Aug 2026 10:00:00 +0200</pubDate>
      <guid>https://cedarpiano.fyi/posts/ethereum-command-line/</guid>
      <description>&lt;p&gt;This tutorial explores an Ethereum blockchain entirely from the shell —
accounts, transactions, blocks, gas, and units — using a local test chain and
then the real network. There is no Solidity here, and no frontend.&lt;/p&gt;
&lt;p&gt;Writing and deploying a contract is the subject of the follow-up,
&lt;a href=&#34;https://cedarpiano.fyi/posts/smart-contract-foundry/&#34;&gt;Writing a Smart Contract with Foundry&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;ethereum&#34;&gt;Ethereum&lt;/h2&gt;
&lt;p&gt;A blockchain is a shared, append-only ledger that nobody owns. What makes one
&lt;em&gt;programmable&lt;/em&gt; is the ability to put code on it — a &lt;strong&gt;smart contract&lt;/strong&gt;, which is
a program with its own address, its own storage, and its own balance. Once
deployed, it runs exactly as written for anyone who calls it, and no single
party can quietly change it or stop it.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
