How to create a Custom theme for TeamSpeak 6

Official Documentations

You can either find the Documentation in the Client beside the theme selector, or just open up these spoilers:

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 start?

I’ll recommend looking at other themes first before doing one from scratch. On those you can start making modifications or start all over with a template. They can be found here: ts6-theme


How to access the CSS to modify / Open the element inspector

You need to start your TeamSpeak Client with these parameters or add them to the desktop shortcut

--remote-debugging-port=9988 --remote-allow-origins=*

Then head over to this this site: about://inspect/#devices

Tick these boxes and add http://localhost:9988 to the target discovery and after a bit of waiting the client should show up. Click on Inspect and from there on you can view and copy the necessary CSS components.

:information_source: You might need to use inspect fallback if the view is unresponsive.

:information_source: All changes does here are not permanent! They are only available for this session.


Recommended resolutions for images

The image type can be an png or svg. The best resolution that fits the frame of the window is 1024x768 px.

5 Likes

sorry for the late response but I wanted to thank you :smiling_face_with_tear:

3 Likes

is this still working with TS6? Didn’t get it working …

with TS6 it seems to work via this link
localhost:[port]/devtools/inspector.html/?ws=localhost:[port]/devtools/page/[id]

3 Likes

Hey m8 can you tell me how you edit the style?
the

--remote-debugging-port=9222

way is not working with the new TS6 update on my end even with chrome as browser. :confused:

I’ve recently updated my post here.

3 Likes