Shared lexicon schemas for long-form publishing on AT Protocol. Uses typescript to json via prototypey.

Add lexicon schemas

aka.dad cbea21ae 7936d642

verified
+1
src/constants.ts
··· 1 + export const MB = 1000000; // 1MB
+60
src/lexicons/site.standard.document.ts
··· 1 + import { lx } from 'prototypey' 2 + import { MB } from '../constants.ts' 3 + 4 + export const siteStandardDocument = lx.lexicon('site.standard.document', { 5 + main: lx.record({ 6 + key: 'tid', 7 + type: 'record', 8 + record: lx.object({ 9 + site: lx.string({ 10 + required: true, 11 + format: 'uri', 12 + description: 'Required URI for parent site or publication (https:// or at://). Use https:// for loose documents. Avoid trailing slashes.' 13 + }), 14 + path: lx.string({ 15 + description: 'Optional path, combined with site or publication url value to construct a full url to the document. Prepend with a leading slash.' 16 + }), 17 + title: lx.string({ 18 + required: true, 19 + maxLength: 1280, 20 + maxGraphemes: 128, 21 + description: 'Required title of the document.' 22 + }), 23 + description: lx.string({ 24 + maxLength: 3000, 25 + maxGraphemes: 300, 26 + description: 'Optional brief description or expert of the document.' 27 + }), 28 + coverImage: lx.blob({ 29 + maxSize: 1 * MB, 30 + accept: ['image/*'], 31 + description: 'Optional image to use as the documents cover. Less than 1MB is size.' 32 + }), 33 + content: lx.union([], { 34 + closed: false, 35 + description: 'Optional open union to construct content within the record. Can be extended with other lexicons to define any content format.' 36 + }), 37 + textContent: lx.string({ 38 + description: 'Optional plaintext representation of the documents contents. Useful for search and other cases.' 39 + }), 40 + bskyPostRef: lx.ref('com.atproto.repo.strongRef', { 41 + description: 'Optional strong reference to a Bluesky post. Useful to keep track of comments off-platform.' 42 + }), 43 + tags: lx.array({ 44 + type: 'string', 45 + }, { 46 + maxLength: 100, 47 + description: 'Optional array of strings used to tag/categorize the document. Avoid prepending tags with hashtags ("#").' 48 + }), 49 + publishedAt: lx.string({ 50 + required: true, 51 + format: 'datetime', 52 + description: 'Required timestamp of the documents publication.' 53 + }), 54 + updatedAt: lx.string({ 55 + format: 'datetime', 56 + description: 'Optional timestamp of the documents last edit.' 57 + }) 58 + }), 59 + }) 60 + })
+16
src/lexicons/site.standard.graph.subscription.ts
··· 1 + import { lx } from 'prototypey' 2 + 3 + export const siteStandardGraphSubscription = lx.lexicon('site.standard.graph.subscription', { 4 + main: lx.record({ 5 + key: 'tid', 6 + type: 'record', 7 + record: lx.object({ 8 + publication: lx.string({ 9 + required: true, 10 + format: 'at-uri', 11 + description: 'Required publication at-uri.' 12 + }) 13 + }), 14 + description: 'Record declaring a subscription to a publication.' 15 + }) 16 + })
+44
src/lexicons/site.standard.publication.ts
··· 1 + import { lx } from 'prototypey' 2 + import { siteStandardThemeBasic } from './site.standard.theme.basic.ts' 3 + import { MB } from '../constants.ts' 4 + 5 + export const siteStandardPublication = lx.lexicon('site.standard.publication', { 6 + main: lx.record({ 7 + key: 'tid', 8 + type: 'record', 9 + record: lx.object({ 10 + url: lx.string({ 11 + required: true, 12 + format: 'uri', 13 + description: 'Required base publication URL (ex: https://standard.site).' 14 + }), 15 + icon: lx.blob({ 16 + maxSize: 1 * MB, 17 + accept: ['image/*'] 18 + }), 19 + name: lx.string({ 20 + required: true, 21 + maxLength: 1280, 22 + maxGraphemes: 128, 23 + description: 'Required name of the publication.' 24 + }), 25 + description: lx.string({ 26 + maxLength: 3000, 27 + maxGraphemes: 300, 28 + description: 'Optional brief description of the publication.' 29 + }), 30 + basicTheme: lx.ref(siteStandardThemeBasic.json.id, { 31 + description: 'Optional simplified publication theme for tools and apps to easily implement when displaying content.' 32 + }), 33 + preferences: lx.ref('#preferences', { 34 + description: 'Optional object containing platform specific preferences (with a few shared properties).' 35 + }) 36 + }), 37 + }), 38 + preferences: lx.object({ 39 + showInDiscover: lx.boolean({ 40 + default: true, 41 + description: 'Optional boolean which decides whether the publication should appear in discovery feeds.' 42 + }) 43 + }) 44 + })
+27
src/lexicons/site.standard.theme.basic.ts
··· 1 + import { lx } from 'prototypey' 2 + import { siteStandardThemeColor } from './site.standard.theme.color.ts' 3 + 4 + export const siteStandardThemeBasic = lx.lexicon('site.standard.theme.basic', { 5 + main: lx.record({ 6 + key: 'tid', 7 + type: 'record', 8 + record: lx.object({ 9 + background: lx.union([siteStandardThemeColor.json.id + '#rgb'], { 10 + required: true, 11 + description: 'Required color used for content background.' 12 + }), 13 + foreground: lx.union([siteStandardThemeColor.json.id + '#rgb'], { 14 + required: true, 15 + description: 'Required color used for content text.' 16 + }), 17 + accent: lx.union([siteStandardThemeColor.json.id + '#rgb'], { 18 + required: true, 19 + description: 'Required color used for links and button backgrounds.' 20 + }), 21 + accentForeground: lx.union([siteStandardThemeColor.json.id + '#rgb'], { 22 + required: true, 23 + description: 'Required color used for button text.' 24 + }) 25 + }), 26 + }) 27 + })
+43
src/lexicons/site.standard.theme.color.ts
··· 1 + import { lx } from 'prototypey' 2 + 3 + export const siteStandardThemeColor = lx.lexicon('site.standard.theme.color', { 4 + rgb: lx.object({ 5 + r: lx.integer({ 6 + required: true, 7 + minimum: 0, 8 + maximum: 255 9 + }), 10 + g: lx.integer({ 11 + required: true, 12 + minimum: 0, 13 + maximum: 255 14 + }), 15 + b: lx.integer({ 16 + required: true, 17 + minimum: 0, 18 + maximum: 255 19 + }) 20 + }), 21 + rgba: lx.object({ 22 + r: lx.integer({ 23 + required: true, 24 + minimum: 0, 25 + maximum: 255 26 + }), 27 + g: lx.integer({ 28 + required: true, 29 + minimum: 0, 30 + maximum: 255 31 + }), 32 + b: lx.integer({ 33 + required: true, 34 + minimum: 0, 35 + maximum: 255 36 + }), 37 + a: lx.integer({ 38 + required: true, 39 + minimum: 0, 40 + maximum: 100 41 + }) 42 + }), 43 + })