diff --git a/edufeed.md b/edufeed.md index 29794cd..e787bd2 100644 --- a/edufeed.md +++ b/edufeed.md @@ -2,7 +2,7 @@ ## Abstract -This NIP defines how to handle the metadata profile ["Allgemeines Metadatenprofil für Bildugnsressourcen" (AMB)](https://dini-ag-kim.github.io/amb/latest/) in nostr: +This NIP defines how to handle the metadata profile ["Allgemeines Metadatenprofil für Bildungsressourcen" (AMB)](https://dini-ag-kim.github.io/amb/latest/) in nostr: - How to convert AMB metadata to an AMB nostr event - How to convert an AMB nostr-event to AMB metadata @@ -11,87 +11,514 @@ This NIP defines how to handle the metadata profile ["Allgemeines Metadatenprofi ## Event Kind This NIP defines `kind:30142` as an AMB Metadata Event. -This means this is a replacable event, that can be adressed using `kind:pubkey:d-tag`. +This means this is a replaceable event, that can be addressed using `kind:pubkey:d-tag`. ## How to convert AMB metadata *to* an AMB nostr event -The transformation is quite straightforward. -For the attributes of the AMB we use tags. +The transformation uses JSON-flattening with `:` as the delimiter to convert nested AMB metadata structures into flat Nostr tags. Additionally, Nostr-native tag conventions are used where applicable for better interoperability and query efficiency. -For attributes expecting values of controlled vocabularies, we use this scheme: +### Nostr-Native Conventions -`[, , , ]` +This NIP follows Nostr conventions where they align with AMB requirements: -For properties that expect arrays, each value is represented as a separate tag with the same key. +- **`t` tags**: Used for keywords/topics (instead of flattened `keywords` tags) +- **`p` tags**: Used for creator/contributor references when the creator has a Nostr identity (pubkey), with fallback to flattened structure for non-Nostr identifiers +- **`a` tags**: Used for references to other addressable events on Nostr (including other AMB events), with fallback to flattened URIs for external resources + +### Flattening Rules + +1. **Simple properties**: Map directly to tags + - AMB: `{"name": "Resource Title"}` + - Nostr: `["name", "Resource Title"]` + +2. **Nested objects**: Flatten using `:` delimiter + - AMB: `{"creator": {"name": "John", "id": "123"}}` + - Nostr: `["creator:name", "John"]`, `["creator:id", "123"]` + +3. **Arrays**: Repeat the same flattened tag key (order is preserved by tag array position) + - AMB: `{"keywords": ["Math", "Physics"]}` + - Nostr: `["t", "Math"]`, `["t", "Physics"]` (Nostr-native `t` tag) + +4. **Arrays of objects**: Repeat flattened keys for each object + - AMB: `{"creator": [{"name": "John"}, {"name": "Jane"}]}` + - Nostr: `["creator:name", "John"]`, `["creator:name", "Jane"]` + +5. **Deep nesting**: Continue flattening with additional `:` delimiters + - AMB: `{"creator": {"affiliation": {"name": "MIT"}}}` + - Nostr: `["creator:affiliation:name", "MIT"]` + +### Property Mappings This is how we convert each property of the AMB: -General: +**General:** -- `id`: `["d", ]` (we use nostr's `d`-tag here as identifier) -- `type`: `["type", , , ...]` -- `name`: `["name", ]` -- `description`: `["description", , ]` (language optional, not specified in AMB) -- `about`: `["about", , , ,]` -- `keywords`: `["keywords", , , ...]` -- `inLanguage`: `["inLanguage", , , ...]` -- `image`: `["image", ]` -- `trailer`: `["image", , , , , , , ]` +- `id` → `["d", ]` (special case: use Nostr's `d` tag as identifier) +- `type` → `["type", ]` (repeat for multiple types) +- `name` → `["name", ]` +- `description` → `["description", ]` +- `about` (array of concept objects) → Repeat for each: + - `["about:id", ]` + - `["about:prefLabel",