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,
"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:
- •
ktag value of# - •
itag matching theItag - • No
etag
Replies have:
- •
ktag value of1111 - •
etag pointing to parent - •
ptag 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
| Relay | URL |
|---|---|
| Ditto | wss://relay.ditto.pub |
| Primal | wss://relay.primal.net |
| Damus | wss://relay.damus.io |
| nos.lol | wss://nos.lol |
Always publish to multiple relays for redundancy. The Nostr protocol allows any relay to store and serve your data.