# HowTo: Write Lua based Modules (deprecated for client side modules) See [online wiki](https://github.com/openwrt/luci/wiki/ModulesHowTo) for latest version. **Note:** If you plan to integrate your module into LuCI, you should read the [Module Reference](./Modules.md) in advance. This tutorial describes how to write your own modules for the LuCI WebUI. For this tutorial we refer to your LuCI installation directory as `lucidir` (`/usr/lib/lua/luci` on your OpenWRT device) and assume your LuCI installation is reachable through your webserver via `http://192.168.1.1/cgi-bin/luci`. The recommended way to set up a development environment: - Install OpenWRT on your router/device (You could use a QEMU or VirtualBox image instead) - Install SSHFS on your host - Mount your routers' root (`/`) someplace on your development host (eg. `/mnt/router`) - Then open `/mnt/router/(lucidir)` in your favorite development studio Extra: - Add configurations to your dev studio which will delete the luci cache (detailed below) and then open a browser window to your routers' configuration page in order to see your module/application. When testing, if you have edited index files, be sure to remove the folder `/tmp/luci-modulecache/*` and the file(s) `/tmp/luci-indexcache*`, then refresh the LUCI page to see your edits. ## The dispatching process LuCI uses a dispatching tree that is built by executing the index-Function of every available controller. The CGI-environment variable `PATH_INFO` will be used as the path in this dispatching tree, e.g.: `/cgi-bin/luci/foo/bar/baz` resolves to `foo.bar.baz`. To register a function in the dispatching tree, use the `entry`-function of `luci.dispatcher`. It takes 4 arguments (2 are optional): ```lua entry(path, target, title=nil, order=nil) ``` * `path` is a table that describes the position in the dispatching tree: For example a path of `{"foo", "bar", "baz"}` would insert your node in `foo.bar.baz`. * `target` describes the action that will be taken when a user requests the node. There are several predefined actions, of which the 3 most important (call, template, cbi) are described later on this page * `title` defines the title that will be visible to the user in the menu (optional) * `order` is a number with which nodes on the same level will be sorted in the menu (optional) You can assign more attributes by manipulating the node table returned by the entry-function. A few example attributes: * `i18n` defines which translation file should be automatically loaded when the page gets requested * `dependent` protects plugins to be called out of their context if a parent node is missing * `leaf` stops parsing the request at this node and goes no further in the dispatching tree * `sysauth` requires the user to authenticate with a given system user account # Naming and the module file Now we can start writing modules. Choose the category and name of your new digital child. Let's assume you want to create a new application `myapp` with a module `mymodule`. So you have to create a new sub-directory `lucidir/controller/myapp` with a file `mymodule.lua` with the following content: ```lua module("luci.controller.myapp.mymodule", package.seeall) function index() end ``` The first line is required for Lua to correctly identify the module and create its scope. The `index`-Function will be used to register actions in the dispatching tree. ## Teaching your new child (Actions) So it has a name, but no actions. We assume you want to reuse your module myapp.mymodule that you began in the last step. ### Actions Reopen `lucidir/controller/myapp/mymodule.lua` and just add a function to it with: ```lua module("luci.controller.myapp.mymodule", package.seeall) function index() entry({"click", "here", "now"}, call("action_tryme"), "Click here", 10).dependent=false end function action_tryme() luci.http.prepare_content("text/plain") luci.http.write("Haha, rebooting now...") luci.sys.reboot() end ``` And now visit the path `/cgi-bin/luci/click/here/now` (`http://192.168.1.1/luci/click/here/now` if you are using the development environment) in your browser. These action functions simply have to be added to a dispatching entry. As you may or may not know: CGI specification requires you to send a `Content-Type` header before you can send your content. You will find several shortcuts (like the one used above) as well as redirecting functions in the module `luci.http` ### Views If you only want to show the user text or some interesting family photos, it may be enough to use an HTML-template. These templates can also include some Lua code but be aware that writing whole office-suites by only using these templates might be considered "dirty" by other developers. Now let's create a little template `lucidir/view/myapp-mymodule/helloworld.htm` with the content: ```html <%+header%>