Getting started
Requirements
Section titled âRequirementsâ- Node.js 22 or later
- pnpm 10 or later
- A text editor or IDE
- We suggest Visual Studio Code, but you can use whatever youâd like.
- Git
- If youâre new to using Git, you may want to use a GUI client. We suggest GitHub Desktop.
Suggested knowledge
Section titled âSuggested knowledgeâ- JavaScript/TypeScript
- We strongly recommend using TypeScript, but if youâre not comfortable with it, you can use JavaScript instead.
- React (if you plan to interact with the UI)
- You should be comfortable with the component model and how props work. Some old UI uses class components, but most use function components.
- If you plan to write your own components, you should know how to manage React state and JSX.
- Reading and writing regexes (if you plan to write patches)
- We suggest regex101 as a good resource for learning regex.
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
Section titled â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
- Context Menu ->
Now, run this command in your terminal and follow the instructions:
pnpm create @moonlight-mod/extensionAfter itâs done, open the newly created folder in your text editor or IDE, and update your extensionâs manifest.json:
- Change
nameto your user-facing extension name. - Change
taglineto 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
authorsto properly credit yourself. - Change
sourceto 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
Section titled â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.jsoncontains 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
webpackModulesfolder, 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
Section titled â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
Section titled â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?
Section titled âWhatâs next?âCongrats on making it this far! Thereâs a lot more to learn about how moonlight works:
- Set up DevTools to view the console and reverse engineer Discord.
- Read about Webpack modules, and learn how to write your own patches and make your own Webpack modules.
- Read the cookbook for common patterns you may want to use in your extension.
- Read common pitfalls so you know to avoid them.
- When your extension is ready, submit your extension to the official repository or distribute it on a custom repository.
If you need any help, donât be afraid to ask in our Discord server.
Making a second extension
Section titled â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
Section titled âUpdating your repositoryâYou should update the dependencies of your repository regularly. This command updates the types package:
pnpm update @moonlight-mod/typesYou 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.