> For the complete documentation index, see [llms.txt](https://pbmodular-docs.gitbook.io/eng-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://pbmodular-docs.gitbook.io/eng-docs/quick-start/module-structure.md).

# Module structure

A module is a Python module (directory with `__init__.py` file) of a special structure.

```
core
├── extensions
│   ├── logs.py
│   ├── mod_manage.py
│   └── permissions.py
├── info.yaml
├── __init__.py
├── main.py
└── strings
    ├── en.yaml
    └── ru.yaml
```

*Structure example*

The heart of the module is the `BaseModule`super-class, which provides the necessary API for the module's operation, as well as performs its initialization. The module class must inherit from `BaseModule`

```
from base.module import BaseModule

class CoreModule(BaseModule):
```

In `__init__.py` there must be an import of a new module class, otherwise the loader just won't see it

```
from .main import CoreModule
```

All information about the module is described in the YAML file `info.yaml`. It includes: title, author, version, description, and permissions (more about them later). An example of such a file:

```
info:
  name: BestModule
  author: Developers
  version: 0.0.1
  description: Just best module, lol
  src_url: https://bestgit.org/BestModule

# Use raw loader object. Very dangerous permission!
permissions:
  - use_loader
```

Module commands are created as class methods, with the same arguments as a normal [handler in pyrogram](https://docs.pyrogram.org/start/updates), except that special decorators must be used (more details in the next section).&#x20;

`ModuleExtension` classes allow you to break module code into files without losing important class attributes. In the example above, the files with extensions are located in the `extensions` folder, although they can be located however you want, it's up to you.&#x20;

The module has a built-in translation system. When loading, the module checks the strings folder, and loads the translation files as dictionaries into the `rawS` attribute, then selects the currently active language (specified in the bot's config) and loads it into the `S` attribute. Example usage:

```
text = self.S["help"]["header"]
```
