Skip to content

Getting started

Requirements

  • Node.js 22 or later
  • pnpm 10 or later
  • A text editor or IDE
  • Git
    • If you’re new to using Git, you may want to use a GUI client. We suggest GitHub Desktop.

Suggested knowledge

You don’t need to be an expert (or have worked) in the above subjects, but it makes creating extensions much easier. We believe in learning by doing, so don’t be afraid to ask for help in our Discord server or reference other extensions.

moonlight has a lot of libraries and modules for common utilities, but sometimes you’ll need to do something that hasn’t been discovered before, and you’ll need to reverse engineer Discord yourself. Understanding Discord’s code can be tough for beginners, so we encourage you to ask for help if you’re stuck. A creative mindset and thinking outside the box goes a long way, though!

Reading how other extensions work can be a huge resource, so we encourage you to reference the moonlight core extensions and the extensions on the official repository. Just remember to respect the licensing of the extension!

Create your extension

Before you create your extension, you’ll need to decide on a few things first:

  • Pick a user-facing name for your extension. This will be displayed to the user in Moonbase. We suggest a short but informational one.
    • Gimmick names are fun to use, but they can confuse users. If your extension’s name doesn’t describe its functionality well, make sure you clarify what your extension does in the tagline.
    • Treat it as a proper noun (“Native Fixes” instead of “Native fixes”).
  • Pick an ID for your extension. This is used internally by moonlight. We suggest picking the name of your extension in camelCase:
    • Context Menu -> contextMenu
    • Moonbase -> moonbase
    • No Hide Token -> noHideToken

Now, run this command in your terminal and follow the instructions:

Terminal window
pnpm create @moonlight-mod/extension

After it’s done, open the newly created folder in your text editor or IDE, and update your extension’s manifest.json:

  • Change name to your user-facing extension name.
  • Change tagline to a short explanation of your extension.
  • Change (or delete) description. If you have any important notes about the extension’s functionality, you should add them here. This field is optional.
  • Change authors to properly credit yourself.
  • Change source to the URL of your Git repository.

Now is a good time to take a look around the rest of the files - most of them are commented.

Build and run your extension

If you haven’t already, run pnpm install to install all dependencies. Run pnpm run build to build the extension. Next to the src folder, a dist folder will appear, which contains the built extension inside of it.

Add the dist folder to the “Extension search paths” setting in Moonbase (or set devSearchPaths in your moonlight config). After restarting your client, your extension will appear in Moonbase, and you can enable it to start using your extension.

Right now, your extension doesn’t do much. Let’s go over what each file does:

  • manifest.json contains all of the metadata about your extension. Every extension has a manifest.
  • In index.ts, your extension exports its patches and Webpack modules. Make sure to export every patch and Webpack module you create, or else moonlight won’t load them.
  • If you open the Discord settings menu, you should see the “User Settings” section has been renamed to “hacked by (your extension ID) lol”. This was edited by the patch in index.ts, which modifies Discord to insert and replace custom code.
  • In the webpackModules folder, there are multiple Webpack modules, which is where most of your extension’s code lives. Right now, all they do is log to the console.
  • In node.ts, your extension runs in the Node environment, where you can access the filesystem or spawn extra processes. Most extensions don’t need to use this, though.
  • In env.d.ts (at the root of the repository), your extension’s Webpack module is declared to let you import it directly. Make sure to update this file when you add or remove Webpack modules, but don’t delete it entirely.

We suggest keeping these examples around for experimentation, but you should delete what you aren’t using before you publish your extension. Most extensions don’t use node.ts, for example.

Edit and reload your extension

Run pnpm run dev to enter watch mode. When you make changes to your extension, the extension will automatically be rebuilt, and you can reload your client (Ctrl+R) to load the new version of your extension.

Try changing one of the logger messages, or maybe edit the example patch. Play around a bit and see what happens!

Publish your extension

Once you’re ready to share your code with the world, create a new GitHub repository.

In the repository settings, make sure GitHub Actions is enabled for your repository, and that the GitHub Pages source is set to GitHub Actions:

  • GitHub Actions: “Code and automation” > “Actions” > “General” > “Actions permissions”
  • GitHub Pages: “Code and automation” > “Pages” > “Build and deployment” > “Source”

Now that your repository is set up, commit your extension to your new repository. Every time a commit is made to the main branch, your extension will be built with GitHub Actions, and published on GitHub Pages at https://<username>.github.io/<repository>/repo.json.

You can start using this repository URL right away, but we suggest ignoring it for now and submitting to the official repository. If you don’t want this to be automatically published, you can also delete the .github/workflows/deploy.yml file and turn off GitHub Pages.

What’s next?

Congrats on making it this far! There’s a lot more to learn about how moonlight works:

If you need any help, don’t be afraid to ask in our Discord server.

Making a second extension

If you’ve decided to make a second extension, you don’t need to make a separate repository for it. Simply run the pnpm create command again, but this time inside of the existing repository. It’ll automatically detect the existing repository and create a new extension for you.

Updating your repository

You should update the dependencies of your repository regularly. This command updates the types package:

Terminal window
pnpm update @moonlight-mod/types

You might need to update other packages (like @moonlight-mod/esbuild-config) to stay up to date. In some scenarios, manually updating or replacing files may be required, so check our communication channels if there is any manual updates required.

When updating your extension to a new API level, follow the instructions here.