Skip to main content

Getting Started

Creating a Friday Night Funkin’ mod is straightforward. At its core, a mod is just a folder with a metadata file and whatever assets or scripts you want to add.
This guide covers basic mod creation. For advanced scripting, see the Scripting Guide.

Mod Structure

Every mod follows this basic structure:
yourmod/
├── _polymod_meta.json    # Required: Mod metadata
├── _polymod_icon.png     # Optional: Icon shown in mod menu
├── data/                 # JSON data files
├── images/               # Image assets (.png)
├── music/                # Music files (.ogg)
├── sounds/               # Sound effects (.ogg)
├── songs/                # Song charts and metadata
├── scripts/              # HScript files (.hscript, .hxc)
└── _append/              # Special folder for merging files
Your mod only needs to include files you want to change. Missing files fall back to the base game.

Step 1: Create Mod Metadata

Every mod requires a _polymod_meta.json file. This tells Polymod about your mod:
1

Create the mod folder

Create a new folder in the game’s mods directory:
mods/
  └── myawesomemod/
2

Create _polymod_meta.json

Inside your mod folder, create _polymod_meta.json with this template:
_polymod_meta.json
{
  "title": "My Awesome Mod",
  "description": "A cool mod that does cool things",
  "contributors": [
    {
      "name": "YourName"
    }
  ],
  "api_version": "0.8.0",
  "mod_version": "1.0.0",
  "license": "Apache-2.0"
}
3

Customize the fields

Required fields:
  • title - Display name of your mod
  • description - What your mod does
  • api_version - Game version compatibility (use "0.8.0" for current)
  • mod_version - Your mod’s version
  • license - License for your mod
Optional fields:
  • contributors - Array of contributor objects with name field
  • homepage - URL to mod page/repository

Example Metadata

Here’s the metadata from the included example mod:
{
  "title": "Intro Mod",
  "description": "An introductory mod.",
  "contributors": [
    {
      "name": "EliteMasterEric"
    }
  ],
  "api_version": "0.8.0",
  "mod_version": "1.0.0",
  "license": "Apache-2.0"
}

Step 2: Add a Mod Icon (Optional)

Create a _polymod_icon.png file to give your mod a custom icon:
  • Size: 256x256 pixels recommended
  • Format: PNG with transparency
  • Location: Root of your mod folder
myawesomemod/
├── _polymod_meta.json
└── _polymod_icon.png  ← 256x256 PNG

Step 3: Replace Assets

The simplest way to mod FNF is by replacing assets. Just match the game’s file structure:

Replacing Images

To replace an image, create the same path in your mod:
images/
  └── newgrounds_logo.png
When the game loads images/newgrounds_logo.png, it will use your version instead!
The testing123 example mod replaces the Newgrounds logo. Check example_mods/testing123/images/ to see it in action.

Replacing Data Files

Same principle for JSON data:
myawesomemod/
  └── data/
      └── characters/
          └── bf.json  ← Modified Boyfriend data

Replacing Audio

Replace music or sound effects:
myawesomemod/
  ├── music/
  │   └── freakyMenu.ogg  ← New menu music
  └── sounds/
      └── confirmMenu.ogg  ← New confirm sound
Audio files should be in OGG Vorbis format for best compatibility.

Step 4: Merge Text Files

Instead of replacing files, you can append to them using the special _append folder:
The _append folder tells Polymod to add your content to the end of existing files instead of replacing them.

Supported Merge Formats

Polymod supports merging for these file types:
  • TXT files - Line-by-line merging
  • JSON files - Deep object merging
  • CSV files - Row appending
  • XML files - Node merging
static function buildParseRules():polymod.format.ParseRules
{
  var output:polymod.format.ParseRules = polymod.format.ParseRules.getDefault();
  // Ensure TXT files have merge support.
  output.addType('txt', TextFileFormat.LINES);
  // Ensure script files have merge support.
  output.addType('hscript', TextFileFormat.PLAINTEXT);
  output.addType('hxs', TextFileFormat.PLAINTEXT);
  output.addType('hxc', TextFileFormat.PLAINTEXT);
  output.addType('hx', TextFileFormat.PLAINTEXT);
  
  return output;
}

Step 5: Add Scripts (Optional)

For custom behavior, add HScript files. Scripts go in the root or in a scripts folder:
myawesomemod/
  ├── _polymod_meta.json
  └── scripts/
      ├── MyModule.hxc
      └── CustomSprite.hxc

Learn Scripting

See the full Scripting Guide for details on writing scripts.

Complete Example Mod

Here’s what a complete simple mod looks like:
coolskinmod/
├── _polymod_meta.json
├── _polymod_icon.png
├── images/
│   └── characters/
│       ├── bf.png        # New Boyfriend sprite
│       └── bf.xml        # Sprite animation data
├── data/
│   └── characters/
│       └── bf.json       # Modified Boyfriend stats
└── sounds/
    └── intro3.ogg        # Custom "Go!" sound
_polymod_meta.json:
{
  "title": "Cool Skin Mod",
  "description": "Gives Boyfriend a cool new look!",
  "contributors": [{"name": "ModderName"}],
  "api_version": "0.8.0",
  "mod_version": "1.0.0",
  "license": "CC-BY-4.0"
}

Testing Your Mod

1

Place in mods folder

Ensure your mod folder is in the correct location:
mods/
  └── coolskinmod/  ← Your mod here
2

Start the game

Launch Friday Night Funkin’. The game will automatically detect and load your mod.
3

Check console logs

Look for messages like:
Mod loading complete. We loaded 1 / 1 mods.
 * Cool Skin Mod v1.0.0 [coolskinmod]
4

Verify changes

Play the game and check that your assets appear correctly.

Hot Reloading (Development)

During development, you can reload mods without restarting:
This is a development feature and requires the game to be compiled with debug features enabled.
PolymodHandler.hx
/**
 * Clear and reload from disk all data assets.
 * Useful for "hot reloading" for fast iteration!
 */
public static function forceReloadAssets():Void
{
  // Forcibly clear scripts so that scripts can be edited.
  ModuleHandler.clearModuleCache();
  Polymod.clearScripts();
  
  // Forcibly reload Polymod so it finds any new files.
  funkin.modding.PolymodHandler.loadAllMods();
  
  // Reload all registries...
}

Best Practices

  • Keep your folder structure clean and organized
  • Use descriptive names for custom assets
  • Document your changes in a README.md
  • Include credits for any borrowed assets
  • Test your mod with a clean game installation
  • Check that API version matches current game version
  • Avoid replacing files unless necessary (use append when possible)
  • Test with other popular mods to check for conflicts
  • Optimize image file sizes (use PNG compression)
  • Keep audio files compressed (OGG with reasonable bitrate)
  • Avoid excessive script calls in update loops
  • Profile your scripts if you notice lag
  • Package as a ZIP with your mod folder at the root
  • Include installation instructions
  • List compatible game versions
  • Provide example screenshots
  • Link to your homepage or source repository

Common File Paths

Here are some commonly modded paths:
images/characters/
  ├── bf.png          # Boyfriend sprites
  ├── gf.png          # Girlfriend sprites
  └── dad.png         # Daddy Dearest sprites

data/characters/
  ├── bf.json         # Boyfriend data
  ├── gf.json         # Girlfriend data
  └── dad.json        # Daddy Dearest data

Next Steps

Scripting Guide

Learn to write custom scripts with HScript

Polymod Deep Dive

Advanced modding techniques and asset merging

Build docs developers (and LLMs) love