Zero to Mojolicious: Building a Site with Zurb Foundation

Tags:

Combining several of my previous posts, let's build a quick site with Mojolicious and Zurb Foundation. We will use the AssetPack plugin. Although we are serving fairly simple Javascript and CSS files now, later we can switch to using Coffeescript, Less or Sass or anything which AssetPack can pre-process.

First, install the AssetPack plugin and create a fresh "app" −

$ cpanm Mojolicious::Plugin::AssetPack
$ mojo generate app FoundationExample

Method 1 − Local copy of Foundation

Download the latest Foundation and put the files under a foundation/ directory under our "app" directory:

$ mkdir foundation
$ cd foundation
$  wget http://foundation.zurb.com/cdn/releases/foundation-5.5.2.zip
$ unzip foundation-5.5.2.zip

Now let's create a set of relative symbolic links for each file in the Foundation directory:

$ mkdir  public/foundation/
$ ln -s -r foundation/* public/foundation/

In lib/FoundationExample.pm, change the startup to −

# This method will run once at server start
sub startup {
  my $self = shift;

  $self->plugin("AssetPack");

  my $source = "/foundation/";
  $self->asset("foundation.css" => $source."css/foundation.min.css");
  $self->asset("foundation.js" => $source."js/foundation.js");
  $self->asset("modernizr.js" => $source."js/vendor/modernizr.js");
  $self->asset("jquery.js" => $source."js/vendor/jquery.js");

  # Router
  my $r = $self->routes;

  # Normal route to controller
  $r->get('/')->to('example#welcome');
}

Continue with Both Methods, below.

Method 2 − CDN method

Use only the changes in lib/FoundationExample.pm shown above, but replace the source with −

  my $source = "https://cdnjs.cloudflare.com/ajax/libs/" .
    "foundation/5.5.2/";

Continue with Both Methods, below.

Both Methods.

In lib/FoundationExample/Controller/Example.pm − change the welcome routine to:

sub welcome {
  my $self = shift;

  $self->stash(copyright_holder => 'Someone');
  $self->stash(keywords => 'something, somebody, somewhere');
  $self->stash(author => 'William Lindley');

  # Render template "example/welcome.html.ep" with message
  $self->render(msg => 'Welcome to the Mojolicious real-time web framework!');
}

In templates/example/welcome.html.ep − change the layout to:

% layout 'zurbish';

and templates/layouts/zurbish.html.ep −

<!DOCTYPE html>
<html lang="en">
 <head>
 <meta charset="utf-8">
 <!-- Zurb Foundation stuff -->
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
%= asset 'foundation.css'
%= asset 'modernizr.js'
 <!-- end Zurb -->
 <title><%= title %></title>
 <meta name="copyright" content="Copyright ⓒ <%= ((localtime())[5]+1900) %> <%= $copyright_holder %>" />
 <meta name="keywords" content="<%= $keywords %>" />
 <meta name="author" content="<%= $author %>" />
 </head>
 <body>
%= asset 'jquery.js'
%= asset 'foundation.js'
 <script>
 $(document).foundation();
 </script>
<%= content %>
 </body>
</html>

For more, see Jan Henning Thorsen's talk on Mojolicious::Plugin::AssetPack at MojoConf 2014.

Toadfarm on Base Debian: An absolutely minimal multi-tenant webserver

Tags:

Here we create an absolutely minimal multi-tenant webserver, without even installing Apache or NginX. Although we can add either of those later, with our content running under them as reverse proxies, this tutorial lets you run one or more Mojolicious "apps" mounted under a single toadfarm startup script, saving you the "default perl memory" times the number of worker processes and apps.

We will b using Jan Henning Thorsen's Toadfarm:

Toadfarm is a module for configuring and starting your Mojolicious applications. You can either combine multiple applications in one script, or just use it as a init script.


First, perform a Debian Netinstall on a virtual machine or virtual host. The only modification to all the default selections is to enable only "Standard System Utilities" and disable desktop, database, mail, print, file, and web server. We will be building our own of all those!

Now boot up into that absolutely stock, base machine. For illustration, we will assume your username is gronk − change this as necessary. First let's install a few system packages (ssh for access; curl for installing Perlbrew et al; sudo for convenience; build-essential for GCC, Make, and the compiler tools; and the no-X version of emacs because I've been using it since 1980):

$ su
# apt-get install sudo ssh curl build-essential emacs-nox
# usermod -a -G sudo <em>gronk</em> # exit

Now we install our Perlbrew environment as the user:

$ \curl -L http://install.perlbrew.pl | bash
$ echo source ~/perl5/perlbrew/etc/bashrc >> ~/.bash_profile
$ perlbrew install 5.22.0 -j5

The -j5 means use five processes for the Make. Then:

$ perlbrew switch 5.22.0
$ perlbrew install-cpanm
$ curl -L https://cpanmin.us |     perl - -M https://cpan.metacpan.org -n Mojolicious
$ cpanm Toadfarm

jhthorsen explains how this goes together:

You can't run individual apps inside toadfarm as different user, but you can start toadfarm as root and change to a different user.

[

This is true of Mojolicious generally ](https://metacpan.org/pod/Mojo::Server#user) .

In particular, we create an Init script with a #! (hashbang) that points to our user's "brewed" Perl. From the documentation:

Remember that the hashbang can be anything, so if you have Toadfarm and Mojolicious running under

[

plenv ](https://github.com/tokuhirom/plenv) or Perlbrew you need to change the hashbang part…

So we change our Init script to start with:

#!/home/<em>gronk</em>/perl5/perlbrew/perls/perl-5.22.0/bin/perl

Then in the Toadfarm script called by the Init script, which is started as root, we do the switch to our user (called some-www-user in the documentation, gronk here):

#/usr/bin/env perl
use Toadfarm -init;
# …
start [qw( http://*:80 https://*:443 )], user => "<em>gronk</em>", group => "<em>www</em>";

From the documentation:

Changing user has one implication: The workers will not use some-www-user's secondary groups. So if "some-www-user" is part of the "www" and "db" groups, then the process will only be run as "some-www-user" part of the "www" group.

See also the IRC log for 26 April 2014.