Symbiotes are our first supported way of modding, allowing you, the community, to make character sheets, fancy dice rollers, hand-out notes, and so much more!
Thanks to the API, these Symbiotes can load data directly from the game enabling tight integrations. Additionally, you can load regular websites if you prefer, to just use your favorite online resource without having to Alt+Tab out all the time.
If you are not a developer or just want a simple introduction into what Symbiotes are and how to use them, visit this page or watch this video guide. If you are a developer, read on.
To understand how web view based Symbiotes work and create your own, check out the examples provided on our GitHub repository.
The very first step is to activate the feature in the settings:
If you just want to use other people's Symbiotes you're now done and can install the ones you want to use. If you want to make your own Symbiotes, you need to create a manifest that describes the Symbiote you want to make. For some Symbiotes this may be sufficient, but for most, you will also need to create an HTML file to be loaded.
Additionally, we provide templated creation within TaleSpire to set up a mostly blank Symbiote for you to work with. To use it, enable the development mode and then press "Create new Symbiote" in the bottom of the Symbiotes panel:
If you need additional help after reading through the documentation, check out the
#talespire-modding channel on our Discord.
To install a Symbiote, simply open the library and open the "Community Mods" tab.
In there, open the "Symbiotes" section. This shows all Symbiotes available on the mod.io repository, together with a search box. There, search for the Symbiote you want to install and then simply click on it to download and install. All installed mods will be shown in the "Installed" section where they can be removed and updated.
Whenever you want to release your Symbiote to the public you can use the mod.io repository. All mods uploaded (video guide) there will be searchable and downloadable through the in-game mod browser. In the future we want to support third party community repositories in addition to mod.io for the in-game downloader.
Symbiotes that aren't uploaded to mod.io can be installed manually. To do this, simply open the Symbiote directory located at
%AppData%\..\LocalLow\BouncyRock Entertainment\TaleSpire\Symbiotes\. Instead of navigating there manually you can click the "Open Symbiotes Directory" button in either the modding page in the game settings or the Symbiote panel itself. Simply add a folder in there for each Symbiote and drop the Symbiote files into that directory directly. Make sure that the manifest.json is in the root of your Symbiote's folder like so:
[...]\Symbiotes\my_cool_symbiote\manifest.json. All folder and Symbiote creation/editing is detected live by TaleSpire and will cause an automatic reload on changes meaning TaleSpire does not need to be restarted for any of this.
On Linux the Windows folder structure is replicated by Proton (by default) next to the install folder. On the default Steam library folder it is located at
~/.steam/steam/steamapps/compatdata/720620/pfx/drive_c/ with the rest of the Windows folder structure being in there. If you have installed TaleSpire to another library location the
compatdata folder will be in there.
When downloading with the in-game mod downloader, Symbiotes are installed to TaleSpire's app cache:
%AppData%\..\LocalLow\BouncyRock Entertainment\TaleSpire\primary\Mods\Symbiote\, which is different to the manual install location described above. This means there are two entirely separate locations where Symbiotes can be installed to, one handled by TaleSpire itself and one manually by users - this can of course result in the same Symbiote being installed once manually and once through the mod downloader. For this case keep in mind that the log and storage locations are separate for both installs!
While you can develop the basic structure of your Symbiote in any external browser, features that rely on data or interactions with TaleSpire cannot be tested outside of TaleSpire. When loading a Symbiote in TaleSpire you can connect to it with an external browser by loading localhost:8080. For this to work you must first enable Symbiotes debugging in the TaleSpire settings:
The embedded browser is Chromium-based, so you can target that as your platform if you want to just support your project running as a Symbiote in TaleSpire.
Any changes you make to files within the Symbiote directory (excluding files/folders starting with a period: '.') will cause the Symbiote to automatically reload. This means you can have the code open in your favorite IDE and have the Symbiote reload with each saved change.
To create a new Symbiote either use the templated creation or create a manifest.json yourself and add it to the Symbiotes directory.
The list links to the various manifest versions. Note that while deprecated versions are still supported for now, we are phasing them out and you should update your existing Symbiotes to a newer version and not create new ones with those versions.
When a manifest (= any file called
manifest.json) gets parsed it can either succeed, which adds the Symbiote to the list of all others, or it can fail due to various reasons. If parsing the manifest fails, the Symbiote will still be shown in the list, but opening it doesn't load the Symbiote, instead it loads an error page. Parsing can fail for a number of obvious reasons: Incorrect manifest version, required fields being missing, the JSON being corrupted and not parseable, etc.
Additionally to all the ways a manifest could contain invalid data, parsing also fails if two installed Symbiotes have the same interop ID. This is true for both Symbiotes, not just one of them.
The list links to the various API versions. Note that while deprecated versions are still supported for now, we are phasing them out and you should update your existing Symbiotes to a newer version and not create new ones with those versions. API updates that are exclusively additional (eg: a completely new API call) will not bump the version number, this will only be done on changes that potentially change the behavior of existing calls to be able to retain compatibility.
TSobject, which is an alias for
com.bouncyrock.talespire. It may be that this short alias has name conflicts on an existing webpage not made with TaleSpire/Symbiotes in mind, which is why it can be disabled in the manifest. All functions can be accessed by calling
We reserve the right to block any API call if the Symbiote has sent too many in short succession to preserve performance for TaleSpire. Any blocked calls will return the
The API only allows access to information that is accessible through the game normally. This means for example that a Symbiote running on a player's client will only be able to query stats for a mini controlled by them, not for other minis. Similarly a slab cannot be put into the hand of a player, as they don't have permissions to build. There is a distinction between users who can be a GM (= they have permission to be GM) and users who currently are a GM. Most calls that require a certain permission need the user (= player) to be able to switch to GM mode (
canGM is set to true), while they don't care about which mode the client is currently in.
If an API version is specified in the manifest, it is injected by TaleSpire. After this, each extra specified in the extras array in the manifest is injected individually in order of the array. Finally, if the API was injected the API initialization starts. This guarantees that:
Scripts loaded by the HTML file itself are loaded according to normal browser behavior which can be before DOMContentLoaded and before API injection. Deferring or setting an event listener for onLoad can be used to ensure they are loaded at the appropriate time. The
hasInitialized event is fired as soon as the API has finished loading and the communication between TaleSpire and the embedded browser is running.
The entire injection procedure is repeated for every page load. This includes the user navigating away from the entry point by clicking a link or a programmatic page switch using eg: window.open. Because of this it is often best to create Symbiotes as one-pagers that switch out content programmatically if necessary instead of navigating to other pages.
TaleSpire scans the top-level directories under
%AppData%\..\LocalLow\BouncyRock Entertainment\TaleSpire\Symbiotes\ looking for directories containing a manifest.json file. The manifest is then read, and the Symbiote is validated. The Symbiote is then available in the symbiotes panel. If the validation fails, then the entry in the panel will have a little warning marker indicating that fact. TaleSpire continues watching the Symbiotes directory for newly added or removed Symbiotes.
When a Symbiote starts, TaleSpire loads the entryPoint specified in the manifest. By default, any additional code injection (such as for the TaleSpire API) begins once the DOMContentLoaded event is emitted by the embedded browser, guaranteeing the
hasInitialized event triggers only once the entire DOM is available. If this is unimportant to you, you can override this by setting the
initializeEarly option to true in the manifest. Note that
initializeEarly doesn't guarantee the
hasInitialized event to trigger before DOMContentLoaded; it just makes it possible that it can happen depending on timing.
If your Symbiote is focused and the Symbiotes panel is closed, your Symbiote will be delivered an event via the
onVisibilityEvent event source.
If your Symbiote was focused, but then a different Symbiote becomes the focus, the behavior depends on the capabilities of your Symbiote. If the
runInBackground capability is specified, then the Symbiote will be informed that it
willEnterBackground, and the Symbiote will continue running. If the
runInBackground capability is not specified, then the Symbiote is shut down until it becomes focused again. We recommend not using the
runInBackground capability whenever possible, as it allows TaleSpire to free up resources for the player. Instead, we prefer saving to Symbiote storage after all notable data changes and reloading them on Symbiote startup.
Symbiotes survive board switches, but some API calls won't work during the switch. For example,
TS.players.getPlayersInThisBoard doesn't make sense if the Symbiote is not in a board. This should only take a short time but should be handled by the Symbiote by listening for client leave/join events for your own client and suppressing API calls.
If dev-mode is enabled, TaleSpire watches the symbiote directory for changes and will live-reload the Symbiote when modified. The folders are watched for file changes to see updates to files and detect new Symbiotes being added (or existing ones removed). Note the exceptions to file watching mentioned in Development Workflow.
On shutdown of a Symbiote, we attempt to deliver the
willShutdown event from the event source
onStateChangeEvent. This can give the Symbiote a short time to do any last-minute cleanup you want to do before the Symbiote is shut down. However, delivery of the shutdown event is made on a "best effort" and is not guaranteed. Therefore don't leave important tasks for this event. We reserve the right to shut down any Symbiote without event/warning for reasons such as performance or stability.
While all of the features of the API are documented above, there are some other miscellaneous extras we provide to make creating your own Symbiotes more convenient and make them look more at home in TaleSpire. They can be added by adding their respective name to the "extras" list in the manifest.
If the string
colorStyles is added to extras, TaleSpire injects a number of CSS variables defining the TaleSpire color scheme, which we highly recommend if you're trying to create a Symbiote that is supposed to fit in with the rest of the UI. This provides easy access to the exact colors TaleSpire's UI uses and they'll be updated with TaleSpire to keep your Symbiote fitting in at no extra work for you. This also allows users to change the UI theme to for example switch to a high contrast theme and have all the Symbiotes adapt to that.
The color descriptions provide info which colors should be used together - you can of course mix and match them in other ways, but please always check any combination with your favorite contrast checker tool. You should aim for a contrast of at least 4.5, though 7 or more is preferable as it helps with legibility, especially for visually impaired people. We don't always achieve this ourselves, but we'll try our best to improve on that front.
While you can use colors in "any way you want", do not completely misuse a color against its name or description, like using a background color in the foreground. Even if it might look fine now, if we update the color palette it may lead to bad looking or even unreadable Symbiotes. If there is a color missing for what you want to do it is better to create your own color than to "misuse" an existing theme color for something it is not intended for.
--ts-color-primary: The primary color for elements like text. Provides high contrast to
--ts-color-secondary: The secondary color for elements like text. Less contrast than the primary color and can be used for disabled elements or less prominent text like descriptions or captions.
--ts-background-primary: The primary color for the background. Provides high contrast to
--ts-background-secondary: The secondary color for the background. Can be used for example for cards that should be visually distinct from the normal background, for alternating color on long lists or tables or for low contrast borders. If visual distinction is essential to be able to use the UI comfortably, consider giving any elements that use this background color on top of
--ts-background-primarya border with color
--ts-accessibility-borderbecause the secondary and primary background colors don't provide good contrast with each other.
--ts-background-tertiary: The primary color for the background. Even less contrast with
--ts-color-primarythan the other two background colors. Used for similar cases as
--ts-background-secondary, as well as button backgrounds, but care should be put into contrast in conjunction with
--ts-color-secondary. For button backgrounds, see also
--ts-accessibility-border: Defines the border color for the high contrast theme for better accessibility. Is transparent (= invisible) in the default theme, but should be used on input elements to create a more accessible experience when needed. When a border is desired in the normal theme use other colors, but to not impede the usefulness of the high contrast theme, consider using one of the foreground colors as border for input elements to provide a high contrast and only using a background colors as border for non-interactive elements (eg: table borders).
--ts-accessibility-focus: Defines a focus color for the high contrast theme for better accessibility. This allows keyboard navigation in Symbiotes by providing a visible highlight around the currently focused element. Is transparent (= invisible) in the default theme, but should be set for all focusable elements (usually input elements). Focus should be set using the "outline" css property. See examples for guidance.
--ts-color-danger: An accent color for depicting something potentially dangerous like deleting/clearing data or similar.
--ts-accent-primary: The primary TaleSpire accent color. Can be used for background, text and accents like borders. Be mindful of using it (and the accompanying
--ts-accent-hover) as background color, because it doesn't provide great contrast with
--ts-accent-hover: An on hover color for
--ts-accent-primary. Used wherever there should be a highlight on mouse hover (or similar actions) and
--ts-accent-primaryis used. Similar considerations regarding contrast as with
--ts-accent-background: A variant of the accent color to serve better as a background. Can be used for example as background color for an element that already has the primary accent color as border. Provides more contrast to
--ts-color-primarywhen used in the background than
If the string
fonts is added to extras, TaleSpire injects the TaleSpire fonts to be used in CSS. Available fonts:
If the string
icons is added to extras, TaleSpire injects CSS classes for each UI icon and some control classes to adjust sizing and behavior.
An icon can be inserted by providing an icon element and adding the respective class for the icon you want:
Additionally, the sizing of the icon can be set to one of the following by inserting their respective classes:
ts-icon-medium: 32px - if no size is specified, it will default to this size
ts-icon-border. Keep in mind, that the icons are usually pure white, so without a border they will be invisible on a white background.
<i class="ts-icon-book ts-icon-small ts-icon-border"></i>
It's possible to invert the icon colors to have black icons (with white borders) by adding the
See here for a list of icons: Available Icons
If the string
diceFinder is added to extras, the dice finder functionality will be added to the Symbiote that's being loaded. The dice finder can identify whether text under the mouse cursor looks like a dice roll that TaleSpire can understand. This is meant to work robustly on as many websites as possible, but due to the vast amount of websites and different approaches it may not work on some. For it to work, it also needs to have the API injected.
We absolutely want to expand on the Symbiotes API! This is just the first step and we're hoping on vastly expanding the capabilities exposed to Symbiotes via the API
Not yet, but this is something we definitely want to tackle for future updates of the API. For now we opted to not include anything that edits "board state", that is Symbiotes can't do anything that gets saved to the board. We chose this to be able to get Symbiotes into your hands sooner as allowing persisting changes through the API needs careful consideration and planning to make it both safe and nice to use.
Some websites open popups/new tabs during login, especially when they're using third party authentication like logging in with your Google account. Having this in different tabs is necessary for the login flow to work, however the default behavior of Symbiotes loads all page navigations in the same tab (equivalent to changing the link target from
_self). If you are having issues with login you can set the
loadTargetBehavior field in the manifest to "popup" to allow links to be opened in popups instead of in the main tab.
Yes! You can either query
TS.players to see whether the player running the Symbiote has GM permission (
canGM is set to true), or
TS.clients to see if the game client is currently in GM view or player view (regardless of the permission the player has) and adapt the displayed UI accordingly.
There's two cases here:
As of right now it's version 111, but don't depend on this being stable and unchanging for certain behaviors in your Symbiotes as we will be updating this without prior notice for security and compatibility reasons.
There are no versions to upgrade to or from yet.