# Extensions

Extensions are a way to add custom functionality to Versia.

Versia's core provides users, subscriptions, and the rules for exchanging entities between instances. Everything else comes from extensions, which add entities, fields and behavior without any changes to the core. Posts, for example, come from the [Social extension](/extensions/social).

Extensions can be implemented in any combination that meets their [requirements](#requirements).

Extensions **SHOULD** be standardized and publicly documented.

## Documented Extensions

These extensions are documented on this site, and all use the `pub.versia` namespace and are at [version](#versions) 1. See [Naming](#naming) for how their names are formed.

- [Custom Emojis](/extensions/custom-emojis) (`pub.versia:custom_emojis`): Adds custom emojis to any entity with text content.
- [Decorations](/extensions/decorations) (`pub.versia:decorations`): Adds a User's header image, images around their avatar, a profile background and a profile sound.
- [Delegation](/extensions/delegation) (`pub.versia:delegation`): Lets users show their actions under another user's name.
- [Domain Handles](/extensions/domain-handles) (`pub.versia:domain_handles`): Lets users be shown by a domain they own, such as @joe.example.
- [Groups](/extensions/groups) (`pub.versia:groups`): Organizes users and notes into communities.
- [Instance Messaging](/extensions/instance-messaging) (`pub.versia:instance_messaging`): Lets instances send each other federation debug messages.
- [Interaction Controls](/extensions/interaction-controls) (`pub.versia:interaction_controls`): Lets users control who can interact with their notes.
- [Likes](/extensions/likes) (`pub.versia:likes`): Lets users like and dislike notes.
- [Migration](/extensions/migration) (`pub.versia:migration`): Lets users move their subscribers and subscriptions to another instance.
- [Polls](/extensions/polls) (`pub.versia:polls`): Lets users create and vote on polls.
- [Profile](/extensions/profile) (`pub.versia:profile`): Adds a User's bio, custom fields, pronouns, birthday, location and time zone.
- [Reactions](/extensions/reactions) (`pub.versia:reactions`): Lets users react to notes with emojis.
- [Reports](/extensions/reports) (`pub.versia:reports`): Reports content to the moderators or administrators of a remote instance for review.
- [Share](/extensions/share) (`pub.versia:share`): Lets users share notes with others.
- [Social](/extensions/social) (`pub.versia:social`): Lets users post notes, with visibility, mentions, replies, quotes and a collection of each user's notes.

An extension does not need to be listed here to be used. To propose one for this list, [open an issue](https://github.com/versia-pub/docs/issues).

## Handling Unsupported Extensions

When an extension is not supported by an Implementation, it can be ignored. This means that the extension is not processed, and its data is not used. Implementations **MUST NOT** throw an error when encountering an unsupported extension, as long as the rest of the entity is valid. An entity whose type comes from an unsupported extension is [answered with a `2xx` status code and dropped](/validation#unknown-fields-and-types).

Extensions **MUST NOT** be designed in a way that makes them required to understand or process core entities, or the entities of an extension that does not [require](#requirements) them.

## Requirements

An extension can build on another, for example by adding interactions to entities that the other extension defines. It then **requires** that extension. Its page lists the extensions it requires, each with a [version](#versions). For example, [`pub.versia:likes@1`](/extensions/likes) requires [`pub.versia:social@1`](/extensions/social), because likes are given to Notes, which Social defines.

An Instance that lists an extension in [`compatibility.extensions`](/entities/instance-metadata) **MUST** also list every extension it requires, at the required version. An extension **MUST NOT** require itself, directly or through other extensions.

## Naming

Versia extension names are composed of two parts:

- The domain name of the extension author, in reverse order. Example: `pub.versia`
- The extension name, separated by a colon, in `snake_case`. Example: `likes`

```text title="Example Extension Name"
pub.versia:likes
```

The namespace **MUST** come from a domain the author controls. `pub.versia` is reserved for extensions defined in this specification.

> Matrix names custom event types the same way, such as `com.example.myapp.event`. ActivityPub uses JSON-LD contexts instead. See [Other Protocols](/other-protocols#plain-json-and-namespaces).

### Entity Names

Custom entities are named in the same way, but with an additional part:

- The entity name, separated by a slash, in `PascalCase`. Example: `Like`

```text title="Example Custom Entity Type"
pub.versia:likes/Like
```

## Versions

An extension's version is a whole number that starts at 1, and goes up only when a change is incompatible. Extension keys, entity types and endpoints do not include it.

Instances list what they support in [`compatibility.extensions`](/entities/instance-metadata), as the extension name and version joined by `@`. They **MAY** list several versions of an extension.

```text title="Example Supported Extension"
pub.versia:likes@1
```

Two instances that both list an extension use the highest version they have in common. If they have none in common, the sender **MUST** leave out that extension's data: its key in `extensions`, its entity types and its collections. The same applies when the version they would use requires an extension that they do not have in common at the required version.

## Extension Definition

Extensions can add any of the following:

- Custom functionality on an existing entity, through its [`extensions` property](#entity-extension).
- New entity types, as [custom entities](#custom-entity).
- [Collections](#collections) on an entity.
- [Endpoints](#endpoints).
- [Interaction types](/extensions/interaction-controls).

### Entity Extension

**Fields**

- `extensions` (`Record<string, JSONData>`): Custom extensions to the entity.

  - `key`: The extension name.
  - `value`: Extension data. **MUST** be a JSON object, following [Versia JSON rules](/json).

```jsonc title="Example Entity Extension"
{
    "type": "pub.versia:groups/Group",
    "id": "033j6qrwzt002",
    "created_at": "2021-01-01T00:00:00Z",
    "open": true,
    "extensions": {
        "com.example:gps": {
            "location": {
                "latitude": 37.7749,
                "longitude": -122.4194
            },
            "accuracy": 10,
            "name": "San Francisco"
        }
    }
}
```

### Custom Entity

**Fields**

- `type` (`string`, required): The extension type, [following naming conventions](#naming).

- `other`: Other properties of the custom entity. These are specific to the extension, and **SHOULD** be documented by the extension author.

  Note that `id` and `created_at` are still required for custom entities, unless the extension author specifies otherwise.

```jsonc title="Example Custom Entity"
{
    "type": "com.example:bookmarks/Bookmark",
    "id": "033fsr7ggg004",
    "author": "example.com:033wv9k6n0007",
    "created_at": "2021-01-01T00:00:00Z",
    "target": "example.com:033qtdbdkj006",
    "label": "Read later"
}
```

### Collections

An extension's [collections](/structures/collection) are named like its custom entities, for example `pub.versia:likes/Likes`.

### Endpoints

An extension's endpoints **MUST** be under `/.versia/v0.X/extensions/{extension_name}/`. This keeps them from colliding with core endpoints or with other extensions. The extension name is [not percent-encoded](/federation/http#encoding).

```text title="Example Extension Endpoint"
/.versia/v0.7/extensions/pub.versia:instance_messaging/messaging
```
