ekx-pinata-ipfslisted
Install: claude install-skill Ekinoxis-evm/claude-skills
# Pinata / IPFS
Our NFT metadata and media storage, including the storage target behind property
NFT metadata.
Docs: https://docs.pinata.cloud
---
## Environment
```bash
PINATA_JWT= # SECRET — the modern auth, use this
PINATA_API_KEY= # legacy pair
PINATA_SECRET_KEY= # SECRET, legacy
NEXT_PUBLIC_PINATA_GATEWAY= # your-gateway.mypinata.cloud
```
⚠️ The portfolio contains `PINATA`, `PINATA_APIKEY`, `PINATASECRET` and
`PINATA_SECRET_KEY` as separate names across repos. Standardise on `PINATA_JWT` alone —
the key/secret pair is legacy and the JWT replaces both.
---
## Uploading
```ts
// Server-side only — the JWT can pin to your paid account.
const form = new FormData();
form.append("file", new Blob([buffer]), "house-42.png");
const res = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PINATA_JWT}` },
body: form,
});
const { IpfsHash } = await res.json(); // the CID
```
JSON metadata: `POST https://api.pinata.cloud/pinning/pinJSONToIPFS`.
**Never expose the JWT to the browser.** Anyone with it can pin arbitrary data to
your billed account. Upload through a route handler that authorises the user first.
---
## tokenURI
Store `ipfs://<CID>` onchain, not a gateway URL. Gateways change; the CID does not,
and a hardcoded gateway in an immutable contract is a permanent dependency on one vendor.
```solidity
function tokenURI(uint