Docs
Specifications
Metadata
Note Metadata

Note Metadata

Note metadata is a way to store information about a note.

This information is stored in a separate file. It is usually stored in IPFS, but it can be stored in an alternative way so long as the client can access it.

Note Metadata File

The note metadata file is a JSON file. Here is an example:

{
  "title": "Hello World",
  "content": "# Hello World\n\nThis is a markdown note.",
  "tags": ["article", "dairy"],
  "sources": ["xlog"],
  "external_urls": ["https://twitter.com/_Crossbell/status/1555900801058488322"],
  "date_published": "2022-01-01T00:00:00Z",
  "attributes": [
    { "value": "post", "trait_type": "type" },
    { "value": "https://example.com", "trait_type": "URL" },
    { "value": 1546360800, "trait_type": "Birthday", "display_type": "date" }
  ],
}

Note Metadata Schema

The note metadata schema is defined as follows:

export class NoteMetadataAttachmentBase<
  ContentType extends 'address' | 'content',
> {
  /**
   * The name of this attachment.
   */
  name?: string
 
  /**
   * The address (url) of this attachment.
   */
  address?: ContentType extends 'address' ? string : never
 
  /**
   * The plain content of this attachment.
   */
  content?: ContentType extends 'content' ? string : never
 
  /**
   * The mime type of the `content`.
   */
  mime_type?: string
 
  /**
   * The size of the `content` in bytes.
   */
  size_in_bytes?: number
 
  /**
   * The alternate text (description) of this attachment.
   * This is used for accessibility or is displayed when the source is not available.
   */
  alt?: string
 
  /**
   * The width of this attachment, in pixels.
   */
  width?: number
 
  /**
   * The height of this attachment, in pixels.
   */
  height?: number
}
 
export class NoteMetadata extends Mixin(BaseMetadata, AttributesMetadata) {
  /**
   * The title of this note.
   */
  title?: string
 
  /**
   * The (markdown) content of this note.
   *
   * @example
   * '# Hello World\n\nThis is a markdown note.'
   */
  content?: string
 
  /**
   * The tags of this note.
   *
   * @example
   * ['article', 'dairy']
   */
  tags?: string[]
 
  /**
   * The attachments of this note.
   */
  attachments?:
    | (
        | NoteMetadataAttachmentBase<'address'>
        | NoteMetadataAttachmentBase<'content'>
      )[]
 
  /**
   * The source of this note. I.e. where it was originally created.
   * For example, it could be your app's name so that you could filtering the notes by the source in your app.
   *
   * @example
   * ['xlog']
   */
  sources?: string[]
 
  /**
   * Where this note was created. User can view this note on this location.
   *
   * @example
   * ['https://twitter.com/_Crossbell/status/1555900801058488322']
   */
  external_urls?: string[]
 
  /**
   * The date this content was published, following the ISO 8601 format.
   *
   * Example case: a blog post was originally published on a website at time A,
   * then was synced to the blockchain at time B.
   * The `date_published` of the note is time A.
   * The date of the blockchain sync is time B (shown as the `createdAt` field
   * in the indexer's response).
   *
   * @example
   * '2022-01-01T00:00:00Z'
   */
  date_published?: string
 
  /**
   * A content warning for this note. On the client side, this will be displayed as a warning.
   *
   * @example
   * 'nsfw'
   */
  content_warning?: 'nsfw' | 'sensitive' | 'spoiler'
 
  /**
   * The variant of this note.
   *
   * - `undefined`: the normal note.
   * - `"achievement"`: the achievement variant.
   *
   * @example
   * 'achievement'
   */
  variant?: 'achievement'
 
  /**
   * Custom attributes.
   *
   * @example
   * [{ value: "post", trait_type: "type" }, { value: "https://example.com", trait_type: "URL" }, { value: 1546360800, trait_type: 'Birthday', "display_type": "date" }]
   */
  attributes?: {
    value: string | number | boolean | null
    trait_type?: string
    display_type?: 'string' | 'number' | 'date' | 'boolean'
  }[]
}

title

The title.

content

The (markdown) content.

"# Hello World\n\nThis is a markdown note."

tags

The tags. It is an array of any strings. It is used to categorize the note.

["article", "dairy"]

attachments

The attachments. It can include medias like images, videos, etc.

For example:

[
  {
    "name": "image.png",
    "address": "ipfs://QmW1Y2Z3X4C5V6B7N8M9K0J1H2G3F4D5S6A7Q8W9E0R1T2Y3U4I5O6P7L8",
    "mime_type": "image/png",
    "size_in_bytes": 123456,
    "alt": "A picture of a cat.",
    "width": 1024,
    "height": 768
  },
  {
    "name": "video.mp4",
    "address": "ipfs://QmW1Y2Z3X4C5V6B7N8M9K0J1H2G3F4D5S6A7Q8W9E0R1T2Y3U4I5O6P7L8",
    "mime_type": "video/mp4",
    "size_in_bytes": 123456,
    "alt": "A video of a cat.",
    "width": 1024,
    "height": 768
  }
]

sources

The source of this note. I.e. where it was originally created. For example, it could be your app's name so that you could filtering the notes by the source in your app.

external_urls

Where this note was originally created. User can view this note on this location.

For example, if you create a note on Twitter, and then sync it to Crossbell, you can put the URL of the original tweet in this field:

["https://twitter.com/_Crossbell/status/1555900801058488322"]

date_published

The date this content was published, following the ISO 8601 format.

"2022-01-01T00:00:00Z"

If not specified, the note created time on blockchain will be used as the published date.

content_warning

A content warning for this note. On the client side, this will be displayed as a warning.

There are three types of content warnings:

  • nsfw: Not Safe For Work. It is used to mark content that is not suitable for work.
  • sensitive: It is used to mark content that is sensitive.
  • spoiler: It is used to mark content that contains spoilers.

variant

The variant of this note.

There are two variants:

attributes

Custom attributes.

[
  { "value": "post", "trait_type": "type" },
  { "value": "https://example.com", "trait_type": "URL" },
  { "value": 1546360800, "trait_type": "Birthday", "display_type": "date" }
]