Nostr Kiwi
Nostr Kiwi is a web app built around communities rather than a single global feed. It lets people browse groups, create community definitions, appoint moderators, submit notes, approve posts, read articles, chat, search, sign with NIP-07 or NIP-46 and pay zaps through WebLN or Nostr Wallet Connect. Its importance is not scale or polish. It is the way it turns Nostr's community events into a concrete reader experience.
A Nostr app organized around communities
Nostr Kiwi is easiest to understand if you start with its headline: communities for everyone. The live homepage says it is a place to share notes and curate content in communities. The GitHub description is a little more explicit: a censorship-resistant app where users curate content in communities, enabled by the Nostr protocol. That is the center of the project. Nostr Kiwi is not mainly a microblogging timeline with communities as a side feature. It is a community browser, editor and moderation surface.
That gives the app a distinct place in the Nostr ecosystem. General clients such as Damus, Amethyst, noStrudel or Primal tend to begin with people, posts and feeds. Nostr Kiwi begins with groups of interest: a community has a name, identifier, description, cover image, rules, tags and moderators. A user can browse communities, open a community page, read its feed, inspect its info, read long-form articles, use a chat view and, if allowed, help approve posts.
This matters because Nostr has always had a tension between open relay publication and community-shaped spaces. A global feed is simple to explain but hard to govern. A community needs discovery, moderation, identity, membership, content rules and a way for readers to understand why a post appears there. Nostr Kiwi is one attempt to make those pieces feel like an app rather than a raw protocol proposal.
The live app and public code
The public site at `nostr.kiwi` is still reachable and renders a landing page with a Launch App button, source link, app icons, a manifest and a phone-frame preview. The app route is `/app`, and the repository homepage points back to the same domain. During current research on June 11, 2026, the GitHub repository `jinglescode/nostr.kiwi` was public, MIT licensed, written mostly in TypeScript, and last pushed in November 2024 with a commit updating the source-code link.
The repository history shows most feature work concentrated in July and August 2023. Commit messages mention community URLs, feeds, list tags, user lists, image upload, GIF search, editor height and removal of PWA plumbing. The repo is small and focused rather than a large multi-year product organization. It has only a few GitHub stars and no open issues at the time of research. That does not make it unimportant. It means readers should evaluate it as an experimental but real Nostr app, not as a dominant client brand.
The official assets are clean enough to use. The live site exposes favicon files, Android and Apple touch icons, splash images and a manifest with the short name Kiwi. The manifest starts the app at `/app`, uses black theme and background colors, and declares a standalone display mode. The source still includes `next-pwa` as a dependency, while `next.config.js` has the PWA wrapper commented out. The practical result is a web app with PWA-style assets and mobile presentation, but readers should verify installability in their own browser.
A mobile-shaped web stack
Nostr Kiwi is a Next.js 13 app built with React, TypeScript, Tailwind, Framework7, Zustand and TanStack Query. It uses `@nostr-dev-kit/ndk` for Nostr relay access and signing abstractions, `nostr-tools` for key and Bech32 work, `alby-js-sdk` for WebLN and Nostr Wallet Connect payments, and `axios` for file uploads. That stack explains the app's feel: it is web-native but phone-shaped, with Framework7 UI patterns and a mobile-first app shell.
The relay list is hard-coded in `src/constants/nostr.ts`: `wss://relay.nostr.band`, `wss://relay.damus.io`, `wss://relay.snort.social`, `wss://relayable.org` and `wss://relay.nsecbunker.com`. Those relays are passed into the NDK provider. The NDK instance connects once, exposes helper functions to fetch events, fetch until EOSE, set a signer and sign or publish an event. This is a normal NDK-based architecture: React components ask hooks for Nostr data, hooks build filters, NDK talks to relays, and TanStack Query caches the result.
That design has clear advantages. It lets Kiwi iterate quickly as a web client, and it keeps most protocol behavior in reusable hooks. It also has limits. A hard-coded relay set can miss community events that live elsewhere. Relay availability, indexing and retention affect what readers see. A local web app can feel smooth while still being dependent on a small set of public relay choices. Anyone using Kiwi seriously should understand that community discovery is only as good as the relays being queried.
Community definitions use kind 34550
The central event type in Kiwi is kind 34550. The `useCommunities` hook fetches events with kind 34550, and `useCommunity` looks up a community by author plus `d` tag. `eventToCommunity.ts` converts a Nostr event into a local community object by reading tags such as `d`, `name`, `description`, `image`, `rules`, `t` and `p` tags marked as moderators. It then constructs the community id as `34550:pubkey:d`.
The community editor publishes the same shape. A creator fills in a name, description, image URL, rules, tags, identifier and moderators. The code creates an NDK event with kind 34550, adds a `d` tag, name tag, optional description, image and rules tags, moderator `p` tags with the marker `moderator`, and topic `t` tags. It then signs and publishes the event. That is a concrete implementation of the Nostr community idea, not just a label in the UI.
This is where Kiwi's product idea becomes visible. A community is not a server-side row owned by the Kiwi website. It is a replaceable, signed Nostr addressable event. If other clients understand the same convention, they can find the same community definition. If a relay drops the event or a client does not query the right relay, discovery suffers. This is the tradeoff of Nostr communities: portable definitions, but no central database that guarantees every app will see them.
Moderation is event-based
Nostr Kiwi does not treat moderation as a hidden admin table. Its approval flow is based on Nostr events. The community feed hook can fetch all kind 1 notes tagged to a community, or it can fetch kind 4550 events authored by community moderators and tagged to that community. The pending-approval hook compares all submitted notes against approved notes and shows what remains. The approval publisher wraps a note into a kind 4550 event, tags the community, original event id, original author and original kind, then signs and publishes that approval.
This pattern matches the broader moderated-community design in NIP-72. A member's note can exist as a normal signed note, while the community's displayed feed is shaped by moderator approvals. Moderators do not have to own every post. They publish approval events that say which posts belong in the community view. That is a useful distinction because it keeps authorship and curation separate.
The reader-facing result is simple: the community can have a moderated feed. The protocol result is more subtle: moderation itself becomes signed, relay-distributed data. Other clients can disagree about whether to show raw submissions, approved submissions, moderator decisions or alternate curation. That is healthier than a single platform delete button, but it also means moderation consistency depends on clients, relays and the community's moderator set.
Notes, articles and chat sit inside the group
Kiwi's community page has several content modes. The `CommunityContent` component can show a feed, articles, approval queue or chat. The feed reads community-tagged notes and moderator approvals. The article view reads kind 30023 long-form events for the community. The chat view reads kind 42 messages with an `a` tag pointing at the community. That gives one group a mixture of quick posts, long posts and chat-like conversation.
The note editor publishes ordinary kind 1 notes by default. If the note is being posted to a community, it adds an `a` tag with the community id. If it is a reply, it adds `p` and `e` tags for the author, root and reply. If it quotes another note, it adds a `q` tag. If the note is community chat, it changes the kind to 42 and tags the community as the root. It also parses hashtags and Nostr references from content. These are the small mechanics that make a community feed navigable across clients.
Media is handled through a basic upload path. The upload helper posts image files to `https://nostr.build/api/v2/upload/files`, and the note editor adds `imeta` tags for uploaded image metadata when available. There is also GIF search plumbing through a Tenor API route. This makes Kiwi more than a text-only proof of concept, but users should remember that media durability depends on external upload services, not only on signed Nostr events.
Login choices carry different risks
Kiwi gives users three login paths. The NIP-07 path uses a browser extension signer and stores the resulting user identity locally. The NIP-46 path uses Nostr Connect with a remote signer such as nsecBunker, creates or reuses a local signer, blocks until the remote signer is ready, and stores the token and local private key material needed for the connection. The direct secret-key path accepts an nsec or raw private key, creates an NDK private-key signer and stores the key on the device.
The UI copy is refreshingly plain about the tradeoffs. The NIP-07 screen says browser extension signing does not work in PWA fullscreen app mode. The NIP-46 screen says it lets the user sign without entering a private key on the client and points to nsecBunker. The secret-key screen says the private key is stored on the device. Those details matter because web clients can be convenient and risky at the same time.
A cautious reader should test Kiwi with a low-value Nostr key first. NIP-07 is generally better for a browser session when a trusted extension is already installed. NIP-46 can be better when the remote signer is configured carefully. Direct nsec entry is the highest-friction risk: it may be acceptable for a disposable key, but it should not be the first move with a valuable long-term identity. Kiwi exposes the choices; the user still needs to pick the right one.
Zaps use WebLN and NWC
Nostr Kiwi includes zap support through NDK and the Alby JavaScript SDK. The zap hook first fetches the original event, asks NDK to create a zap invoice for the note or request event, then pays the invoice through either a browser WebLN provider or a Nostr Wallet Connect provider. If a WebLN wallet is present, Kiwi enables it and calls `sendPayment`. If not, it can fall back to opening a `lightning:` URL.
The NWC path is more flexible. Kiwi can use a saved NWC URI, a wallet pubkey plus relay and secret, or initialize a new Alby Nostr Wallet Connect provider. When direct initialization fails, it builds an authorization URL with the app name `nostr.kiwi` and a return path under `/nwc`. The settings UI exposes preferred Lightning wallet options, including Alby Nostr Wallet Connect and custom NWC, though some older actions are commented out in the current code.
This is why Kiwi belongs in payment-aware Nostr coverage even though it is not a wallet. It does not hold funds as its main job. It lets community readers send zaps from a social context. The practical question for a user is permissions: which wallet is connected, what payment limits are set, whether the NWC secret is stored safely, and whether the app's payment path is still maintained enough for real sats.
Search, lists and discovery
Kiwi has several discovery surfaces beyond the community list. It has a For You area with public notes, hot notes, followed users and followed communities. It uses `nostr.band` APIs for note stats and trending notes, and `nostr.wine` for search. The search component can produce results for users, communities, hashtags and notes. It can decode Bech32 note references and use Nostr filters to find referenced events.
Lists are part of the app's social model. Hooks read and publish kind 30000 and 30001 list events, including user lists, tag lists, followed communities and user topics. Following a community is represented by updating a list of community ids and publishing the updated event. This is a good example of Nostr's addressable-list style: the app stores preference and organization data as signed events instead of only keeping it in a private database.
Discovery remains one of the hardest parts of a community client. Users need to find communities, communities need to expose tags and images, moderators need to be visible, and the app needs enough relay coverage to avoid empty screens. Kiwi makes a serious attempt, but its small hard-coded relay set and older activity timeline mean readers should treat search results and community counts as partial views of the network.
Spam handling and moderation limits
The source contains a small spam text list with phrases such as `claim free` and `airdrop`. That is not a full moderation system, but it shows the developer was thinking about low-effort spam inside public feeds. The real moderation model is the community approval flow: a post can be submitted to a community, and moderator approval events decide whether it appears in the curated community feed.
This model is valuable because it keeps community governance local to the community. A moderator can approve content without pretending to remove the original event from all relays. Other clients can choose how to display the same raw event. This is closer to curation than deletion. It fits Nostr's reality: signed events can be copied, relays can diverge, and clients decide what to show.
The downside is that users may expect platform-style enforcement. If someone posts abusive content tagged to a community, an approval model can keep it out of the official community feed, but it cannot make the signed event disappear everywhere. Screenshots, alternate relays and alternate clients remain possible. Nostr Kiwi's community model is useful, but readers should understand the boundary between moderation, curation and erasure.
What to test before relying on it
The first thing to test is whether the app still works against current relays. Open the live app, check whether communities load, try a disposable key, and inspect whether kind 34550 community definitions and kind 4550 approvals appear across the relays Kiwi queries. If the feed feels empty, it may be a relay-coverage problem rather than proof that no communities exist.
The second thing to test is signing. NIP-07 may be easiest in a normal browser tab, but it may not work in standalone PWA mode. NIP-46 needs a remote signer that understands the token flow. Direct secret-key login stores key material locally and should be reserved for test keys unless the user is comfortable with the tradeoff. Also test logout, storage clearing and whether the browser keeps old session data.
The third thing to test is payment. If you use zaps, begin with a tiny amount and a wallet with strict limits. Confirm whether WebLN, NWC URI or custom NWC configuration is active. Watch for authorization prompts and stored settings. Nostr Kiwi can create a nice community payment flow, but payments are one place where an experimental web app deserves more caution than curiosity.
Where Nostr Kiwi fits
Nostr Kiwi is not the most active or most polished Nostr social client. Its value is narrower and more interesting. It shows how Nostr communities can be represented as signed events, how moderator approvals can be events too, and how a web app can combine community feeds, long-form articles, chat, lists, signers and zaps without becoming a centralized forum database.
For readers, the app is worth opening if they want to understand NIP-72 style community UX. Create a throwaway key, browse the community list, inspect a community id, look at the moderator set, post a note, and see how the approval view differs from raw submissions. That learning is the main reason Kiwi belongs in a Nostr app archive even if the project is quiet.
For builders, Kiwi is a useful code reference. It is compact enough to read, uses NDK directly, and exposes common problems every Nostr community app must solve: relay discovery, signer choices, moderator events, event addressing, lists, media uploads, payment configuration, cache staleness and mobile web presentation. It is a small app with a big protocol question underneath: who gets to shape a public conversation when no platform owns the whole room?
Sources worth opening
Useful sources start with the live nostr.kiwi site and GitHub repository, then move through the NDK hooks, community editor, zap code, login components, manifest, NIP-72 and the NIPs behind signers, lists, articles, reactions and zaps.
- Nostr Kiwi live site
- Nostr Kiwi app route
- Nostr Kiwi GitHub repository
- Nostr Kiwi README
- Nostr Kiwi package.json
- Nostr Kiwi relay constants
- Nostr Kiwi NDK instance
- Nostr Kiwi signer helpers
- Nostr Kiwi NDK provider
- Nostr Kiwi community fetch hook
- Nostr Kiwi single community hook
- Nostr Kiwi community publisher
- Nostr Kiwi community approval hook
- Nostr Kiwi community approval publisher
- Nostr Kiwi community feed hook
- Nostr Kiwi community chat hook
- Nostr Kiwi community editor
- Nostr Kiwi community content switcher
- Nostr Kiwi note editor
- Nostr Kiwi zap hook
- Nostr Kiwi zap settings
- Nostr Kiwi upload helper
- Nostr Kiwi manifest
- Nostr Kiwi NIP-05 file
- Nostr Development Kit
- Framework7 React
- Next.js documentation
- Alby JS SDK
- nostr.build upload service
- nostr.band
- nostr.wine
- Nostr NIPs repository
- NIP-01 basic protocol flow
- NIP-05 DNS-based identifiers
- NIP-07 browser signer
- NIP-19 Bech32 encoded entities
- NIP-23 long-form content
- NIP-25 reactions
- NIP-28 public chat
- NIP-46 Nostr remote signing
- NIP-47 Nostr Wallet Connect
- NIP-51 lists
- NIP-57 Lightning zaps
- NIP-72 moderated communities





