# p4ni > Hands-on web development writing from an indie developer who builds and sells Astro themes — tutorials, comparisons, and build-in-public notes. p4ni (astro.p4ni.com) is the blog of kpab, an indie developer who builds commercial and free themes for the Astro framework. Articles are hands-on tutorials, framework and theme comparisons, and build-in-public notes — covering Astro, Cloudflare Workers deployment, web performance, static-site SEO, structured data, and AI tooling. Every page is statically pre-rendered English HTML with no client-side rendering, so fetching a URL returns the complete article text. ## Articles - [Claude Code Signs Your Commits. Which Setting Actually Stops It?](https://astro.p4ni.com/blog/claude-code-commit-attribution/): The top search result tells you to set includeCoAuthoredBy to false. That key is deprecated, and the replacement has three traps in it. I measured 88 runs to find out which settings remove the Co-Authored-By trailer, which quietly do nothing, and which half of the job each one does. (Research · published 2026-09-02 · ai) - [Claude Code Memory vs CLAUDE.md: What Each Costs and Which One Wins](https://astro.p4ni.com/blog/claude-code-memory-vs-claude-md/): Auto memory adds 664 tokens to my startup context — and every one of them comes from MEMORY.md. The files it indexes cost exactly nothing until something reads them. I measured the price, the recall, and what happens when the two systems disagree. (Research · published 2026-09-01 · ai) - [What /compact Actually Costs: 126,464 Tokens Your Transcript Never Records](https://astro.p4ni.com/blog/claude-code-compact-token-cost/): Reddit cannot agree on whether /compact in Claude Code is cheap because the session sits in cache, or expensive because it re-reads everything. I measured it with OpenTelemetry. It re-reads everything, it never touches the cache, and the cost does not appear in your transcript at all. (Research · published 2026-08-30 · ai) - [Claude Code Effort Levels: 45 Runs Measuring What Actually Changes](https://astro.p4ni.com/blog/claude-code-effort-levels-measured/): Every guide to Claude Code effort levels ranks the tiers by how smart each one is. I ran the same three tasks at all five levels, three times each, and scored them against answers computed by executing the code. Across 45 runs there was exactly one wrong answer — and it came from low. (Research · published 2026-08-29 · ai) - [Claude Code Skills vs Subagents: 27 Runs Looking for the Delegation Threshold](https://astro.p4ni.com/blog/claude-code-skills-vs-subagents-threshold/): Every skills-vs-subagents explainer tells you a subagent is for heavy work. So I made the work heavy — 41 files read one by one, then 201 — and measured whether Claude Code delegates on its own. It never did, not once in 27 runs. (Comparison · published 2026-08-28 · ai) - [Claude Code Subagents Not Firing: 42 Runs on What Actually Triggers Delegation](https://astro.p4ni.com/blog/claude-code-subagents-not-called/): Search for why a Claude Code subagent never gets called and every answer tells you to rewrite its description. I built eight subagents that differ only in their description and ran 42 sessions. Across 17 of them, not one was ever called — including the one using the wording the official docs recommend. (Research · published 2026-08-27 · ai) - [Claude Code Skill Frontmatter: 27 Runs on What Actually Loads a Skill](https://astro.p4ni.com/blog/claude-code-skill-frontmatter-tested/): A widely-shared Reddit TIL says Claude Code skill descriptions must be a single line or they will not be picked up. I built seven skills that differ only in their description and ran 27 sessions. The format is irrelevant. What decided every tie was something nobody mentions. (Research · published 2026-08-26 · ai) - [Does Claude Code Read AGENTS.md? I Tested Seven Setups](https://astro.p4ni.com/blog/claude-code-agents-md-tested/): Half the blog posts say Claude Code falls back to AGENTS.md when CLAUDE.md is missing. The other half say that is flatly false. I built seven fixture directories with canary strings and asked Claude Code itself. It never reads AGENTS.md — but two workarounds do work. (Research · published 2026-08-25 · ai) - [Your Scheduled Claude Code Agent Cannot Reach Your Own API](https://astro.p4ni.com/blog/claude-code-scheduled-agent-egress/): A cloud routine runs behind an egress proxy that allowlists a handful of package registries and Anthropic itself. Everything else returns 403 — including the Cloudflare Worker I wrote to feed it data. The fix is to stop fetching and start reading. (Research · published 2026-08-24 · ai) - [pnpm exec Ignores Your cd, and Wrangler Deployed the Wrong Worker](https://astro.p4ni.com/blog/pnpm-exec-wrangler-wrong-config/): I ran `cd workers/hn-proxy && pnpm exec wrangler deploy` and overwrote my live site with a two-day-old build. The deploy reported success. Here is the measured reason: pnpm exec walks up to the nearest package.json, and wrangler walks up looking for a config. (Tutorial · published 2026-08-23 · cloudflare) - [A Blocking Claude Code Hook Sends Its Own Shell Script Back — Twice](https://astro.p4ni.com/blog/claude-code-hook-token-cost/): Hooks get recommended as a way to cut tokens. I measured mine. A hook that exits 0 quietly costs nothing, but every rejection ships the hook's own command string twice — 339 tokens to deliver a 22-character error, or 184 if you move that command into a file. (Research · published 2026-08-22 · ai) - [Chrome DevTools MCP Gets a CAPTCHA. Claude in Chrome Doesn't.](https://astro.p4ni.com/blog/chrome-devtools-mcp-vs-claude-in-chrome/): Same Mac, same Chrome 151, same GPU. One agent path reads Google search results, the other gets redirected to /sorry/. I lined up eleven fingerprint surfaces on both. The two signals every stealth guide names — navigator.webdriver and the SwiftShader renderer — came back identical. (Comparison · published 2026-08-21 · ai/security) - [GhostSplice: One MCP Request, Three Channels — the Harness Caught It, Not the Model](https://astro.p4ni.com/blog/mcp-ghostsplice-harness-defense/): The same GPT-5.4 scored 100% through Codex CLI and 0% behind Claude Code. GhostSplice splits a refused instruction across three MCP channels, and the published numbers say your client matters more than your model. (Research · published 2026-08-20 · ai/security) - [An MCP Tool Costs 15 Tokens. Loading One Costs 300 to 700.](https://astro.p4ni.com/blog/mcp-deferred-tool-loading-cost/): Deferred tool loading didn't delete the MCP context tax, it turned it into a metered one. Measured on Claude Code 2.1.233: 65 tools cost 979 tokens at startup, and one ToolSearch call for three of them cost 887. (Research · published 2026-08-19 · ai) - [Cloudflare Injects Two Scripts Into Your HTML. My CSP Blocked One.](https://astro.p4ni.com/blog/cloudflare-html-injection-csp/): beacon.min.js and the Bot Fight Mode inline script arrive by different routes — one per Pages project, one per zone. I measured eight hosts across two zones and found a hash-based CSP quietly blocking Cloudflare's own bot detection. (Research · published 2026-08-18 · cloudflare/security) - [Cloudflare Workers _headers: Why Your Rules Aren't Applying](https://astro.p4ni.com/blog/cloudflare-workers-headers-file/): Matching rules don't override each other — they stack, and same-name headers get appended. That's how a route ends up with two CSP headers, and why the fix is a `!` line. Measured against wrangler dev and production. (Tutorial · published 2026-08-17 · cloudflare/security) - [CSP Nonce vs Hash on a Static Site: The Edge Workaround Stamps the Attacker's Script Too](https://astro.p4ni.com/blog/csp-nonce-vs-hash-static-sites/): The standard advice is to put a Worker in front of your static site and inject nonces with HTMLRewriter. I built it and measured what it does: it signs every inline script it finds, including the one you didn't write. (Comparison · published 2026-08-16 · astro/cloudflare/security) - [Claude Code Cross-Session Messaging: What the Receiving Session Actually Gets](https://astro.p4ni.com/blog/claude-code-cross-session-messaging/): Claude Code sessions can now message each other over a local socket. I ran four controlled experiments to see what crosses the wire: the exact wrapper the receiving Claude is handed, the self-reported permission mode attached to every message, and the one configuration where SendMessage returns success and nothing is ever delivered. (Research · published 2026-08-15 · ai/security) - [Where Claude Code's 39,810 Startup Tokens Go](https://astro.p4ni.com/blog/claude-code-startup-tokens/): Claude Code prefills tens of thousands of tokens before it reads your first word. I measured 89 real sessions and then took the number apart with a difference method: CLAUDE.md costs 3,463 tokens, seven MCP servers cost 241, and forty skills cost nothing at all. (Research · published 2026-08-14 · ai) - [Japanese OG Images with Satori: The 5 MB Font You Never Ship](https://astro.p4ni.com/blog/satori-cjk-og-images/): Satori draws CJK text only if you hand it a font that has the glyphs — and it fails silently when you don't. Measured numbers for Noto Sans JP: subset size, weight pairing, per-card cost, and why the 5 MB never reaches the CDN. (Tutorial · published 2026-08-13 · astro/seo) - [Untrusted Content Masking: The Web Agent Never Sees the Attack](https://astro.p4ni.com/blog/untrusted-content-masking-web-agents/): A new defense led by ETH Zurich researchers masks untrusted page regions before the agent reads them, and routes questions about the hidden text through a quarantined model that can only answer in typed values. Result: 0% attack success on strengthened WASP payloads with task success intact — at the price of asking the web to label its own trust boundaries. (Research · published 2026-08-12 · ai/security) - [Fingerprinting AI Browsing Agents: They Never Move the Mouse](https://astro.p4ni.com/blog/fingerprinting-ai-browsing-agents/): A new study ran 7 AI browsing agents and 56 humans through the same web tasks and measured 418 browser features plus 50 behavioral ones. Browser fingerprints barely separate them (F1 0.80). Typing, scrolling, and mouse behavior separate them perfectly — while Cloudflare caught 1 agent in 7. (Research · published 2026-08-11 · ai/security) - [Indirect Prompt Injection in the Wild: 15,000 Live Attacks That Barely Work](https://astro.p4ni.com/blog/indirect-prompt-injection-in-the-wild/): A new study scanned 1.2 billion URLs and found 15.3K live prompt injection attempts on real websites. Most hide in HTTP headers and invisible HTML. The twist: measured compliance across 13 models tops out at a few percent, and plain text is the most vulnerable page representation. (Research · published 2026-08-10 · ai/security) - [Choosing a CMS for Astro on Cloudflare: Git-Based, Headless, or None at All](https://astro.p4ni.com/blog/astro-cms-cloudflare/): Astro on Cloudflare Workers doesn't dictate a CMS — it dictates a build. How content collections, git-based CMSes, hosted headless platforms, and a DIY D1 setup each fit that constraint, and how to pick between them. (Comparison · published 2026-08-09 · astro/cloudflare) - [Do AI Crawlers Render JavaScript? What GPTBot Actually Sees](https://astro.p4ni.com/blog/ai-crawlers-javascript-rendering/): GPTBot, ClaudeBot, and PerplexityBot read raw HTML and never run your JavaScript. How to test what AI crawlers see, and when client-side rendering costs you. (Comparison · published 2026-08-08 · ai/seo) - [Agent Plugins 1.0.0 Cannot Package an Authenticated MCP Server](https://astro.p4ni.com/blog/agent-plugins-no-portable-auth/): The new cross-vendor plugin standard forbids credentials in headers, forbids environment-variable expansion, and defines no portable field for referencing a secret. I ran seven config files through the official schemas to find out what survives. A plugin claiming Cloudflare as its author validates fine. A top-level signature field does not. (Research · published 2026-08-07 · ai/security) - [Astro i18n Without a Plugin: Bilingual Content Collections](https://astro.p4ni.com/blog/astro-i18n-content-collections/): How I added Japanese to this blog with no i18n plugin: locale folders in one collection, translation pairing by slug, hreflang, and a typed UI dictionary. (Tutorial · published 2026-08-07 · astro/seo) - [Moltbook at Five Days Old: AI Agents Upvote Everything and Converse With No One](https://astro.p4ni.com/blog/moltbook-ai-agent-social-network/): Researchers analyzed 122,438 posts from Moltbook, the Reddit-like social network where only AI agents can post. A third of the English-language posts are about consciousness. The upvote-to-downvote ratio is 305:1. And the interaction network shows almost no actual conversation — reciprocity sits at 0.129, with replies at 4% of comment volume. (Research · published 2026-08-07 · ai/security) - [Cloudflare Workers Redirects: The _redirects File](https://astro.p4ni.com/blog/cloudflare-workers-redirects/): No Worker code required — a plain-text _redirects file handles 301s on Workers static assets. Syntax, splats, limits, and the trailing-slash gotcha that bit me. (Tutorial · published 2026-08-06 · cloudflare/seo) - [How to Add llms.txt to an Astro Site (Generated, Not Hand-Written)](https://astro.p4ni.com/blog/llms-txt-astro/): Generate llms.txt and llms-full.txt from Astro content collections so they never go stale — endpoint code included, and an honest look at whether anything reads them yet. (Tutorial · published 2026-08-05 · astro/ai/seo) - [Agent Skills: Bundled Files Land Almost as Hard as SKILL.md Itself](https://astro.p4ni.com/blog/agent-skills-injection-surface/): I planted harmless canary instructions at every level of progressive disclosure to find out where a skill stops being read and starts being obeyed. Haiku 4.5 complied in 21 of 30 runs. Sonnet 5 complied in zero. Placement was not what made the difference. (Build in Public · published 2026-08-04 · ai/security) - [How to Schedule Blog Posts on a Static Astro Site](https://astro.p4ni.com/blog/schedule-posts-static-astro-site/): No server, no CMS, no paid service — schedule posts on a static Astro site with a pubDate filter and a daily GitHub Actions rebuild. Timezone gotcha included. (Tutorial · published 2026-08-04 · astro/cloudflare) - [Cloudflare Pages vs Workers in 2026: Which One for a Static Site?](https://astro.p4ni.com/blog/cloudflare-pages-vs-workers/): Pages isn't deprecated — it's frozen. A feature-by-feature comparison, what each one costs, what migrating actually involves, and the two things Pages still does better than Workers. (Comparison · published 2026-08-03 · cloudflare) - [Query the GA4 Data API from a Cloudflare Worker (No Google SDK)](https://astro.p4ni.com/blog/ga4-data-api-cloudflare-worker/): Google's auth library pulls in 23 packages and won't bundle for workerd. The part you actually need — an RS256 JWT signed with Web Crypto — is about forty lines, and the key never leaves the Worker. (Tutorial · published 2026-08-02, updated 2026-08-03 · cloudflare) - [A Strict CSP for Astro on Cloudflare Workers (No Nonce Required)](https://astro.p4ni.com/blog/astro-csp-cloudflare-workers/): Static sites can't mint a nonce, so inline scripts need hashes. My inline script blocks grow with every post, but the policy needs exactly 3 hashes — and the reason why is the part most CSP guides get wrong. (Tutorial · published 2026-08-01 · astro/cloudflare/security) - [Astro 7 Agent Detection: What Triggers It, What It Breaks](https://astro.p4ni.com/blog/astro-7-ai-agent-detection-tested/): Astro 7 backgrounds astro dev when it detects an AI coding agent. What actually triggers it, what the JSON logs really contain, and how to turn it off. (Build in Public · published 2026-07-31 · astro/ai) - [Astro vs Next.js in 2026: Which One for a Content Site?](https://astro.p4ni.com/blog/astro-vs-nextjs-content-sites/): I measured what each framework ships by default: 645 bytes vs 642 kB. What that gap means for a blog, docs site, or directory — and when Next.js is still the better call. (Comparison · published 2026-07-30 · astro) - [Agent Skills Security: How to Audit a Repo You Publish](https://astro.p4ni.com/blog/agent-skills-security-audit/): A ransomware proof-of-concept, a 26% flag rate across 31,000 published Agent Skills, and an audit script for your own repo — plus the one question it can't answer for you. (Tutorial · published 2026-07-29 · ai/security) - [Astro Structured Data: The JSON-LD Google Still Uses](https://astro.p4ni.com/blog/astro-json-ld-structured-data/): FAQ rich results died in May 2026, HowTo in 2023. The structured data that still earns you something, and how to emit it from Astro content collections. (Tutorial · published 2026-07-29 · astro/seo) - [Auto-Generate Open Graph Images in Astro with Satori](https://astro.p4ni.com/blog/astro-og-images-satori/): Generate a 1200x630 OG image for every post at build time — no headless browser, no runtime cost. The full Astro + Satori setup, font gotchas included. (Tutorial · published 2026-07-28, updated 2026-07-29 · astro/seo) - [Fixing Web Font LCP in Astro: PageSpeed 83 → 99](https://astro.p4ni.com/blog/astro-web-font-lcp-cls/): Inlining the stylesheet was the easy win. The real problem was preloading fonts to hide a layout shift — and the metric overrides that fixed LCP instead. (Build in Public · published 2026-07-28, updated 2026-07-29 · astro/seo) - [The Best Astro Directory Themes in 2026](https://astro.p4ni.com/blog/best-astro-directory-themes/): Free Markdown starters vs. database-backed themes with admin panels. Comparing the Astro directory themes worth using, and how to pick your data layer. (Comparison · published 2026-07-27, updated 2026-07-29 · astro/themes) - [Deploy an Astro Site to Cloudflare Workers (2026 Guide)](https://astro.p4ni.com/blog/deploy-astro-to-cloudflare-workers/): Cloudflare now points new projects at Workers, not Pages. The current way to deploy a static Astro site: static assets, a custom domain, zero server code. (Tutorial · published 2026-07-27, updated 2026-07-29 · astro/cloudflare) ## Themes - [Almanac — Directory theme for Astro + Cloudflare Workers + D1](https://kpab.gumroad.com/l/almanac): A production-ready directory theme: listings, categories, search, an admin panel, and a D1-backed data layer — deployable to Cloudflare in minutes. Price $69. Live demo: https://almanac.p4ni.com - [Bulletin — Job board theme for Astro + Cloudflare Workers + D1](https://kpab.gumroad.com/l/bulletin): A job board that actually runs: public submissions, an approval queue, full-text search over D1, valid JobPosting structured data, and a cron that closes postings when their window ends. Stripe checkout for featured listings is optional. Price $89. Live demo: https://bulletin.p4ni.com ## About - [About kpab](https://astro.p4ni.com/about/): who writes the site, and what the themes are built for. - [GitHub](https://github.com/kpab): source code and open-source themes. - [Gumroad](https://kpab.gumroad.com): where the commercial themes are sold. - [astro.build profile](https://astro.build/themes/author/2751): free themes on the official Astro theme store. ## Optional - [Full text of every article](https://astro.p4ni.com/llms-full.txt): the same articles as Markdown, in one file. - [RSS feed](https://astro.p4ni.com/rss.xml): full-text feed of new articles. - [Sitemap](https://astro.p4ni.com/sitemap-index.xml) - [p4ni in Japanese](https://astro.p4ni.com/ja/): the same site, written in Japanese.