Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions 100.md
Original file line number Diff line number Diff line change
@@ -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", "<reviewed-entity-identifier>"], // required, same as r for addressability
["r", "<reviewed-entity-identifier>"], // 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", "<short title>"], // optional
["summary", "<one-line summary>"], // optional
["image", "<image URL>"] // optional
],
"content": "<full review text (markdown allowed)>",
...
}
```

### 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":["<entity-identifier>"]}` or `{"kinds":[30016], "#r":["<entity-identifier>"]}`
- To get a user's reviews: `{"kinds":[30016], "authors":["<pubkey>"]}`
- 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:<domain>/product/<id>`
- Services: `npub:…` (seller), `web:<domain>/service/<id>`
- 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.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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) |
Expand Down