Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ node_modules
package-lock.json

# Bilingual blog prose — avoid Prettier reflowing/mangling content mixed with JSX.
src/content/blog/*.mdx
src/content/**/*.mdx
14 changes: 7 additions & 7 deletions CLAUDE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"verify": "npm run format:check && npm run check && npm run build && npm test",
"art": "node scripts/generate-art.mjs",
"bitcoin-epochs": "node scripts/generate-bitcoin-epochs.mjs",
"offchain-pseudo": "node scripts/generate-offchain-pseudo.mjs src/lib/offchain-revenue-jan2023.json",
"offchain-pseudo": "node scripts/generate-offchain-pseudo.mjs src/content/posts/bitcoin/offchain-revenue-jan2023.json",
"test": "tsx --test src/**/*.test.ts"
},
"dependencies": {
Expand Down
23 changes: 14 additions & 9 deletions scripts/generate-art.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/**
* Turns a full-size master in `art-src/` into the one committed webp the site
* builds from, in `src/assets/`.
* builds from, in `src/assets/`. Subdirectories are mirrored, so a master at
* `art-src/bitcoin/bg.png` becomes `src/assets/bitcoin/bg.webp` — one folder
* per post, matching `src/content/posts/`.
*
* Why this exists rather than handing the master to Astro: a master is tens of
* megabytes of lossless pixels, and committing one puts it in git history
Expand All @@ -18,7 +20,7 @@
* npm run art # every master, default quality
* npm run art -- --quality 100 # lossless-ish, bigger file
* npm run art -- --sizes 1920 # a different stage width
* npm run art -- bitcoin # just one master, by name
* npm run art -- bitcoin/bg # just one master, by path
*/
import { mkdir, readdir, stat, writeFile } from "node:fs/promises";
import path from "node:path";
Expand Down Expand Up @@ -64,11 +66,14 @@ const kb = (bytes) => `${Math.round(bytes / 1024)} KB`;

const { names, quality, sizes } = parseArgs(process.argv.slice(2));

const entries = (await readdir(SRC_DIR)).filter(
(file) =>
MASTERS.test(file) &&
(names.length === 0 || names.includes(path.parse(file).name)),
);
const entries = (await readdir(SRC_DIR, { recursive: true }))
.map((file) => file.split(path.sep).join("/"))
.filter((file) => {
if (!MASTERS.test(file)) return false;
if (names.length === 0) return true;
const stem = file.replace(MASTERS, "");
return names.some((name) => name === stem || name === path.basename(stem));
});

if (entries.length === 0) {
console.error(
Expand All @@ -79,12 +84,12 @@ if (entries.length === 0) {
process.exit(1);
}

await mkdir(OUT_DIR, { recursive: true });
console.log(`webp q${quality} · widths ${sizes.join(", ")}`);

for (const file of entries) {
const name = path.parse(file).name;
const name = file.replace(MASTERS, "");
const source = path.join(SRC_DIR, file);
await mkdir(path.join(OUT_DIR, path.dirname(name)), { recursive: true });
const master = await stat(source);
console.log(`\n${name} (master ${kb(master.size)})`);

Expand Down
4 changes: 2 additions & 2 deletions scripts/generate-bitcoin-epochs.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node
/**
* Updates src/lib/bitcoin-epochs.json — one row per *finished* halving epoch,
* Updates src/content/posts/bitcoin/epochs.json — one row per *finished* halving epoch,
* aggregated from public history, plus the average BTC/USD needed to say what
* that epoch's own tx fees were worth at the time.
*
Expand Down Expand Up @@ -45,7 +45,7 @@ import { access, readFile, writeFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";

const OUT = fileURLToPath(
new URL("../src/lib/bitcoin-epochs.json", import.meta.url),
new URL("../src/content/posts/bitcoin/epochs.json", import.meta.url),
);
// The protocol's own constants — a halving every 210,000 blocks, subsidy
// halving each time from 50 BTC. Deriving epoch heights and subsidies from
Expand Down
File renamed without changes
File renamed without changes.
4 changes: 2 additions & 2 deletions src/components/diagrams/BitcoinCoin3D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import {
} from "@react-three/drei";
// Imported as a URL rather than served from public/ so the build fingerprints
// it and fails loudly if the file ever moves.
import modelUrl from "@/assets/bitcoin.glb?url";
import modelUrl from "@/assets/bitcoin/coin.glb?url";

/**
* A downloaded bitcoin coin model (src/assets/bitcoin.glb — a Sketchfab export
* A downloaded bitcoin coin model (src/assets/bitcoin/coin.glb — a Sketchfab export
* with baked baseColor/metallicRoughness/normal maps already built in, so no
* custom material work is needed) rendered with a small studio lighting rig
* for a polished-metal look. Drag to orbit the camera via OrbitControls;
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "Pools, farms and miners"
date: "2026-07-28"
feat: true
tags: ["bitcoin", "crypto", "cryptocurrency"]
stageImage: "../../assets/bitcoin-bg.webp"
stageImage: "../../../assets/bitcoin/bg.webp"
color: "#F7941D"
stageTone: "dark"
---
Expand Down
Loading