Version 4.1.0 · All versions

All pages

These are the docs as released with Solid Memo 4.1.0. Read the latest docs.

Vocabulary

Solid Memo stores its data as linked data (RDF), where every kind of thing and every property is named by a web address. Where no existing standard has a term, as for a card's review schedule, Solid Memo defines its own. This page says where those terms are defined, how they are versioned, and how code is generated from them.

Solid Memo's own RDF terms, where they are defined, how they are versioned and how the app's constants are produced from them. The namespace is https://solid-memo.com/ns/vocab/v1.ttl# — declared as solid-memo: in the Turtle files, abbreviated to sm: in these docs; no existing vocabulary covers spaced repetition.

Source of truth

The vocabulary lives in this repository's ns/vocab/ folder and is published with the site at https://solid-memo.com/ns/vocab/ (ns.ts, deployment.md). Its documents are v1.ttl (the ontology), topics.ttl (the topics scheme) and external.ttl (reference data), each at an address that is also its IRI and its @base, so every term IRI is a fragment of the document that defines it. Changes to them go through git and CI like any other change (ci.yml).

ns/vocab/v1.ttl is an RDFS/OWL ontology: the owl:Ontology subject carries owl:versionInfo and a skos:changeNote per release, and every term is an owl:Class, owl:DatatypeProperty (literal-valued, with an xsd: range) or owl:ObjectProperty (IRI-valued) with rdfs:label, rdfs:comment, rdfs:domain where it has one class, rdfs:range, rdfs:isDefinedBy and a skos:historyNote saying when it arrived.

Where the vocabulary goes
The vocabulary's Turtle file generates the TypeScript constants and is published with the site, where it is read as reference data.
The diagram's source
flowchart LR
    accTitle: Where the vocabulary goes
    accDescr: The vocabulary's Turtle file generates the TypeScript constants and is published with the site, where it is read as reference data.
    ttl["ns/vocab/v1.ttl"] -->|npm run generate| ts["src/vocab.generated.ts<br/>SM constants"]
    ttl -->|npm run build| dist["dist/ns/vocab/v1.ttl"]
    ts --> app["mappers, tooling"]
    dist -->|read at runtime| refs["reference data<br/>(profile checks)"]

SM in vocab.ts is a re-export of the generated constants; the external vocabularies there (Solid terms, PIM space, Dublin Core terms, RDF, RDFS, FOAF) are not ours to publish and stay hand-written. standards.md lists every vocabulary and specification Solid Memo uses, with its version and status. The generator copies each term's comment and history note into the constant's JSDoc, so the meaning is one hover away.

Concept schemes

Where a value is one of a fixed set, it is a SKOS concept, not a string, so other applications can look up what it means:

