Skip to content
BitcoinOrdinalsWeb3Developer Guide

Recursive Inscriptions and On-Chain Composability on Bitcoin: A Developer Guide

Updated Feb 28, 2026/15 min read

A technical guide for engineers evaluating Bitcoin Ordinals. Covers recursive inscriptions, on-chain composability, game-state coordination, real-world architecture patterns from Pizza Ninjas and Pizza Pets, and tradeoffs vs. EVM/Solana.

What Recursive Inscriptions Actually Are

A standard inscription embeds its content directly in a Bitcoin transaction's witness data. An image, a JSON file, an HTML document — whatever you inscribe is self-contained. That works fine for static assets, but it has an obvious scaling problem: every piece of data you need must be re-inscribed from scratch. If you have 10,000 PFPs and each one shares 40KB of base artwork, you either duplicate that 40KB ten thousand times or you accept that each item is entirely self-contained with no shared state.

Recursive inscriptions solve this by letting an inscription reference existing on-chain data instead of re-inscribing it. The syntax is straightforward — from within an inscription (HTML, JavaScript, SVG), you point to another inscription using a URL path like /content/<inscription_id>. The ord indexer resolves that reference and serves the content. You're essentially building a content-addressed filesystem directly on Bitcoin, where inscriptions can import from each other the way a web page imports a stylesheet.

This flipped the architecture model for Ordinals collections. Instead of monolithic inscriptions that contain everything, you can now build in layers:

  • Layer 0: Base assets, shared libraries, rendering engines — inscribed once
  • Layer 1: Trait assets, component images, audio — inscribed per-category, not per-token
  • Layer 2: Token metadata files that reference Layer 0 and Layer 1 by inscription ID
  • Layer 3: Compositing logic — an HTML/JS inscription that assembles the final render from references

The key constraint to understand: this is reference resolution at indexer time, not at transaction time. Bitcoin has no native execution environment. The ord indexer handles the /content/ endpoint, and clients (wallets, marketplaces) call that endpoint when they need to render something. The chain itself just stores bytes. It does not run your code.

This is not a limitation to paper over — it's a fundamental property that shapes everything about how you architect on Ordinals.

Why This Matters for Collections and Games

Before recursion shipped (early 2023), the only way to do dynamic traits was to inscribe a new version of an asset every time something changed. That's expensive, slow, and introduces indexing complexity around which version is "canonical."

With recursion, your token inscription can be a thin HTML file that calls out to trait data inscribed separately, passes in block height or some other chain-verifiable signal, and renders differently based on that signal — all without touching the original inscription.

Pizza Ninjas (1,500-piece Ordinals blue-chip) used exactly this pattern. Certain traits were designed to evolve based on block height — as Bitcoin's chain progressed, the rendering logic would produce a different visual output for the same token. The inscription itself never changes. The block height is an external, trustless, universally verifiable input. Any client rendering the inscription at block 850,000 sees the same result as any other client at that block height, because they're all running the same on-chain logic against the same on-chain state.

This matters for collections for three reasons:

  1. Trustless dynamism. Nobody can fake the block height. There's no oracle, no signed message from the team, no centralized "trait reveal" server that can go offline or lie. The Bitcoin chain is the source of truth.
  2. Storage efficiency. Shared trait assets inscribed once can be referenced by thousands of tokens. For a 10,000-piece collection with 100 trait categories, you might inscribe 100 trait files instead of embedding everything in each token.
  3. Upgradeable compositing. If your compositing logic is in a separate inscription referenced by tokens, you can inscribe an updated renderer and — if your tokens reference a "pointer" inscription rather than the renderer directly — update the pointer to point at the new renderer. This is the closest thing to upgradeable logic that Bitcoin natively allows.

Technical Architecture

Here's how to structure a recursive inscription pipeline from scratch.

Step 1: Inscribe your primitive layer first.

Anything shared across the collection should be inscribed before you inscribe individual tokens. This includes: base image layers, shared JavaScript libraries (p5.js, three.js, or a custom rendering engine), font files, audio clips, and trait sprite sheets. Every one of these gets an inscription ID that you'll reference later. Keep a manifest — a JSON file mapping semantic names to inscription IDs. You'll reference this constantly.

Step 2: Inscribe trait assets as separate inscriptions.

Each distinct trait value (background color, weapon, clothing) should be its own inscription. This is not strictly required — you can embed everything in the compositing layer — but it enables the storage efficiency benefits and lets you reuse traits across collections or update individual traits without touching others.

Step 3: Write your compositing inscription.

This is the HTML/JS file that references everything above it. It:

  • Imports the rendering library via /content/<library_inscription_id>
  • Loads trait data based on the token's metadata
  • Assembles the final output

