diff --git a/100.md b/100.md new file mode 100644 index 0000000000..fb8347ba41 --- /dev/null +++ b/100.md @@ -0,0 +1,108 @@ +NIP-100 +====== + +Decentralized Stars & Reviews +------------------------------- + +`draft` `optional` + +### Abstract + +This NIP defines an addressable event (kind 30016) for posting star ratings and optional text reviews of entities (products, services, sellers, locations) identified by any URI-like identifier. It replaces centralized "star & review" systems with verifiable, portable, censorship-resistant data on Nostr. + +### Overview +Defines an addressable event (kind 30016) for posting star ratings (1-5) and optional text reviews of entities (products, services, sellers, locations) identified by any URI-like identifier. Replaces centralized "star & review" systems with verifiable, portable, censorship-resistant data on Nostr. + +### Event Structure +```json +{ + "kind": 30016, + "tags": [ + ["d", ""], // required, same as r for addressability + ["r", ""], // required, e.g. "isbn:978-3-16-148410-0", "npub:...", "shop:example.com/product/123", "geo:13.7563,100.5018" + ["rating", "{\"score\":4,\"max_score\":5,\"review_text\":\"Optional short summary\"}"], // required, JSON object + ["title", ""], // optional + ["summary", ""], // optional + ["image", ""] // optional + ], + "content": "", + ... +} +``` + +### Rules +- Events are addressable per NIP-01 (kind 30016), ensuring one event per author per `d` tag value (which matches the `r` tag). +- `d` tag MUST match the `r` tag value for addressability. +- `rating` tag MUST contain a valid JSON object with at least `score` (positive integer, typically 1–5). `max_score` is optional (defaults to 5 if omitted). `review_text` is optional. +- Clients MUST ignore events with invalid or missing `rating` JSON, or `score` not a positive integer ≤ `max_score`. +- Multiple `r` tags allowed for reviewing the same entity under different identifiers (but `d` should be the primary one). +- Relays MUST store only the latest event per combination of `kind`, `pubkey`, and `d` tag value. + +### Client Behavior +- Display aggregated average stars and review list. +- Allow filtering by verified authors or minimum reputation. +- Support replies (kind 1) threaded under review event ID for discussions. + +### Querying Reviews +Clients can query reviews using standard Nostr filters: +- To get all reviews for an entity: `{"kinds":[30016], "#d":[""]}` or `{"kinds":[30016], "#r":[""]}` +- To get a user's reviews: `{"kinds":[30016], "authors":[""]}` +- Combine with `since`/`until` for time ranges. + +### Aggregation and Display +- Clients SHOULD aggregate ratings by computing the average `score` from valid events. +- Display review lists sorted by `created_at` (newest first). +- Show user reputation if available (e.g., via other NIPs). + +### Replies and Discussions +- Use [NIP-10](10.md) threaded replies (kind 1) referencing the review event ID for discussions. + +### Examples +1. Review a product: +```json +{ + "kind": 30016, + "tags": [ + ["d", "shop:example.com/product/123"], + ["r", "shop:example.com/product/123"], + ["rating", "{\"score\":5,\"max_score\":5,\"review_text\":\"Excellent quality!\"}"], + ["title", "Great Buy"], + ["summary", "Highly recommend"] + ], + "content": "Detailed review text in markdown." +} +``` + +2. Review a location (using default max_score of 5): +```json +{ + "kind": 30016, + "tags": [ + ["d", "geo:13.7563,100.5018"], + ["r", "geo:13.7563,100.5018"], + ["rating", "{\"score\":3}"] + ], + "content": "Nice place but crowded." +} +``` + +3. Review with higher scale (e.g., out of 10): +```json +{ + "kind": 30016, + "tags": [ + ["d", "isbn:978-3-16-148410-0"], + ["r", "isbn:978-3-16-148410-0"], + ["rating", "{\"score\":8,\"max_score\":10}"] + ], + "content": "Solid read, worth the time." +} +``` + +### Identifier Recommendations +Use stable, globally unique strings: +- Products: `isbn:…`, `gtin:…`, `shop:/product/` +- Services: `npub:…` (seller), `web:/service/` +- Places: `geo:lat,lng` or `osm:node/…` + +This NIP enables open, user-owned reputation layers for e-commerce, freelance platforms, and local services without gatekeepers. diff --git a/README.md b/README.md index ccae3aa006..fdf3745448 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos - [NIP-96: HTTP File Storage Integration](96.md) --- **unrecommended**: replaced by blossom APIs - [NIP-98: HTTP Auth](98.md) - [NIP-99: Classified Listings](99.md) +- [NIP-100: Decentralized Stars & Reviews](100.md) - [NIP-A0: Voice Messages](A0.md) - [NIP-B0: Web Bookmarks](B0.md) - [NIP-B7: Blossom](B7.md) @@ -204,6 +205,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `10012` | Favorite relays list | [51](51.md) | | `10013` | Private event relay list | [37](37.md) | | `10015` | Interests list | [51](51.md) | +| `30016` | Star Ratings | [100](100.md) | | `10019` | Nutzap Mint Recommendation | [61](61.md) | | `10020` | Media follows | [51](51.md) | | `10030` | User emoji list | [51](51.md) |