SchemeWhereConceptsUsed by
sm:StudyDirectionsv1.ttlsm:frontToBack, sm:backToFront, sm:bidirectionalsm:studyDirection on a deck
sm:InvalidDataPoliciesv1.ttlsm:blockInstance, sm:blockSubject (default), sm:warnOnlysm:invalidDataPolicy in preferences
sm:Themesv1.ttlsm:systemTheme (default), sm:lightTheme, sm:darkThemesm:theme in preferences (theme.md)
sm:AnswerModesv1.ttlsm:recall (absent means this), sm:multipleChoicesm:answerMode on an answer in the answer log
sm:TextFormatsv1.ttlsm:plainText (absent means this), sm:markdownsm:textFormat on a card, a course step or a chapter (Text formats)
sm:Schedulersv1.ttlsm:sm2 (absent means this), sm:fsrs6sm:scheduler on a review state (Review states); sm:studyScheduler in preferences and sm:scheduledWith on a deck schedule (FSRS-6)
Topics (https://solid-memo.com/ns/vocab/topics.ttl)topics.ttllanguages (swedish), geography, computing (linked-data), science (chemistry), art, labour-marketdcat:theme on a deck, next to the EU data theme EDUC

Versioning policy

Courses

Version 1.14 added the terms of a course: a library release that is also a schema:Course, with chapters of steps whose questions are its cards.

TermKindDomain → rangeAlignment
sm:Chapterclasssubclass of schema:Syllabus
sm:Stepclasssubclass of schema:LearningResource
sm:Distractorclasssubclass of schema:Answer
sm:theorydatatype propertyStep → language-tagged textsubproperty of schema:text
sm:checkedByobject propertyStep → Card
sm:reviewQuestionobject propertyChapter → Card
sm:distractorobject propertyCard → Distractorsee also schema:suggestedAnswer
sm:distractorTextdatatype propertyDistractor → text, untagged or tagged as sm:back issubproperty of schema:text
sm:distractorNotedatatype propertyDistractor → language-tagged textsee also schema:answerExplanation
sm:completedChapterobject propertyDeck → Chapter
sm:answerModeobject propertyAnswer → a concept of sm:AnswerModes
sm:chosenDistractorobject propertyAnswer → Distractor

Text formats

Version 1.15 added how a text is written: sm:textFormat, a concept of sm:TextFormats, on the subject that holds the text.

ConceptNotationMeaning
sm:plainTextplainShown as written. The same as no text format; the app writes it where a person chose it, so a deliberate choice is told from a marker an older app lost.
sm:markdownmarkdownCommonMark 0.31.2, with GitHub Flavored Markdown pipe tables as its one extension (skos:broadMatch IANA text/markdown).

Review states

Version 1.16 added what a review state is of, so an app that does not know Solid Memo's naming rule can join a state to its card, and one that schedules by another algorithm can keep its states beside Solid Memo's.

TermKindDomain → rangeAbsent means
sm:reviewOfobject propertyReviewState → Cardthe card the subject is named after: #<cardId> or #<cardId>@back-to-front
sm:reviewDirectionobject propertyReviewState → sm:frontToBack or sm:backToFrontback to front when the subject ends in @back-to-front, else front to back
sm:schedulerobject propertyReviewState → a concept of sm:Schedulerssm:sm2, as every state was before 1.16

The library index

Two terms are written only in the deck library's index, on subjects whose shapes do not own them: sm:cardCount, the cards in use of a listed release, and, since 1.17, sm:newcomerCourse (dcat:Catalog → dcat:DatasetSeries), the course the app offers to someone with no decks yet (courses.md). Absent, none is offered. A pod's catalog.ttl never has it.

Drafts and releases

Three terms of 1.18 let anyone write a release in their own pod and publish it there (the Studio, studio.md):

TermFrom → toWhat
sm:releaseDraftdcat:Catalog → sm:DeckA draft of a release the catalog's owner is writing in the instance: the draft's release document, whose subject is the draft deck itself, as a release is its document.
sm:publishedReleasedcat:Catalog → dcat:DatasetA release the owner published from the instance, frozen once published. Where the catalog is readable, a reader finds the author's releases there.
sm:releasedAssm:Deck → dcat:DatasetOn a draft: the release it was published as. A draft that states it is released, and no longer edited; absent, it is still being written.

The two catalog links belong to no shape, as sm:newcomerCourse does: CatalogV1 does not own them, so the catalog format did not move, and every writer of the catalog keeps them. sm:releasedAs belongs to draft deck format 1 (shapes.md). A link to the release, rather than a flag, says where the draft went.

The answer log

Four terms of 1.19 say how an answer in the answer log was given, each optional on answer format 1:

TermKindDomain → rangeAlignment
sm:recallMillisdatatype propertyAnswer → xsd:integer (milliseconds)
sm:gradeMillisdatatype propertyAnswer → xsd:integer (milliseconds)
sm:priorDuedatatype propertyAnswer → xsd:string (YYYY-MM-DD, as sm:due)
sm:utcOffsetMinutesdatatype propertyAnswer → xsd:integer (minutes east of UTC)

Card labels

1.20 gave the front a label, as 1.8 gave the back:

TermKindDomain → rangeAlignment
sm:frontLabeldatatype propertyCard → xsd:string (language-tagged)

A label is a short caption above a side's text that says what kind of thing that side is ("Country" above "Croatia", "Capital" above "Zagreb"). It is shown whenever its side is, as the question or as the answer, so a card studied both ways says what is asked. The side's text stays the prompt or the answer itself. Card format 6 owns it (shapes.md): card format 5 was published without it, and a published shape is never edited.

FSRS-6

1.21 added a second scheduler, FSRS-6, whose states are kept beside the SM-2 ones (#191):

TermKindDomain → range
sm:fsrs6concept of sm:Schedulers (notation fsrs6)
sm:stabilitydatatype propertyReviewState → xsd:decimal (days, > 0)
sm:difficultydatatype propertyReviewState → xsd:decimal (1–10)
sm:previousStabilitydatatype propertyReviewState → xsd:decimal
sm:previousDifficultydatatype propertyReviewState → xsd:decimal
sm:studySchedulerobject propertyPreferences → a concept of sm:Schedulers
sm:desiredRetentiondatatype propertyPreferences → xsd:decimal (a share: 0.9 is 90%)
sm:schedulerInvitationDismisseddatatype propertyPreferences → xsd:boolean (the learner answered "Not now" to the invitation to switch to FSRS-6)
sm:scheduledWithobject propertyDeckSchedule → a concept of sm:Schedulers

The language of text

Solid Memo's text properties (sm:front, sm:back, sm:frontNote, sm:frontLabel, sm:backLabel, sm:backNote, sm:frontImageDescription, sm:backImageDescription, a course's sm:theory, sm:distractorText and sm:distractorNote, and dcterms:title and dcterms:description on a deck or chapter) say their language with the literal's own language tag ("Huvudstäder"@sv), one value per language, not with a term of ours. A deck's keywords (dcat:keyword) are tagged the same way, the one text with several values per language ("capitals"@en, "countries"@en, "huvudstäder"@sv). Tags are BCP 47, stored in lower case. Text in no language — codes, numbers, symbols ("404", "Fe") — is tagged zxx, BCP 47's "no linguistic content", rather than with a language it is not in; a page shows it with no lang. A card side saved untagged (xsd:string), or a keyword saved before deck format 6, says nothing about its language: it is not known, not none. Which formats require which tags is the shapes' business.

There is no term for a deck's languages: the app works out which languages to offer from the tags the deck's text already uses (see i18n.md). Optional sm:frontLanguage / sm:backLanguage defaults could join the deck's next format, should that prove too weak. dcterms:language is used only on library releases, for DCAT-AP: it names EU authority-table languages and cannot tell a card's front from its back.

License

Everything in ns/ is MIT-licensed, like the rest of the repository (README). The topics scheme says so in its own data, dcterms:license <https://spdx.org/licenses/MIT> on the scheme (since 1.11). The ontology's v1.ttl, the shapes' versions and external.ttl do not state it in their RDF; REUSE.toml states it for every file in ns/ instead, without editing them (style.md). A future version of the ontology or of a shape may state it the way the topics scheme does.

What dereferences

IRIWhat is served
https://solid-memo.com/ns/vocab/v1.ttl#Deck (any term)The ontology, …/ns/vocab/v1.ttl, as Turtle: the term is a subject of it.
https://solid-memo.com/ns/vocab/topics.ttl#geography (any topic)The topics scheme, …/ns/vocab/topics.ttl.
https://solid-memo.com/ns/vocab/external.ttlReference data, not terms of ours: the external terms (EU authority-table entries, media types) Solid Memo data points at, typed so profile validation can check them.

GitHub Pages serves each as text/turtle with Access-Control-Allow-Origin: *, so any application reads it directly. It negotiates no content: the documents are Turtle only, and an IRI without the .ttl would be a 404, which is why the namespace keeps the extension. The turtleDirectoryPlugin in packages/vocab/tooling/publishTurtle.ts emits them into the build and serves them in dev.

Adding a term

  1. Add it to ns/vocab/v1.ttl with every annotation; bump the version and the change note.
  2. npm run generate (CI runs npm run generate:check and fails on drift; the drift test in packages/vocab/tooling/generate.test.ts does too).
  3. Use it in a shape — the fixture test checks that every sm: predicate a shape uses is declared here. A published shape is never edited, so the term goes into the shape's next version (Versioning policy).