The compositing inscription for individual tokens is typically minimal. It passes a seed or token ID to the shared renderer, and the renderer does the heavy lifting. Example structure:

<script src="/content/RENDERER_INSCRIPTION_ID"></script>
<script>
  render({ tokenId: 42, blockHeight: window.__ord_block_height });
</script>

Step 4: Inscribe token metadata files.

Each token gets a JSON inscription with its trait assignments, which the compositing HTML references. This is where you encode the immutable properties of each token at mint time.

Step 5: Inscribe the final token HTML files.

These reference everything above. Ideally they're small — just enough to bootstrap the render by importing the compositing layer and passing the right token ID.

Block height injection. The ord server injects window.__ord_block_height into the rendering context. This is the key primitive for dynamic trait logic. Anything derived from block height is deterministic and verifiable.

Inscription ordering matters. You must inscribe in dependency order. A token HTML file that references a renderer that doesn't exist yet will simply fail to render. Plan your inscription batches carefully, especially if you're inscribing thousands of tokens — you need all dependencies committed and indexed before the dependent files go live.

Tradeoffs vs. Ethereum and Solana

Let's be direct about what you're giving up and what you're gaining. This is the section I wish someone had handed me clearly before I started.

What Bitcoin gives you:

  • Absolute immutability. An inscription is unalterable by anyone, including you. The asset will exist as long as Bitcoin exists and the sat is not lost. No proxy contracts, no admin keys, no upgrade mechanisms. For collectors and serious projects, this is genuinely valuable — it's a credible commitment nobody on Ethereum can match without sacrificing upgradeability entirely.
  • Settlement finality. Bitcoin has the deepest proof-of-work finality in existence. After 6 blocks, your inscription is effectively permanent. The chain isn't going to roll back.
  • Cost model simplicity. You pay once to inscribe. No gas spikes, no failed transactions eating fees, no MEV. The cost to inscribe is a one-time fee to miners, and then the data lives on-chain indefinitely.

What you're giving up:

  • Smart contracts. There are none. Bitcoin Script is deliberately limited. You cannot deploy executable logic that runs on-chain and can be called by transactions. Everything "smart" in your application runs off-chain and references on-chain data for state.
  • Composability at execution time. On Ethereum, smart contracts call each other during transaction execution. On Bitcoin, composability is read-only at indexer time. You can compose data. You cannot compose execution.
  • Rich developer tooling. The Hardhat/Foundry/Ethers.js ecosystem doesn't exist for Ordinals. As of 2026, tooling has improved substantially but it's still thinner than EVM.
  • EVM familiarity. If your whole team knows Solidity and has no Bitcoin development background, the learning curve is real. The mental model is fundamentally different.

The honest comparison on cost: Inscribing a rich HTML file with recursive references costs roughly the same as inscribing the equivalent bytes in raw content. If your average token file is 2KB (just the HTML shell), you're paying per-byte fees on 2KB per token rather than the full asset size. For a 10,000-piece collection, this is significant. On Ethereum, your actual on-chain storage is minimal because you're storing a URI that points off-chain — but then you've accepted that the metadata can go offline. Recursive Ordinals let you have genuine on-chain storage at reasonable cost because you're sharing the heavy bytes.

Finality on Solana is faster (seconds) but the chain has experienced multiple outages and validator coordination failures. If you're building something where "the inscription exists forever, no exceptions" is the product guarantee, Bitcoin wins. If you need fast finality and cheap transactions and can tolerate some infrastructure risk, Solana is competitive.

Game-State on Bitcoin

Pizza Pets was the first Bitcoin-native pets game — and coordinating game state on a chain with no native execution layer required a different architecture than anything that had been built before.

The core challenge: Bitcoin has no on-chain memory. There's no storage slot that says "this pet has been fed 15 times." Every piece of state must be derived from the transaction history itself — from the pattern of inscriptions, transfers, and specific transactions sent to specific addresses.

The architecture that worked:

Inscription-as-action. Players fed their pets by sending a specific type of inscription (a "feed" inscription) to their pet's sat address. Each feeding interaction was recorded as a new inscription on the blockchain. The game's indexer scanned the chain, identified feed inscriptions sent to valid pet sats, and derived current game state from the cumulative history of those transactions.

This produced over 1 million feeding interactions — each one a real Bitcoin transaction, each one permanently recorded on-chain. The state of every pet at any point in time is deterministically derivable from the chain. There's no database that can be hacked, no server that can shut down and wipe state. If you run the indexer yourself, you get the same answer as the game server.

