MUD config
The mud.config.ts file is where a MUD project begins. It defines the resources (namespaces, tables, systems, and modules) used by your app and how MUD should codegen and deploy them. Its output is strongly typed for better type safety and developer experience in the form of hinting, inference, and autocomplete.
By default, the MUD config assumes your project is using only a single namespace. This is a great starting place for simple apps and worlds, where you're not yet thinking about extendability.
Once you're building a more complex app or on top of an existing world, you may want to take advantage of multiple namespaces. This enables more complex and composable behavior, including access control around data and functionality. Even MUD itself takes advantage of several namespaces for its core resources.
Single namespace
import { defineWorld } from "@latticexyz/world";
 
export default defineWorld({
  namespace: "mud",
  enums: {
    TerrainType: ["None", "TallGrass", "Boulder"],
  },
  tables: {
    Counter: {
      schema: {
        value: "uint32",
      },
      key: [],
    },
    Tasks: {
      schema: {
        id: "bytes32",
        createdAt: "uint256",
        completedAt: "uint256",
        description: "string",
      },
      key: ["id"],
    },
  },
  systems: {
    IncrementSystem: {
      name: "increment",
      openAccess: true,
    },
  },
  excludeSystems: ["System3", "System2"],
});Multiple namespaces
Starting with version 2.1 you can put multiple namespaces in the same config file, you create a namespaces record and within it a record for every namespace.
For example:
Sample mud.config.ts files
A namespace
This is an extremely simple configuration file with a single namespace that contains a single table.
The systems are defined implicitly, as all the contracts under src/namespaces/app that match *System.sol.
import { defineWorld } from "@latticexyz/world";
 
export default defineWorld({
  namespaces: {
    app: {
      tables: {
        Tasks: {
          schema: {
            id: "bytes32",
            createdAt: "uint256",
            completedAt: "uint256",
            description: "string",
          },
          key: ["id"],
        },
      },
    },
  },
});Source files
- src/namespaces/app/systems- systems that belong to the- appnamespace.
Note that this is a convention, any *System.sol under src/namespaces/<namespace> is interpreted as a system in that namespace.
Generated files
- src/namespaces/app/codegen/tables/Tasks.sol- the generated code for- app__Taskstable.
- src/namespaces/app/codegen/index.sol- a single file that imports all the table definitions of the namespace (in this case, only- Tasks.sol).
- src/codegen/world/I*System.sol- interfaces for all the systems.
- src/codegen/world/IWorld.sol- the- IWorldinterface that inherits from all the- I*System.solfiles.
A namespace with an explicit system definition
By default Systems are publicly accessible.
In this configuration, we explicitly specify TestSystem so we can specify that access to it is limited to authorized addresses.
import { defineWorld } from "@latticexyz/world";
 
export default defineWorld({
  namespaces: {
    app: {
      tables: {
        Tasks: {
          schema: {
            id: "bytes32",
            createdAt: "uint256",
            completedAt: "uint256",
            description: "string",
          },
          key: ["id"],
        },
      },
      systems: {
        TestSystem: {
          openAccess: false,
        },
      },
    },
  },
});Source files
- src/namespaces/app/systems/RootSystem.sol- The system specified in- mud.config.ts.
- src/namespaces/app/systems- systems that belong to the- appnamespace.
Note that this is a convention, any *System.sol under src/namespaces/<namespace> is interpreted as a system in that namespace.
Generated files
- src/namespaces/app/codegen/tables/Tasks.sol- the generated code for- app__Tasks.
- src/namespaces/app/codegen/index.sol- a single file that imports all the table definitions (in this case, only- Tasks.sol).
- src/codegen/world/I*System.sol- interfaces for all the systems, including- IRootSystem.sol
- src/codegen/world/IWorld.sol- the- IWorldinterface that inherits from all the- I*System.solfiles.
Two namespaces
In this example there are two namespaces, app and config.
Each namespace contains a single table: app__Tasks and config__Configuration.
import { defineWorld } from "@latticexyz/world";
 
export default defineWorld({
  namespaces: {
    app: {
      tables: {
        Tasks: {
          schema: {
            id: "bytes32",
            createdAt: "uint256",
            completedAt: "uint256",
            description: "string",
          },
          key: ["id"],
        },
      },
    },
    config: {
      tables: {
        Configuration: {
          schema: {
            deployer: "address",
            tokenAddress: "address",
            ipAddress: "bytes4",
            url: "string",
          },
          key: [],
        },
      },
    },
  },
});Source files
- src/namespaces/app/systems- systems that belong to the- appnamespace.
- src/namespaces/config/systems- systems that belong to the- confignamespace.
Note that this is a convention, any *System.sol under src/namespaces/<namespace> is interpreted as a system in that namespace.
Generated files
- src/namespaces/app/codegen/tables/Tasks.sol- the generated code for- app__Taskstable.
- src/namespaces/app/codegen/index.sol- a single file that imports all the table definitions of the namespace (in this case, only- Tasks.sol).
- src/namespaces/config/systems- systems that belong to the- confignamespace.
- src/namespaces/config/codegen/tables/Tasks.sol- the generated code for- config__Configurationtable.
- src/namespaces/config/codegen/index.sol- a single file that imports all the table definitions of the namespace (in this case, only- Configuration.sol).
- src/codegen/world/I*System.sol- interfaces for all the systems.
- src/codegen/world/IWorld.sol- the- IWorldinterface that inherits from all the- I*System.solfiles.
Enumerations
import { defineWorld } from "@latticexyz/world";
 
export default defineWorld({
  enums: {
    Direction: ["Up", "Down", "Left", "Right"],
    MapDirection: ["North", "East", "South", "West"],
  },
  namespaces: {
    app: {
      tables: {
        Heading: {
          schema: {
            id: "bytes32",
            direction: "Direction",
            name: "string",
          },
          key: ["id"],
        },
        MapCursor: {
          schema: {
            id: "bytes32",
            direction: "MapDirection",
            name: "string",
          },
          key: ["id"],
        },
      },
    },
  },
});Source files
- src/namespaces/app/systems- systems that belong to the- appnamespace.
Note that this is a convention, any *System.sol under src/namespaces/<namespace> is interpreted as a system in that namespace.
Generated files
- src/namespaces/app/codegen/tables/Heading.sol- the generated code for- app__Headingtable.
- src/namespaces/app/codegen/tables/MapCursor.sol- the generated code for- app__MapCursortable.
- src/namespaces/app/codegen/index.sol- a single file that imports all the table definitions of the namespace (in this case,- Heading.soland- MapCursor.sol).
- src/codegn/common.sol- the enumerations in the config file.
- src/codegen/world/I*.sol- interfaces for all the systems.
- src/codegen/world/IWorld.sol- the- IWorldinterface that inherits from all the- I*System.solfiles.