Before this week I thought a Solana NFT was a Metaplex thing. It turns out you can mint a full NFT — with metadata, a collection, and live updates — using just the Token Extensions program and the spl-token CLI.
The mental model
If you already understand SPL tokens, an NFT is the same program with tighter rules: 0 decimals (nothing to split), supply capped at 1, and mint authority disabled when you are done so no one can ever inflate it. Uniqueness is enforced by token math, not by a is_nft flag.
The Metadata extension stores name, symbol, and URI directly on the mint account — no separate Metaplex metadata account. The URI points at a JSON file hosted somewhere public; that JSON holds the image URL and attributes. Wallets and Solana Explorer read the on-chain fields, fetch the JSON, render the art.
Collections use the Group and Member extensions: one mint is the collection (group), each NFT mint points back to it (member). Web2 analogy: a collection_id foreign key stamped into the row — except there is no central database to join against.
What I built
Over Days 44–47 on devnet I went from a named NFT to a collection I could inspect and patch live.
1. NFT with on-chain metadata. I minted Black Box Oracle (ORCL) on Token-2022 with --enable-metadata, pointed the URI at a gist JSON file, minted one token, and disabled mint authority.
export TOKENZ=TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
spl-token create-token --program-id $TOKENZ --enable-metadata --decimals 0 ./nft....json
spl-token initialize-metadata <MINT> "Black Box Oracle" "ORCL" "<GIST_RAW_URL>"
spl-token mint <MINT> 1
spl-token authorize <MINT> mint --disable
Mint: Nft5CnhQbXUjvce9RGux9BVJwdH8QNGZgqoQtQ2KJeJ
2. A collection with two members. Solana Sketchbook (SKTCH) uses --enable-group; each sketch uses --enable-member. Both flags must be set at mint creation — you cannot bolt them on later.
spl-token initialize-group <COLLECTION> 3
spl-token initialize-member <MEMBER> <COLLECTION>
Collection: 6CBzxZ96JX87hhVbrr7NdyiXSneeTbVW2mTHCExGFVbg · Members: Sketch #1 · Sketch #2. Group shows size: 2, max_size: 3.
3. An on-chain audit. I ran spl-token display on the member and collection mints and verified extension blocks, supply, and that TokenGroupMember → Group matched the collection address byte-for-byte. Same habit as querying a row after a migration — trust the CLI output, not just the Explorer UI.
4. Live metadata edits. While I still held update authority, I renamed Sketch #1 to Field Notes, added and removed a custom rarity field, and pointed the URI at new JSON — each change one transaction, visible in Explorer within a slot.
The surprising part
Extensions are schema decisions. Group and member must be declared when you create the mint. I could not retro-fit my metadata NFT into the Sketchbook collection afterward.
Three layers, three speeds. Name and URI update on chain immediately. The image lives off chain and wallets cache it aggressively — Explorer showed "Field Notes" while Phantom still showed the old art.
No separate NFT program. Collectibles are SPL Token plus a small set of extensions. Metaplex Core is still the common marketplace path; Token Extensions is the native SPL stack when you want metadata and grouping inside the token program itself.
Top comments (0)