The indexer is the game engine. In this model, the "smart contract" is replaced by an off-chain indexer with well-defined, open-source rules for interpreting chain state. The rules are published. The indexer is reproducible. The data is on-chain. The trust model is: "anyone who runs this indexer against Bitcoin mainnet will reach the same state."

This is the architectural pattern that makes Bitcoin gaming viable: define the state transition rules off-chain, anchor the state transitions themselves on-chain as inscriptions, build an open indexer that anyone can verify. The game server is a convenience layer, not a trust layer.

What this costs. Every player action is a Bitcoin transaction. Fees apply. During high-fee periods in 2023-2024, this created UX friction — feeding your pet could cost $5-20 in fees. This is the honest tradeoff. If your game loop requires hundreds of player actions per session, Bitcoin is probably not your chain. If your game loop is more deliberate — fewer, higher-stakes interactions — the cost structure can work.

Tooling in 2026

The landscape changed significantly from January 2024. Here's what the stack actually looks like now:

Indexers. ord (the reference implementation from Casey Rodarmor's team) remains the primary indexer, now at a much more stable version with recursive resolution well-supported. Hiro's Ordinals API provides a hosted indexer with REST endpoints and has become reliable enough for production use. Running your own ord node is still necessary for collections that need custom indexing logic.

Inscription tooling. ord CLI handles inscriptions, but for collections of any meaningful size you'll want a batch inscription tool. Several have matured: ordinalsbot for managed inscriptions with retry handling, and open-source batch scripts that wrap the ord CLI. The UX around child inscriptions (for provenance/parent-child collection structure) is now well-documented.

Wallets. Xverse and Leather (previously Hiro Wallet) both have stable APIs. Magic Eden's wallet has become a credible third option. All three support Ordinals, Runes, and BTC in a single wallet interface. The wallet connectivity landscape in 2026 is meaningfully better than 2024 — you're not fighting as hard to get users to the right address type.

Marketplaces and rendering. Magic Eden, Gamma, and OKX have recursive inscription rendering support. The era of "my recursive inscription renders as a blank square on the marketplace" is mostly over. Test your rendering pipeline on all three before launch.

Development workflow. The closest thing to a local development environment is running a ord server pointed at regtest or signet Bitcoin. Signet is now more commonly used because it has realistic block times without real money at stake. There's no Hardhat-equivalent with hot reloading and built-in debugging — this is still a gap.

What's still missing in 2026: There's no mature SDK that abstracts inscription creation the way ethers.js abstracts Ethereum. You're still stitching together ord CLI commands, Bitcoin RPC calls, and custom scripts. If you come from an EVM background, expect to spend two to four weeks just getting comfortable with the toolchain before you ship anything.

Common Mistakes Developers Make

I've seen these patterns kill projects or add months of rework.

Inscribing dependencies after tokens. The most operationally painful mistake: inscribing token HTML files that reference a renderer inscription that hasn't been confirmed yet. Your tokens render as broken for however many blocks it takes to get the dependency confirmed and indexed. Always inscribe in strict dependency order and confirm before proceeding.

Not running your own indexer. Relying entirely on third-party indexer APIs for a production collection means your rendering pipeline has an uptime dependency on someone else's infrastructure. The /content/ endpoint on the ord API is what resolves recursive references. If it's down, your collection appears broken. Run your own node, or have a fallback strategy.

Over-engineering the on-chain layer. The temptation when you come from EVM is to try to put more logic on-chain than Bitcoin actually supports. Bitcoin stores data. It does not run code. If you find yourself trying to implement game logic that "runs on-chain," you've misunderstood the model. Move the logic off-chain, anchor the state transitions on-chain.

Ignoring fee market volatility. Building a game loop that requires frequent small transactions without accounting for fee spikes will destroy your UX during congested periods. Design for intermittent high-fee environments. Cache state aggressively off-chain. Use inscription batching where possible. Let players queue actions and batch-commit them.

Circular recursive references. An inscription that references a second inscription that references the first will cause the renderer to hang or error depending on the client. The ord indexer does not detect or prevent circular references — it's your responsibility to ensure your dependency graph is a DAG.

Assuming stable inscription IDs before confirmation. Transaction IDs change during RBF (replace-by-fee) bumping. If you compute inscription IDs from unconfirmed transactions and use those IDs in other inscriptions before confirmation, you can end up with broken references if the transaction gets replaced. Build your batch pipeline to wait for full confirmation before deriving dependent inscription IDs.

No rendering test on all target wallets/marketplaces. Recursive rendering behavior varies between clients. What renders correctly in ord's local server may not render correctly in Xverse or on Magic Eden. Test early, test all surfaces.

Whether to Build Here

Bitcoin Ordinals in 2026 is a real platform with real production collections and real users — not an experiment. But it is genuinely different from what most web3 engineers are used to, and not every project belongs here.

Build on Ordinals if: your core value proposition is permanent, trustless, verifiable on-chain assets. If the answer to "why does this need to be on Bitcoin" is something like "so that the collection exists forever, provably, regardless of what the team does," you're in the right place. Collections, high-value PFP projects, games with deliberate interaction loops, digital assets where immutability is the feature — these are natural fits.

Don't build on Ordinals if: you need cheap, frequent user interactions (build on an L2 or Solana), you need smart contract composability at execution time (use EVM), or your team has no appetite for thinner tooling and a steeper learning curve.

The mental model shift is real. Once you internalize that Bitcoin stores data and you derive behavior from that data off-chain through deterministic indexers, a lot of what seemed like limitations starts to look like guarantees. That's the thing that makes building here interesting — and occasionally maddening.

If you're evaluating whether Ordinals is the right substrate for your project — or if you're mid-build and running into architecture questions — the Bitcoin & Ordinals development consulting engagement is built for exactly this. Senior eng on both Pizza Ninjas and Pizza Pets, and available for contract work as a senior engineer or co-architect on your team.

The full Pizza Ninjas build — recursive architecture in production, 1,500 inscribed on mainnet, and the Sotheby's outcome: Pizza Ninjas case study →

FAQ

Common questions.

What is a recursive inscription on Bitcoin?

A recursive inscription is a Bitcoin Ordinal that references other inscriptions by their inscription ID rather than embedding its own full content. A generative PFP collection, for example, can inscribe shared trait assets (SVG layers, JavaScript code) once, then inscribe tiny HTML files per item that pull those shared parts in at render time. The result is a collection that lives entirely on-chain, renders without any server, and costs a fraction of a non-recursive approach in fees.

Why are recursive inscriptions better than regular inscriptions for collections?

Three reasons. First, cost — inscribing shared assets once instead of per-item cuts inscription fees by an order of magnitude for most generative collections. Second, upgradability of a narrow kind — you cannot modify inscribed data, but you can re-assemble it on the client side, which opens design space. Third, composability — an inscription can reference any other inscription, meaning collections, games, and tooling can build on top of each other without off-chain dependencies.

Can you build games on Bitcoin using Ordinals?

Yes — with a different mental model than Ethereum. Bitcoin does not execute smart contracts, so game state is derived off-chain from inscribed data via deterministic indexers. Pizza Pets is a production example: game state (feeding, evolution, death) lives in inscribed transactions and is interpreted by a shared indexer spec. The result is a fully on-chain game loop with over one million interactions logged. The approach trades execution-time composability for immutability and auditability.

How does Bitcoin Ordinals compare to Ethereum and Solana for developers?

Ethereum gives you native smart contracts and the deepest tooling ecosystem, at the cost of gas and a more complex attack surface. Solana gives you throughput and low fees, at the cost of centralisation concerns and ecosystem youth. Bitcoin Ordinals gives you maximum immutability, provable data permanence, and zero smart-contract risk — at the cost of execution (all logic is off-chain indexer work) and thinner tooling. The choice should follow the product, not the tribe.

What tooling should I use for Bitcoin Ordinals development in 2026?

The ord CLI is still the reference implementation and worth understanding at a low level, even if you use wrappers in production. For inscription pipelines at scale, OrdinalsBot's API and custom batching scripts are the proven path (used for Pizza Ninjas, Project Spartacus, and Pizza Pets). For wallet integration, PSBT-based flows work across Unisat, Xverse, Leather, OKX, and Magic Eden. For indexing, either run your own ord node or use a managed indexer — the tradeoff is reliability versus cost.

When should you NOT build on Bitcoin Ordinals?

When you need cheap, frequent user interactions — an L2 or Solana will serve you better. When you need execution-time composability between contracts — use EVM. When your team has no appetite for thinner tooling, indexer maintenance, and a steeper learning curve — use what they already know. Ordinals is a strong fit when the core value proposition is permanent, trustless, verifiable on-chain data. When that is not the answer to 'why Bitcoin,' build elsewhere.

Part of the /bitcoin hub

Free download · 6 pages · PDF

What I learned shipping 1,500 Ordinals on Bitcoin.

Pre-launch, launch-day, and the 90 days after — with the mistakes that cost real BTC. Ordinals, Runes, and beyond.

No spam. You also get the Sunday note — unsubscribe in one click.

Written by

David Dacruz

Digital architect in Ericeira, Portugal. 42 alumni. I write about building at the intersection of AI, web3, and what actually ships.