In the Appearance tab, you’ll find the documentation about the extensions itself. You should read trough the documentation to understand what the package.json
should contain.
Official theme documentation from the TeamSpeak Client
TeamSpeak Extension Information
This file aims to provide information for extension authors to build extensions
for the TeamSpeak client.
Note: This is currently alpha state and subject to change.
This also applies to this documentation, which is probably not as thorough as
you might want.
Please report issues and shortcomings of this documentation
on the usual channels.
Please note that remote content is not allowed to be loaded or accessed
by extensions.
General information
Extensions consist of a folder that must contain all the files necessary for
your extension to work properly.
This folder needs to contain a package.json
file that must follow a specific
format.
The format and content of the package.json is verified to match the
extensions.json
schema that accompanies this
documentation. You may use a validator
to verify that your package.json is valid. The client will also log validation
failures in the log.
In the future the json schema will also be available online (location TBD).
Naming conventions
The folder name of your extension is supposed to follow standard identifier naming.
For example com.teamspeak.dark
or com.teamspeak.themes.dark
would be reasonable identifiers for the default Dark theme included in the client.
The folder name must match your extension identifier in the package.json, and both
must be all lowercase.
Package Information File
The package.json contains information about your extension, such as the content of
the extension, a unique identifier, a public repository containing the source code
and author information. It may optionally contain additional links to community and
support information, as well as a TeamSpeak server address and a public chat room.
Themes
Themes consists of:
- One CSS file, containing all the CSS rules you wish to apply to the client
- One image file, showing a preview of your Theme displayed in the client
- Additional files you require (such as images)
An extension may optionally contain multiple variations of the same theme, if you
wish to provide several different versions (with different accent colors for
example).
However if your themes are vastly different we would strongly suggest to package
them as separate extensions instead.
Example
A sort of minimal example package.json might look as follows:
{
"name": "Example Theme",
"description": "This is an example theme, making everything purple",
"version": "1.0.0",
"identifier": "invalid.example.theme",
"engines": {
"teamspeak": 1
},
"repository": {
"url": "https://github.com/bestDudeEver/themes/",
"directory": "purple",
"type": "git"
},
"image": "preview.png",
"license": "MIT",
"author": {
"name": "Joe Doe",
"email": "[email protected]",
"url": "https://example.net",
"userTag": "[email protected]"
},
"content": {
"themes": [
{
"name": "Purple Theme",
"source": "purple.css",
"image": "purple-preview.png",
"apiVersion": 1
}
]
}
}
Please note that the repository could also just be the link itself, if you don’t
need the other information.
Similarly the author can just be "author": "Joe Doe"
in case you don’t want to
provide the additional details.
JSON scheme to validate the package.json
{
"$schema": "https://json-schema.org/draft-07/schema",
"$id": "https://teamspeak.com/specs/extensions.scheme.json",
"title": "TeamSpeak Extension",
"description": "A TeamSpeak Extension meta data file for the TeamSpeak client",
"type": "object",
"additionalProperties": false,
"required": [ "engines", "identifier", "image", "repository", "author", "description", "name", "version", "content", "license" ],
"properties": {
"engines": {
"type": "object",
"required": [ "teamspeak" ],
"minProperties": 1,
"maxProperties": 1,
"additionalProperties": false,
"properties": {
"teamspeak": {
"description": "The version of the extension meta data information specification this file adheres to",
"type": "integer",
"minimum": 1
}
}
},
"version": {
"description": "The version of this extension. Use SemVer versioning, see https://semver.org",
"type": "string",
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
},
"name": {
"description": "The name of this extension as displayed in the UI",
"type": "string",
"maxLength": 64,
"minLength": 5
},
"description": {
"description": "A short concise description of what this extension does",
"type": "string",
"maxLength": 256,
"minLength": 20
},
"author": {
"description": "Information about the author",
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [ "name" ],
"properties": {
"name": {
"description": "Name of the author",
"type": "string",
"maxLength": 64,
"minLength": 3
},
"email": {
"description": "Contact email address of the author",
"type": "string",
"format": "email"
},
"url": {
"description": "A link to a website to a website of the author",
"type": "string",
"pattern": "^https://.*\\..*"
},
"userTag": {
"description": "Public chat alias of the author. See Settings -> Chat -> User Tags",
"type": "string",
"format": "email"
}
}
},
{
"type": "string",
"maxLength": 64,
"minLength": 3
}
]
},
"homepage": {
"description": "A link where further information can be found about this extension",
"type": "string",
"maxLength": 1024,
"pattern": "^https://.*\\..*"
},
"docsUrl": {
"description": "An optional link where documentation for this extension can be found",
"type": "string",
"maxLength": 1024,
"pattern": "^https://.*\\..*"
},
"repository": {
"description": "The repository information where the source code for this extension can be found",
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [ "type", "url" ],
"properties": {
"type": {
"description": "The type of the repository (e.g. git) ",
"type": "string",
"enum": [ "git", "svn" ]
},
"url": {
"description": "The url of a public git repository that contains the source code for this extension",
"type": "string",
"maxLength": 1024,
"pattern": "^https://.*\\..*"
},
"directory": {
"description": "Optional sub directory within the git repository specified that contains the source code, if the repository contains more than just the source code for this extension",
"type": "string",
"maxLength": 256
}
}
},
{
"type": "string",
"pattern": "^https://.*\\..*",
"minLength": 15,
"maxLength": 512
}
]
},
"community": {
"description": "Optional links to the support / community for this extension",
"type": "object",
"additionalProperties": false,
"properties": {
"room": {
"description": "An optional public room alias, which people can join to discuss or get help with this extension",
"type": "string",
"pattern": "^#.*:([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])(\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]))*$",
"maxLength": 256,
"minLength": 20
},
"server": {
"description": "An optional teamspeak server address, which people can join to discuss or get help with this extension",
"type": "string",
"format": "hostname",
"maxLength": 128,
"minLength": 3
}
}
},
"identifier": {
"description": "A unique identifier for this extension",
"type": "string",
"pattern": "^[a-z]{2,}\\.([a-z]{3,}\\.){1,}[a-z]{3,}$",
"maxLength": 64,
"minLength": 11
},
"image": {
"description": "File name of an image to display for this extension",
"type": "string",
"minLength": 6
},
"license": {
"description": "The license this work falls under",
"type": "string",
"maxLength": 20,
"minLength": 3
},
"keywords": {
"description": "Short concise keywords describing the extension",
"type": "array",
"items": {
"type": "string",
"maxLength": 10,
"minLength": 3
},
"maxItems": 5,
"uniqueItems": true
},
"content": {
"description": "Describes the content of this extension",
"type": "object",
"minProperties": 1,
"additionalProperties": false,
"properties": {
"themes": {
"description": "Information about the theme part of the extension",
"type": "array",
"minItems": 1,
"maxItems": 20,
"uniqueItems": true,
"items": {
"type": "object",
"required": [ "name", "source", "apiVersion", "image" ],
"additionalProperties": false,
"properties": {
"name": {
"description": "The name of this theme variant for UI display",
"type": "string",
"minLength": 4,
"maxLength": 30
},
"source": {
"description": "The source file to load for this theme",
"type": "string",
"pattern": "^[-\\w\\s=\\.]{3,200}$"
},
"apiVersion": {
"description": "The theme API version this theme implements. Future client releases may choose to not load themes that have an incompatible API version",
"type": "integer",
"minimum": 1
},
"image": {
"description": "A small preview image of this theme variant",
"type": "string",
"pattern": "^.*\\.(?:png|svg)$",
"maxLength": 128,
"minLength": 6
}
}
}
}
}
}
}
}
How to create the Extension?
After you’ve created the extension folder with the package.json itself, you’ll add a CSS file to the folder. In there you can override code or add new code.
You can add multiple version of the theme, that you will need to declare in the package.json.
Example:
"themes": [
{
"name": "Version 1",
"source": "Version1.css",
"apiVersion": 1,
"image": "Version1.png"
},
{
"name": "Version 2",
"source": "Version2.css",
"apiVersion": 1,
"image": "Version2.png"
}
]
Where to get Code?
You need to start your TeamSpeak Client with this parameters or add them to the desktop shortcut
--remote-debugging-port=9988 --remote-allow-origins=*
Then you’ll need to go into your browser: about://inspect/#devices
Check the check boxes and click on configure and add localhost:9988 as a discovery server.
Then you should see the TS ui pop up below and then you can click inspect. Now you can change the styling and add it to a CSS file later to have it in your theme.
From there on you can inspect elements and edit their appearance for “testing” the change.
→ These changes are not permanent.
Add these changes to the CSS.
Image
The image type can be an png or svg. The best resolution that fits the frame of the window is 1024x768
px.