Foxhole

    Technical Guide

    Everything you need to implement a Foxhole-compatible client or integrate with the network.

    Protocol Overview

    Foxhole uses standard Nostr NIPs to create a Reddit-like experience. Every hashtag on Nostr becomes a community (called a "Den"). Posts are NIP-22 comments on NIP-73 hashtag identifiers.

    Den Communities

    Dens are communities identified by NIP-73 hashtag identifiers. Every hashtag on Nostr is automatically a den — no registration or creation needed.

    Hashtag Identifier Format

    ["I", "#gaming"]
    ["K", "#"]

    The I tag contains a # prefix followed by the den name (lowercase). The K tag is always # — the NIP-73 kind for hashtag identifiers.

    For example, the den d/gaming maps to ["I", "#gaming"].

    Why hashtags? Using NIP-73 hashtag identifiers means Foxhole communities are universal across Nostr. Any client can display den content, and any hashtag can become a community. No walled gardens.

    Event Types

    Top-Level Post

    A top-level post in a den is a NIP-22 comment on a NIP-73 hashtag identifier.

    Kind 1111 - Top-Level Post
    {
      "kind": 1111,
      "content": "Has anyone tried the new game engine?",
      "tags": [
        // Root scope: the hashtag identifier
        ["I", "#videogames"],
        ["K", "#"],
    
        // Parent item: same as root for top-level posts
        ["i", "#videogames"],
        ["k", "#"]
      ]
    }

    Voting System

    Foxhole uses NIP-25 reactions for voting (dig/bury). The content field determines the vote type.

    Dig (Upvote)

    {
      "kind": 7,
      "content": "+",
      "tags": [
        ["e", "<post-id>", "<relay>", "<pubkey>"],
        ["p", "<post-pubkey>"],
        ["k", "1111"]
      ]
    }

    Bury (Downvote)

    {
      "kind": 7,
      "content": "-",
      "tags": [
        ["e", "<post-id>", "<relay>", "<pubkey>"],
        ["p", "<post-pubkey>"],
        ["k", "1111"]
      ]
    }

    Querying Data

    Fetch All Posts Across Dens

    {
      "kinds": [1111],
      "#K": ["#"],
      "limit": 50
    }

    Filter by #K: ["#"] to get all kind 1111 posts that use hashtag identifiers.

    Fetch Posts in a Specific Den

    {
      "kinds": [1111],
      "#i": ["#videogames"],
      "#k": ["#"],
      "limit": 50
    }

    Use lowercase #i with the hashtag identifier to scope to a specific den. Top-level posts have k = #.

    Identify Top-Level vs Replies

    Top-level posts have:

    • k tag value of #
    • i tag matching the I tag
    • • No e tag

    Replies have:

    • k tag value of 1111
    • e tag pointing to parent
    • p tag with parent author

    Fetch Replies to a Post

    {
      "kinds": [1111],
      "#e": ["<post-id>"],
      "#k": ["1111"]
    }

    Discover Active Dens

    Query recent posts and extract unique den names from the I tags:

    {
      "kinds": [1111],
      "#K": ["#"],
      "limit": 200
    }

    Then extract den names by stripping the # prefix from each I tag value.

    Recommended Relays

    RelayURL
    Dittowss://relay.ditto.pub
    Primalwss://relay.primal.net
    Damuswss://relay.damus.io
    nos.lolwss://nos.lol

    Always publish to multiple relays for redundancy. The Nostr protocol allows any relay to store and serve your data.