Skip to content

Widgets

DomeNinchen edited this page Oct 16, 2026 · 6 revisions

Server Widgets

A widget is an embeddable, public snapshot of a server — the kind of live status banner you put on a website or forum so visitors can see who's online without opening TeamSpeak. You manage them from the Embed widgets button on the Dashboard (admins only) — not to be confused with the dashboard's own tiles, which every user arranges for themselves.

Creating one

In the widget manager, Create and set:

  • Name — for your own reference.
  • Server and Virtual Server ID — which server it reports on.
  • Theme — a visual style for the rendered banner.
  • Show Channel Tree / Show Clients — what the widget includes.
  • Hide Empty Channels and Max Channel Depth — trim a large tree down to something that fits in a banner.

Who counts as online

A widget's user count leaves out ServerQuery logins. An admin can narrow it further in a widget's Edit view, under Online count of the embed widgets: tick server groups whose clients should not be counted, and turn on Don't count this manager's music bots to leave out its own music bots. The setting belongs to the virtual server, so it applies to every widget of that server, and it is separate from the dashboard's own setting. Only the number changes; a widget's channel tree still lists every client.

How it's embedded — and the token

Each widget gets its own token, and that token is the public key to it: anyone with the URL can view the widget without logging in, and only that one widget's data is exposed. Three forms are served, all under /api/widget/<token>/:

URL Use
…/<token>/image.svg Sharp vector image — best for a web page
…/<token>/image.png Raster image — for places that won't render SVG, like some forum software
…/<token>/data Raw JSON — if you want to build your own display

There's also a live embed (an <iframe> snippet the manager gives you) for a self-updating banner rather than a static image. The manager's SVG and embed buttons copy the right URL or snippet for you.

Because the token grants public read access, treat it like a shared link: regenerating or deleting the widget invalidates the old URL. Widget responses are briefly cached, so a change on your server shows up within a short delay rather than instantly.

If the embedded widget stays blank

The live widget page (/widget/<token>) is the one page of the app that other sites may put in an iframe. Every other page refuses to be framed from another site, on purpose.

If the frame on the other site stays empty, the browser's developer console (F12) says why, usually a message like "Framing … violates the following Content Security Policy directive: frame-ancestors" or "Refused to display … in a frame because it set X-Frame-Options". Two causes are worth checking:

  • An older frontend. With the Docker images, frontend versions before 3.66.1 sent the strict "this site only" framing headers on the widget page as well, so the live embed was refused everywhere. Update the frontend. The SVG and PNG images are not framed, so they do not depend on this; they have a check of their own, see the next section.
  • A proxy that sets its own framing headers. A reverse proxy or CDN in front of the app, configured to add X-Frame-Options or a frame-ancestors policy to the whole site, overrides what the app sends. Leave the path /widget/ out of that rule, or don't set the header there.

To see what actually arrives, ask for the widget page and look at the headers (any text works as a token for this check):

curl -sI https://your-manager.example/widget/test

There should be no X-Frame-Options line, and the Content-Security-Policy line should contain frame-ancestors *.

If an SVG or PNG image stays blank on another site

The two images are meant to be loaded by other sites (an <img> tag, a forum's image code), so the backend lets exactly these two be embedded cross-site; its other responses keep the stricter default. If one of them shows as a broken image on the other site, two causes are worth checking:

  • An older backend. Backend versions before 2.52.1 sent Cross-Origin-Resource-Policy: same-origin on the images like on everything else, and browsers refuse to show such an image on another site (Chromium-based browsers log net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin in the developer console). Update the backend. The JSON at …/<token>/data is read with an ordinary cross-origin request and is not affected by this.
  • A proxy that sets its own policy. A reverse proxy or CDN in front of the app, configured to add a Cross-Origin-Resource-Policy header to the whole site, overrides what the app sends. Leave the path /api/widget/ out of that rule, or don't set the header there.

To see what actually arrives, ask for one of your widget's image URLs and look at the headers:

curl -sI https://your-manager.example/api/widget/<token>/image.svg

The Cross-Origin-Resource-Policy line should say cross-origin.

What it does and doesn't expose

A widget shows only what you enabled — channel tree and/or client list for the one virtual server. It's read-only and carries no management access whatsoever; the token can't be used against the rest of the API. Still, it is public, so don't enable the client list on a widget if who's connected is something you'd rather not put on a public page.

The live page stores nothing in the visitor's browser and shows no storage notice, because it sits on somebody else's site; see Privacy and Hosting.


v0.6, last edited 16.10.2026

Getting started

Home
Getting Started
Install on Debian 13
Setup: same machine
Setup: elsewhere / rented
Users and Roles

Using the app

Dashboard
Virtual Servers and Instance
Channels
Clients
Client Database
Permissions
Server and Channel Groups
Moderation
Tokens and Passwords
Files
Icons
Bot Flows
Music Bots
Server Widgets
Server Maintenance
Server Logs
Query Console
Connection Journal
Themes and Appearance

Running it

Administration
Configuration
Deployment
Privacy and Hosting

When something is odd

Tips and Pitfalls
Troubleshooting

Contributing

Development

Repository · Changelog

Clone this wiki locally