Creating Plugins for Sextant

  • sextant
  • discord
  • mods
Sat May 17 2025
Author: Neo Sahadeo

What is Sextant

Sextant is my Discord Electron Wrapper around Discord Web to provide a more optimised, privacy focused, and enhanced streaming to the base Discord experience.

I have every intention of writing a documentation resource; but for the time-being, this will work for now!

Understanding the Folder Structure

This is a representation as of 17/05/2025. There will be new files and content but the structure should not change.

src
├── components
│   ├── settingsTab.html
│   └── settingsTab.ts
├── electrons
│   ├── externalConfig.ts
│   └── tray_icon.ts
├── patches
│   ├── blockDomain.ts
│   ├── disableCSP.ts
│   ├── onBeforeRequest.ts
│   ├── requestLimit.ts
│   └── stream.ts
├── plugins
│   ├── betterStream.ts
│   ├── dispatcher.ts
│   ├── dynamicStyles.ts
│   ├── fileLoader.ts
│   ├── reduceDOMSize.ts
│   ├── settingsTab.ts
│   └── stopPropagation.ts
├── global.d.ts
├── main.ts
├── pluginManager.ts
├── preload.js
└── utils.ts
static
└── styles
    ├── config.toml
    ├── settings.toml
    ├── sextant.png
    └── tray_icon.png

Right, the folders you should be interested in is, components and plugins. Generally patches are very limited in extension functionality - hence the word patch - and you will most likely not really want to right a patch.

Components

The components folder is where all your HTML and JS(TS) will go. These must be DOM specific and cannot contain any code that would not normally run in the DOM.

The code is injected at runtime into Discord and will not run if there are errors in the script file; it will just silently fail

Writing Plugins

To write a plugin is really quite simple, follow this template

export const [PLUGIN_HANDLER_EXPORT] = (s: any) => {
   // Register IPC Content here
};

export const [PLUGIN_EXPORT_NAME]: SextantPlugin = {
    name: "[NAME_OF_PLUGIN]",
    load() {
        return () => {
           // Your Plugin Code goes here
        }
    }
    unload() {
        return () => {
           // Your Plugin Clean up goes here
        }
    }
}

All the code in the return functions will be injected into the DOM at runtime, the return code MUST be DOM specific.

IPC events should be registered in the preload.js, currently I have no plans to automate it unless there are many events I would like to register.

Be sure to clean up code that was previously injected! If not, the code blocks will be duplicated and it can lead to performance issues and undesired behaviors

Registering Plugins and IPC Handlers

To register the plugin, import the plugin into the main.ts file, then add the plugin into the plugins list

const plugins = [
    dispatcher, // We them events
    file_loader, // Load asap
    settings_tab, // Load asap2
    dynamic_styles,
    better_stream,
    reduce_dom_size,
    // your plugin goes here
];

For the IPC Handler, there is a plugins_handler list

const plugin_handlers = [
    file_loader_handler,
    dynamic_styles_handler,
    settings_tab_handler,
    // your plugin handler (IPC) goes here
];

If you would like the ability to disable and enable the plugin at runtime, or let the user be able to choose to toggle it off / on, add the name of the function to the static/config.toml file under plugins.

[Plugins]
# Disabling these will break functionality
DynamicStyles = true
Dispatcher = true
FileLoader = true
BetterStream = true
SettingsTab = true
##########################################

# You can add you plugins here
# This can be configured as u wish!
ReduceDOMSize = true
StopPropagation = true
###################################

Stream Data to the Components

  • window.sextant_events.[METHOD]

Something you might want to do is have your plugin data be available to the components you inject. Sextant provides a event structure similar to normal Javascript. The event listener code is in the utils.ts file. Methods exposed: addEventListener dispatchEvent removeEventListener

For example, in the BetterStream plugin, we stream data to the components using the dispatch event handler.

window.sextant_events.dispatchEvent("bitrate", bitrate);

and in the component script we can listen for “bitrate” events.

window.sextant_events.addEventListener("bitrate", (bitrate: number) => {
})

As a rule of thumb, make the event dispatch in the form of USERNAME_EVENT to avoid naming conflicts and false event positives.