mirror of
https://github.com/versia-pub/docs.git
synced 2025-12-06 06:18:19 +01:00
Create initial docs
This commit is contained in:
commit
a3576b7458
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
.vitepress/cache
|
||||
35
.vitepress/config.mts
Normal file
35
.vitepress/config.mts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { defineConfig } from 'vitepress'
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
title: "Lysand Documentation",
|
||||
description: "Documentation for Lysand, a new federated protocol",
|
||||
themeConfig: {
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
nav: [
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Specification', link: '/spec' }
|
||||
],
|
||||
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Spec Details',
|
||||
items: [
|
||||
{ text: 'Spec', link: '/spec' },
|
||||
{ text: "Objects", link: '/objects' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "Structures",
|
||||
items: [
|
||||
{ text: "Content Format", link: '/structures/content-format' },
|
||||
{ text: "Custom Emoji", link: '/structures/custom-emoji' },
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/lysand-org/' }
|
||||
]
|
||||
}
|
||||
})
|
||||
49
api-examples.md
Normal file
49
api-examples.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Runtime API Examples
|
||||
|
||||
This page demonstrates usage of some of the runtime APIs provided by VitePress.
|
||||
|
||||
The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files:
|
||||
|
||||
```md
|
||||
<script setup>
|
||||
import { useData } from 'vitepress'
|
||||
|
||||
const { theme, page, frontmatter } = useData()
|
||||
</script>
|
||||
|
||||
## Results
|
||||
|
||||
### Theme Data
|
||||
<pre>{{ theme }}</pre>
|
||||
|
||||
### Page Data
|
||||
<pre>{{ page }}</pre>
|
||||
|
||||
### Page Frontmatter
|
||||
<pre>{{ frontmatter }}</pre>
|
||||
```
|
||||
|
||||
<script setup>
|
||||
import { useData } from 'vitepress'
|
||||
|
||||
const { site, theme, page, frontmatter } = useData()
|
||||
</script>
|
||||
|
||||
## Results
|
||||
|
||||
### Theme Data
|
||||
<pre>{{ theme }}</pre>
|
||||
|
||||
### Page Data
|
||||
<pre>{{ page }}</pre>
|
||||
|
||||
### Page Frontmatter
|
||||
<pre>{{ frontmatter }}</pre>
|
||||
|
||||
## More
|
||||
|
||||
Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
|
||||
26
index.md
Normal file
26
index.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
# https://vitepress.dev/reference/default-theme-home-page
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: "Lysand"
|
||||
text: "Federation, simpler"
|
||||
tagline: A simple to implement and complete federation protocol
|
||||
actions:
|
||||
- theme: brand
|
||||
text: Protocol Docs
|
||||
link: /spec
|
||||
- theme: alt
|
||||
text: Types
|
||||
link: /types
|
||||
|
||||
features:
|
||||
- title: JSON-based APIs
|
||||
details: Simple JSON objects are used to represent all data
|
||||
- title: Built-in namespaced extensions
|
||||
details: Extensions for common use cases are built-in, such as custom emojis and reactions
|
||||
- title: Easy to implement
|
||||
details: The protocol is simple to implement, and can be used with any language
|
||||
---
|
||||
|
||||
|
||||
85
markdown-examples.md
Normal file
85
markdown-examples.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Markdown Extension Examples
|
||||
|
||||
This page demonstrates some of the built-in markdown extensions provided by VitePress.
|
||||
|
||||
## Syntax Highlighting
|
||||
|
||||
VitePress provides Syntax Highlighting powered by [Shikiji](https://github.com/antfu/shikiji), with additional features like line-highlighting:
|
||||
|
||||
**Input**
|
||||
|
||||
````md
|
||||
```js{4}
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Highlighted!'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output**
|
||||
|
||||
```js{4}
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Highlighted!'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Containers
|
||||
|
||||
**Input**
|
||||
|
||||
```md
|
||||
::: info
|
||||
This is an info box.
|
||||
:::
|
||||
|
||||
::: tip
|
||||
This is a tip.
|
||||
:::
|
||||
|
||||
::: warning
|
||||
This is a warning.
|
||||
:::
|
||||
|
||||
::: danger
|
||||
This is a dangerous warning.
|
||||
:::
|
||||
|
||||
::: details
|
||||
This is a details block.
|
||||
:::
|
||||
```
|
||||
|
||||
**Output**
|
||||
|
||||
::: info
|
||||
This is an info box.
|
||||
:::
|
||||
|
||||
::: tip
|
||||
This is a tip.
|
||||
:::
|
||||
|
||||
::: warning
|
||||
This is a warning.
|
||||
:::
|
||||
|
||||
::: danger
|
||||
This is a dangerous warning.
|
||||
:::
|
||||
|
||||
::: details
|
||||
This is a details block.
|
||||
:::
|
||||
|
||||
## More
|
||||
|
||||
Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).
|
||||
45
objects.md
Normal file
45
objects.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Objects
|
||||
|
||||
Lysand uses JSON (JavaScript Object Notation) objects as its data format. It is meant to be a simple format that is easy to implement and understand.
|
||||
|
||||
All JSON objects such as [Publications](/objects/publications), [Actors](/objects/actors), and [Actions](/objects/actions) **MUST** have the following fields:
|
||||
|
||||
## ID
|
||||
|
||||
The `id` field on an Object is a string that represents the unique identifier of the object. It is used to identify the object, and **MUST** be unique across all objects on the same server.
|
||||
|
||||
The `id` field is not required to be unique across the entire network, but it is recommended that it is. Servers **MUST** use UUIDs or a UUID-compatible system for the `id` field.
|
||||
|
||||
## Created At
|
||||
|
||||
The `created_at` field on an object is a string that represents the date and time that the object was created. It is used to determine the order of objects. The data **MUST** be in ISO 8601 format.
|
||||
|
||||
Example: `2021-01-01T00:00:00.000Z`
|
||||
|
||||
> **Note:** The `created_at` field should be the date and time that the post was actually made, but it is not required to be. Any ISO 8601 date is allowed in the `created_at` field. It is up to the servers to decide if they want to process dates that they would consider invalid, such as dates in the future.
|
||||
|
||||
## URI
|
||||
|
||||
The `uri` field on an object is a string that represents the URI of the object. It is used to identify the object, and **MUST** be unique across all objects. This URI **MUST** be unique across the entire network, and contain the `id` of the object in the URI.
|
||||
|
||||
URIs must follow the rules defined [here](/spec).
|
||||
|
||||
## Type
|
||||
|
||||
The `type` field on an object is a string that represents the type of the object. It is used to determine how the object should be displayed to the user.
|
||||
|
||||
The `type` field **MUST** be one of the following values:
|
||||
- `Note`
|
||||
- `Patch`
|
||||
- `Actor`
|
||||
- `Like`
|
||||
- `Dislike`
|
||||
- `Follow`
|
||||
- `FollowAccept`
|
||||
- `FollowReject`
|
||||
- `Announce`
|
||||
- `Undo`
|
||||
- `ServerMetadata`
|
||||
- `Extension`
|
||||
|
||||
Other values are not allowed in this current iteration of the protocol.
|
||||
10
package.json
Normal file
10
package.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"scripts": {
|
||||
"docs:dev": "vitepress dev",
|
||||
"docs:build": "vitepress build",
|
||||
"docs:preview": "vitepress preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vitepress": "^1.0.0-rc.31"
|
||||
}
|
||||
}
|
||||
27
spec.md
Normal file
27
spec.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Introduction
|
||||
|
||||
The Lysand Protocol is meant to be a protocol for federated applications to communicate with each other using the HTTP stack. It is meant to be a simple protocol that is easy to implement and understand.
|
||||
|
||||
Unlike ActivityPub, Lysand includes many more out of the box features designed for social media applications. It is also designed to be more secure and private by default.
|
||||
|
||||
Lysand tries to be as standardized and possible and discourage use of vendor-specific implementations, such as what Mastodon has done with ActivityPub. It is based on simple JSON objects and HTTP requests, with no need for complex serialization formats.
|
||||
|
||||
TypeScript types are provided in this repository for every object in the protocol, which can be easily adapted to other languages.
|
||||
|
||||
# Design Goals
|
||||
|
||||
Lysand tries to have similar concepts to already existing popular protocols, such as ActivityPub and ActivityStreams. However, it is not compatible with either of them. It is also not compatible with ActivityPub's JSON-LD serialization format.
|
||||
|
||||
Lysand-compatible servers may implement other protocols as well, such as ActivityPub, but they are not required to do so.
|
||||
|
||||
# Required Across Implementations
|
||||
|
||||
All HTTP request bodies and response bodies **MUST** be encoded as UTF-8 JSON, with the `Content-Type` header set to `application/json; charset=utf-8`. If cryptography is supported by the server, there **MUST** also be a `Signature` header as defined in [/signatures](the signatures spec).
|
||||
|
||||
Servers **MUST** use UUIDs or a UUID-compatible system for the `id` field. Any kind of UUID is allowed, as long as it is a valid UUID. It **should** be unique across the entire known network if possible, but this is not needed as long as the server can guarantee that the `id` is unique across the server.
|
||||
|
||||
> **Note**: Implementers of the protocol may prefer to use [UUIDv7](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html#name-uuid-version-7) instead of the popular UUIDv4 in their internal databases, as UUIDv7 is lexicographically sortable by time generated. A PostgreSQL extension available [here](https://github.com/fboulnois/pg_uuidv7).
|
||||
|
||||
All URIs **MUST** be absolute URIs, and **MUST** be HTTPS URIs, except for development purposes. They **MUST** be unique across the entire network, and **MUST** contain the `id` of the object in the URI. They **should not** contain data that can be changed, such as the actor's `username`.
|
||||
|
||||
All URIs **MUST** be normalized, and **MUST NOT** contain any query parameters
|
||||
104
structures/content-format.md
Normal file
104
structures/content-format.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# ContentFormat
|
||||
|
||||
A `ContentFormat` structure can be represented as such in TypeScript:
|
||||
|
||||
```ts
|
||||
interface ContentFormat {
|
||||
content: string;
|
||||
content_type: string;
|
||||
description?: string;
|
||||
size?: number;
|
||||
hash?: {
|
||||
md5?: string;
|
||||
sha1?: string;
|
||||
sha256?: string;
|
||||
sha512?: string;
|
||||
[key: string]: string | undefined;
|
||||
};
|
||||
blurhash?: string;
|
||||
fps?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
duration?: number;
|
||||
}
|
||||
```
|
||||
|
||||
An example value would be:
|
||||
```json
|
||||
{
|
||||
"content": "Hello, world!",
|
||||
"content_type": "text/plain"
|
||||
}
|
||||
```
|
||||
|
||||
Another example:
|
||||
```json
|
||||
{
|
||||
"content": "https://cdn.example.com/attachments/ece2f9d9-27d7-457d-b657-4ce9172bdcf8.png",
|
||||
"content_type": "image/png",
|
||||
"description": "A jolly horse running in the mountains",
|
||||
"size": 123456,
|
||||
"hash": {
|
||||
"sha256": "91714fc336210d459d4f9d9233de663be2b87ffe923f1cfd76ece9d06f7c965d"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `contents` field is a string that contains the actual content of the object. The `content_type` field is a string that contains the MIME type of the content.
|
||||
|
||||
The `content` and `content_type` fields are required on all `ContentFormat` objects, but other fields are optional.
|
||||
|
||||
The `description` field is a string that contains a description of the content. It is used to describe the content to users that cannot see the content, such as users that are blind, or when the content does not load properly. It is not required on all `ContentFormat` objects. If it is not provided, it is assumed that the content does not have a description.
|
||||
|
||||
The `size` field is a number that contains the size of the content in bytes. It is not required on all `ContentFormat` objects. If it is not provided, it is assumed that the content size is not specified.
|
||||
|
||||
It is generally not needed to provide content size for text content, but it is recommended to provide content size for binary content, such as images, videos, and audio. This is useful for clients to determine if they should download the content or not.
|
||||
|
||||
It is expected that files in an array of `ContentFormat` objects (when used to store URLs to files) are the same file, but in different formats. For example, a PNG image and a WebP image. Files in formats such as PDF that cannot be converted to other formats should only be stored once.
|
||||
|
||||
For example, this is acceptable:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"content": "https://cdn.example.com/attachments/ece2f9d9-27d7-457d-b657-4ce9172bdcf8.png",
|
||||
"content_type": "image/png",
|
||||
"description": "A jolly horse running in the mountains",
|
||||
"hash": {
|
||||
"sha256": "91714fc336210d459d4f9d9233de663be2b87ffe923f1cfd76ece9d06f7c965d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"content": "https://cdn.example.com/attachments/ece2f9d9-27d7-457d-b657-4ce9172bdcf8.webp",
|
||||
"content_type": "image/webp",
|
||||
"description": "A jolly horse running in the mountains",
|
||||
"hash": {
|
||||
"sha256": "b493d48364afe44d11c0165cf470a4164d1e2609911ef998be868d46ade3de4e"
|
||||
},
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
But this is not:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"content": "https://cdn.example.com/attachments/ece2f9d9-27d7-457d-b657-4ce9172bdcf8.png",
|
||||
"content_type": "image/png",
|
||||
"description": "A jolly horse running in the mountains"
|
||||
},
|
||||
{
|
||||
"content": "https://cdn.example.com/attachments/ece2f9d9-27d7-457d-b657-4ce9172bdcf8.webp",
|
||||
"content_type": "image/webp",
|
||||
"description": "A jolly horse running in the mountains",
|
||||
},
|
||||
{
|
||||
"content": "https://cdn.example.com/attachments/anotherfile.pdf",
|
||||
"content_type": "application/pdf",
|
||||
"description": "A PDF file about macroeconomics"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Each array of ContentFormat objects should be considered as a SINGLE FILE, and not multiple files. The multiple formats are only meant to save bandwidth.
|
||||
|
||||
If optional fields are provided on one object in the array, they should be provided on all objects in the array. For example, if the `description` field is provided on one object, it should be provided on all objects (since they are the same file).
|
||||
55
structures/custom-emoji.md
Normal file
55
structures/custom-emoji.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# Custom Emojis
|
||||
|
||||
Lysand supports custom emojis. They are represented as such in TypeScript:
|
||||
|
||||
```ts
|
||||
interface Emoji {
|
||||
name: string;
|
||||
alt?: string;
|
||||
url: ContentFormat[];
|
||||
}
|
||||
```
|
||||
|
||||
Lysand custom emojis are implemented as part of an official optional extension to the protocol. See [Protocol Extensions](#protocol-extensions) for more information.
|
||||
|
||||
Servers **MAY** choose not to implement custom emojis, but it is recommended that they do so.
|
||||
|
||||
An example value would be:
|
||||
```json
|
||||
{
|
||||
"name": "happy_face",
|
||||
"alt": "A happy face emoji.",
|
||||
"url": [
|
||||
{
|
||||
"content": "https://cdn.example.com/emojis/happy_face.webp",
|
||||
"content_type": "image/webp"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The `name` field **MUST** be a string that contains only alphanumeric characters, underscores, and dashes. It **MUST NOT** contain any spaces or other special characters.
|
||||
|
||||
It **MUST** match this regex: `/^[a-zA-Z0-9_-]+$/`
|
||||
|
||||
---
|
||||
|
||||
The `url` field is an array that contains a list of `ContentFormat` objects. It is meant to serve as a list of URLs that the emoji can be accessed at. It is required on all emojis, and **MUST** contain at least one URL.
|
||||
|
||||
The `url` field **MUST** be a binary image format, such as `image/png` or `image/jpeg`. The `url` field **MUST NOT** be a text format, such as `text/plain` or `text/html`.
|
||||
|
||||
---
|
||||
|
||||
The `alt` field is a string that contains the alt text for the emoji. It is used to describe the emoji to users that cannot see the emoji, such as users that are blind, or when the emoji does not load properly.
|
||||
|
||||
The `alt` field is not required on all emojis. If it is not provided, it is assumed that the emoji does not have an alt text.
|
||||
|
||||
---
|
||||
|
||||
Emojis normally do not need to be transcoded into more modern formats, as they are typically small and do not take up much bandwidth. However, servers **MAY** choose to transcode emojis into more modern formats, such as WebP, AVIF, JXL, or HEIF.
|
||||
|
||||
Clients should display the most modern format that they support, such as WebP, AVIF, JXL, or HEIF. If the client does not support any modern formats, it should display the original format.
|
||||
|
||||
> **Note:** Servers may find it useful to use a CDN that can automatically convert images to modern formats, such as Cloudflare. This will offload image processing from the server, and improve performance for clients.
|
||||
|
||||
Emoji size is not standardized, and is up to the server to decide. Servers **MAY** choose to limit the size of emojis, but it is not required. Generally, an upper limit of a few hundred kilobytes is recommended so as to not take up too much bandwidth.
|
||||
Loading…
Reference in a new issue