The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


Mojolicious::Plugin::InstallablePaths - Easy installation configuration for Mojolicious apps


 package MyApp;
 use Mojo::Base 'Mojolicious';

 sub startup {
   my $app = shift;
   $app->plugin( 'InstallablePaths' );

then if using Module::Build

 # Build.PL
 use Module::Build::Mojolicious clean_install => 1;
 my $builder = Module::Build::Mojolicious->new(
   configure_requires => {
     'Module::Build::Mojolicious' => 0,
     'Module::Build' => 0.38,


Mojolicious applications work nicely from a working directory, but once the app is bundled for installation some of the configuration gets a little bit tricky. Though some examples are shown in the Mojolicious documentation, the process is still rather involved. However, Mojolicious::Plugin::InstallablePaths handles all the configuration for you (provided you follow a proscribed directory tree)!


 myapp                              # Application directory
 |- bin                             # Script directory
 |  +- myapp                        # Application script
 |- lib                             # Library directory
 |  |-                     # Application class
 |  +- MyApp                        # Application namespace
 |     |-                # Controller class
 |     +- files                     # Shared directory for all non-module content
 |        |- public                 # Static file directory (served automatically)
 |        |  +- index.html          # Static HTML file
 |        +- templates              # Template directory
 |           |- layouts             # Template directory for layouts
 |           |  +- default.html.ep  # Layout template
 |           +- example             # Template directory for "Example" controller
 |              +- welcome.html.ep  # Template for "welcome" action
 |- t                               # Test directory
 |  +- basic.t                      # Random test
 +- Build.PL                        # Build file uses Module::Build::Mojolicious

As you can see, all non-module content is placed inside a directory named files directly inside the folder named for the module. In the above example this is the lib/MyApp/files/ directory. If the app had been Some::App then the directory would be lib/Some/App/files/.

There is no allowance for different names of these folders nor of different locations for them relative to the main module. Patches will be considered, but the primary purpose of this module is the simple generic case; to do strange things the Mojolicious path manipulation system should be used directly.


The magic happens when your app loads the InstallablePaths plugin.


Before this call, the directories are not set correctly, so be sure to use it early! The plugin will detect if the directory tree exists as above (i.e. before installation) and use it directly or else it will attempt to use the File::ShareDir system to locate the directories (i.e. after installation). In this way, your app should always find its needed files, no matter what phase of development or installation!


When using ExtUtils::MakeMaker the files are installed directly and the plugin finds them from the main tree. Just install as usual.


If Module::Build is more your flavor (it is mine), included with Mojolicious::Plugin::InstallablePaths is a subclass of Module::Build named Module::Build::Mojolicious (of course). The purpose of this subclass is to add the necessary directory to the list of shared folders using the File::ShareDir integration. This is done completely behind the scenes, provided the directory exists. Simply change the name of your build module and use as normal:

 use Module::Build::Mojolicious clean_install => 1;
 my $builder = Module::Build::Mojolicious->new(
   configure_requires => {
     'Module::Build::Mojolicious' => 0,
     'Module::Build' => 0.38,

Later, this directory can be found using the usual mechanisms that that File::ShareDir provides. Keep in mind that you should add it to the configure_requires key as you should for any module used in a Build.PL file.

Finally note that if passing clean_install => 1 at import, Module::Build::CleanInstall will be inserted into the inheritance tree at import time. This module ensures that old files are removed before upgrading an already installed module. The author recommends this option be enabled.




Joel Berger, <>


Copyright (C) 2012 by Joel Berger

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.