For builders

Build on it. It's yours.

Normies Yacht Club is CC0 — public domain. The art, the data and the code. Here is a free, public API with the official collection data and the real on-chain pixel art. Make a game, a bot, a viewer, merch, a derivative. No permission needed. No attribution required.

CC0 1.0 · public domain No API key No rate limits Free forever Art 100% on-chain

This openness isn't an afterthought — it's the foundation. NYC is building Agent Islands: open, on-chain worlds where NFT-agents live and act. The same CC0 data, art and identity you see here are the rails an agent economy runs on. Build now; you're building on what comes next.

Try it right now

This yacht is fetched live from the public API and drawn from its official bitmap — no library, no key, one fetch().

loading…

Quick start

Draw any yacht in ten lines — this is the whole thing:

const r = await fetch("https://normiesyachtclub.com/api/v1/yacht/7.json");
const y = await r.json();

const cv  = document.querySelector("canvas");        // 40 x 40
const ctx = cv.getContext("2d");
ctx.fillStyle = y.art.off; ctx.fillRect(0, 0, 40, 40);
ctx.fillStyle = y.art.on;
for (let i = 0; i < 1600; i++)
  if (y.art.bits[i] === "1") ctx.fillRect(i % 40, (i / 40) | 0, 1, 1);

console.log(y.class, y.rarityRank, y.traits);        // "Superyacht", 12, {...}

Endpoints

Plain JSON, served from the CDN. Base: https://normiesyachtclub.com/api/v1

EndpointWhat you get
/index.jsonStart here — a discovery manifest listing every endpoint, with counts and links.
/openapi.jsonMachine-readable OpenAPI 3.1 spec of this API (for agents, codegen, tooling).
/stats.jsonCollection totals — fleet size, wallets, class breakdown.
/fleet.jsonIndex of every yacht: id, normieId, pixelCount, class, rarityRank.
/yacht/{id}.jsonOne yacht, self-sufficient: all traits plus the real 40×40 art bitmap. Everything you need to render it.
/traits.jsonFrequency of every trait value across the fleet — compute your own rarity.
/contract.jsonAddress, chain, deploy block and ABI, so you can read live state yourself.

Privacy by design: this API publishes no wallet addresses — no owner lists, no burner lists. That data is public on-chain, but we don't repackage holder lists into a bulk feed. For ownership, read ownerOf(id) from the contract.

For LLMs & agents: see /llms.txt for a plain-language overview and /api/v1/openapi.json for the schema.

The art bitmap

Each yacht's art is a 1600-character string, row-major, where '1' means the pixel is on. Pixel (x, y) is bits[y * 40 + x]. Two colours: #48494b on, #e3e5e4 off. That's it — the same bitmap the contract renders on-chain.

The generator

Want to roll yachts that don't exist yet — for a prototype, a level, a mock? The art engine is public and deterministic: the same seed always gives the same yacht, forever.

<script src="https://normiesyachtclub.com/art/yacht-generator.js"></script>
<script>
  const bits   = NYC.generateYachtBits(1234, { pixelCount: 620 });   // 1600 chars
  const traits = NYC.generateYachtTraits(1234, { pixelCount: 620 }); // { class, hull, ... }
  const svg    = NYC.bitsToSvg(bits);                                // ready to drop in
</script>

Works in Node too (module.exports). pixelCount is the "ink" of the burned Normie — it sets the class: Sloop, Cruiser, or Superyacht.

Live state lives on-chain

Who owns what, and how many are claimed, changes by the minute — so don't trust a cached file for it, and don't trust me. Read the chain. It is the only source of truth, and it's open to everyone.

tokenURI(id)The official image, rendered fully on-chain. Immutable — the renderer is locked.
ownerOf(id)Who holds a yacht right now.
balanceOf(a)How many a wallet holds.
claimed(id)Whether a yacht has been claimed yet.
totalMinted()How many are afloat.

Contract (Ethereum mainnet):
0x87306c282eBd62Fe1c80AA69Dd9408331Dc11f64

Full ABI and deploy block: /api/v1/contract.json

Every yacht is an agent

Each yacht owns an account — an ERC-6551 token-bound account it keeps for life. It can hold ETH and NFTs, sign, and act. Whoever holds the yacht controls it; transfer the yacht and the account goes with it, contents included. The address is a pure function of the token id, so it exists and is stable before anyone deploys it — no registration, no operator, nothing to ask us for.

An account address depends on the implementation and salt used to derive it, so we publish ours. Use this pair — a different one gives you different addresses for the same yachts, and your fleet stops being the same fleet as everyone else's.

Registry0x000000006551c19487814612e58FE06813775758
Implementation0x41C8f39463A868d3A88af00cd0fe7102F30E44eC
Salt0x00…00 (zero)
const y = await (await fetch("https://normiesyachtclub.com/api/v1/yacht/17.json")).json();
y.onchain.agent            // 0x3E1939a1531B9bD370AfB7B0a6D82f24178e915A

// or derive it yourself — a view call, valid before the account is deployed:
registry.account(implementation, salt, 1, "0x87306c282eBd62Fe1c80AA69Dd9408331Dc11f64", 17)

Every yacht file carries its own address under onchain.agent, and the full configuration — registry ABI plus three test vectors to check your derivation against — is in contract.json under agents. Holders can activate and manage their own accounts in The Purser.

Read ownership yourself. An agent address says nothing about who controls it: call ownerOf(id) on the collection before letting an agent act on anyone's behalf.

The rules

Built something? Come tell the crew in The Lounge at the marina, or tag @NormieYachtClub. We'd love to sail it.

Normies Yacht Club — CC0 1.0 Universal. Art, data and code dedicated to the public domain. A CC0 derivative inspired by, and built for, the Normies — read the Normifesto ↗.