nostr-nip05-setup

Set up NIP-05 DNS-based identity verification for Nostr, including the /.well-known/nostr.json endpoint, CORS headers, and kind:0 profile updates. Use when configuring NIP-05, setting up nostr.json, debugging NIP-05 verification failures, adding DNS identity to a Nostr profile, or working with /.well-known/nostr.json files and CORS for Nostr clients.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "nostr-nip05-setup" with this command: npx skills add accolver/skill-maker/accolver-skill-maker-nostr-nip05-setup

NIP-05 Identity Setup

Overview

Set up NIP-05 DNS-based identity verification so Nostr clients can map human-readable identifiers (like bob@example.com) to hex public keys. This skill covers creating the /.well-known/nostr.json endpoint, configuring CORS headers, updating kind:0 profiles, and debugging verification failures.

When to Use

  • Setting up NIP-05 verification for a domain
  • Creating or editing a /.well-known/nostr.json file
  • Configuring web server CORS headers for Nostr clients
  • Updating a kind:0 profile with a nip05 field
  • Debugging why NIP-05 verification is failing
  • Setting up the _@domain root identifier

Do NOT use when:

  • Building a Nostr relay (that's relay protocol)
  • Working with NIP-19 bech32 encoding (npub/nsec display format)
  • Implementing Nostr event signing or key management

Workflow

1. Determine the Setup Type

Ask: "Static file or dynamic server?"

ScenarioApproachBest For
Few users, rarely changesStatic .well-known/nostr.json filePersonal sites, small communities
Many users, frequent changesDynamic server with ?name= query handlingNIP-05 providers, large communities
Existing web serverAdd location block + CORS headersNginx, Apache, Caddy setups

2. Create the nostr.json File

The file maps human-readable names to hex public keys.

Format:

{
  "names": {
    "bob": "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9"
  },
  "relays": {
    "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": [
      "wss://relay.example.com",
      "wss://relay2.example.com"
    ]
  }
}

Critical rules:

  • Public keys MUST be 64-character lowercase hex (NOT npub bech32 format)
  • The names object is REQUIRED
  • The relays object is RECOMMENDED — it helps clients discover where to find the user
  • Local-part (the name) MUST only contain a-z0-9-_. (lowercase, no uppercase)
  • _ is the special "root" identifier — _@example.com displays as just example.com in clients

Root identifier example:

{
  "names": {
    "_": "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9"
  }
}

This lets the user be identified as just example.com instead of bob@example.com.

3. Serve the File Correctly

The file MUST be served at exactly:

https://<domain>/.well-known/nostr.json?name=<local-part>

Three non-negotiable requirements:

  1. HTTPS only — HTTP will not work. Clients only fetch over HTTPS.
  2. CORS header — Response MUST include Access-Control-Allow-Origin: * because JavaScript Nostr clients run in browsers and are blocked by CORS policies without this header.
  3. No redirects — The endpoint MUST NOT return HTTP redirects (301, 302, etc.). Fetchers MUST ignore redirects per the NIP-05 spec. This is a security constraint.

The ?name=<local-part> query string format exists so both static files and dynamic servers work. A static file ignores the query string and returns all names; a dynamic server can filter by name.

See references/server-configs.md for Nginx, Apache, Caddy, and Node.js configuration examples.

4. Update the Kind:0 Profile

The user's kind:0 metadata event must include the nip05 field:

{
  "kind": 0,
  "content": "{\"name\":\"bob\",\"nip05\":\"bob@example.com\",\"about\":\"A Nostr user\",\"picture\":\"https://example.com/avatar.jpg\"}"
}

The nip05 value format is <local-part>@<domain> — it looks like an email address but is NOT an email address.

Verification flow (what clients do):

  1. Client sees "nip05": "bob@example.com" in a kind:0 event
  2. Client splits into local-part bob and domain example.com
  3. Client fetches https://example.com/.well-known/nostr.json?name=bob
  4. Client checks if response.names.bob matches the event's pubkey
  5. If match → identity is verified and displayed

5. Test the Setup

Verify the endpoint returns correct JSON:

curl -s https://example.com/.well-known/nostr.json?name=bob | jq .

Verify CORS headers are present:

curl -sI https://example.com/.well-known/nostr.json?name=bob | grep -i ^access-control
# Expected: Access-Control-Allow-Origin: *

Verify no redirects:

curl -sI -o /dev/null -w "%{http_code}" https://example.com/.well-known/nostr.json?name=bob
# Expected: 200 (NOT 301, 302, 307, 308)

Verify the pubkey is hex (not npub):

curl -s https://example.com/.well-known/nostr.json?name=bob | jq -r '.names.bob' | grep -E '^[0-9a-f]{64}$'
# Should match — 64 lowercase hex characters

Checklist

  • nostr.json file created with correct names mapping
  • Public keys are 64-char lowercase hex (not npub)
  • Local-parts use only a-z0-9-_. characters
  • File served over HTTPS
  • Access-Control-Allow-Origin: * header present
  • No HTTP redirects on the endpoint
  • relays object included (recommended)
  • Kind:0 profile updated with nip05 field
  • Endpoint tested with curl and returns 200 with correct JSON

Common Mistakes

MistakeWhy It BreaksFix
Using npub instead of hex pubkeyNIP-05 requires hex format; npub is only for UI displayConvert npub to hex using a tool like nak decode npub1...
Missing CORS headerJavaScript Nostr clients in browsers can't fetch the fileAdd Access-Control-Allow-Origin: * to server config
HTTP redirects (301/302)NIP-05 spec says fetchers MUST ignore redirectsServe directly, no redirects — check trailing slash redirects
Uppercase in local-partSpec requires a-z0-9-_. onlyNormalize to lowercase before storing
Serving over HTTP instead of HTTPSClients only fetch NIP-05 over HTTPSSet up TLS (Let's Encrypt, Cloudflare, etc.)
Trailing slash redirect on .well-knownNginx/Apache may redirect /nostr.json to /nostr.json/Ensure exact match location, not directory
Wrong Content-TypeSome servers don't set application/jsonAdd Content-Type: application/json header
Query string breaks static fileSome servers reject or misroute ?name= on static filesEnsure server passes query strings through to static files

Quick Reference

ItemValue
Endpointhttps://<domain>/.well-known/nostr.json?name=<local-part>
Required headerAccess-Control-Allow-Origin: *
Pubkey format64-char lowercase hex
Local-part charsa-z0-9-_.
Root identifier_@domain (displays as just the domain)
Profile field"nip05": "name@domain" in kind:0 content
ProtocolHTTPS only (no HTTP)
RedirectsMUST NOT redirect

Key Principles

  1. Hex keys, never npub — The nostr.json file uses raw 64-character lowercase hex public keys. npub is a display format (NIP-19) and must never appear in nostr.json. This is the single most common mistake.

  2. CORS is mandatory — Without Access-Control-Allow-Origin: *, every browser-based Nostr client silently fails to verify the identity. The user sees no error — verification just doesn't work.

  3. No redirects, ever — HTTP redirects are a security risk in this context. The spec explicitly requires fetchers to ignore them. Common culprits: trailing-slash redirects, HTTP→HTTPS redirects on the endpoint itself, and www→non-www redirects.

  4. Identification, not verification — NIP-05 identifies users (maps human-readable names to keys), it does not verify trust. The exception is well-known domains (companies, projects) where domain ownership itself implies trust.

  5. Clients follow pubkeys, not NIP-05 addresses — If a user follows bob@example.com, the client stores the pubkey, not the address. If the NIP-05 mapping changes later, the client unfollows the address display but keeps following the pubkey.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

nostr-client-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

code-reviewer

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

cloudevents

No summary provided by upstream source.

Repository SourceNeeds Review
General

skill-maker

No summary provided by upstream source.

Repository SourceNeeds Review