extracted spec from an ADR for implementing an atproto client and public lexicon
livtet_lexicon.md
113 lines 3.6 kB view raw view rendered
1### ATProto Lexicons 2 3ATProto lexicons use JSON with NSID identifiers. The lexicon format includes `lexicon`, `id`, `defs`, and record/query/procedure types. Custom lexicons are stored as JSON and embedded via `include_str!`. 4 5Domain: `livtet.app` (user owns this domain). Not a full PDS implementation—just a minimal lexicon server. 6 7**`app.livtet.work`** - Work record (literary work like "Frankenstein"): 8 9```json 10{ 11 "lexicon": 1, 12 "id": "app.livtet.work", 13 "defs": { 14 "main": { 15 "type": "record", 16 "description": "A literary work tracked by Livtet.", 17 "key": "tid", 18 "record": { 19 "type": "object", 20 "required": ["name", "language", "datePublished"], 21 "properties": { 22 "name": { "type": "string", "description": "Title of the work" }, 23 "language": { "type": "string", "description": "ISO 639-1 language code" }, 24 "datePublished": { "type": "string", "format": "datetime" }, 25 "description": { "type": "string" }, 26 "series": { "type": "ref", "ref": "app.livtet.defs#seriesRef" }, 27 "identifiers": { 28 "type": "array", 29 "items": { "type": "ref", "ref": "app.livtet.defs#identifier" } 30 } 31 } 32 } 33 } 34 } 35} 36``` 37 38**`app.livtet.edition`** - Edition record (specific form of a work): 39 40```json 41{ 42 "lexicon": 1, 43 "id": "app.livtet.edition", 44 "defs": { 45 "main": { 46 "type": "record", 47 "description": "A specific edition of a work.", 48 "key": "tid", 49 "record": { 50 "type": "object", 51 "required": ["work", "format"], 52 "properties": { 53 "work": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 54 "format": { 55 "type": "union", 56 "refs": ["app.livtet.defs#physicalFormat", "app.livtet.defs#virtualFormat", "app.livtet.defs#audiobookFormat"] 57 }, 58 "datePublished": { "type": "string", "format": "datetime" }, 59 "seriesIndex": { "type": "integer" }, 60 "url": { "type": "string", "format": "uri" }, 61 "identifiers": { 62 "type": "array", 63 "items": { "type": "ref", "ref": "app.livtet.defs#identifier" } 64 } 65 } 66 } 67 } 68 } 69} 70``` 71 72**`app.livtet.readProgress`** - Reading progress record: 73 74```json 75{ 76 "lexicon": 1, 77 "id": "app.livtet.readProgress", 78 "defs": { 79 "main": { 80 "type": "record", 81 "description": "Reading progress for a specific edition.", 82 "key": "tid", 83 "record": { 84 "type": "object", 85 "required": ["edition", "progress", "updatedAt"], 86 "properties": { 87 "edition": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 88 "progress": { "type": "integer", "minimum": 0, "maximum": 100 }, 89 "lastPosition": { "type": "string" }, 90 "updatedAt": { "type": "string", "format": "datetime" }, 91 "highlights": { "type": "array", "items": { "type": "ref", "ref": "#highlight" } } 92 } 93 } 94 }, 95 "highlight": { 96 "type": "object", 97 "properties": { 98 "text": { "type": "string" }, 99 "location": { "type": "string" }, 100 "note": { "type": "string" }, 101 "createdAt": { "type": "string", "format": "datetime" } 102 } 103 } 104 } 105} 106``` 107 108Supporting definitions in `app.livtet.defs`: 109- `seriesRef`: `{ seriesId: string }` 110- `identifier`: `{ type: string, value: string }` (e.g., `{"type": "isbn", "value": "978-0-123456-78-9"}`) 111- `physicalFormat`: `{ pages: integer }` 112- `virtualFormat`: `{ size: integer }` (bytes) 113- `audiobookFormat`: `{ duration: integer }` (seconds)