A static site generator, build for speed and flexibility.
$ mix new myProject
mix.exs
See Mix configuration .
$ mix deps.get
lib/{{project name}}.ex
See Configuration .
$ mix fermo.build
Have pages reloaded when structure, style or content change.
$ FERMO_LIVE=true mix fermo.live
The live site is available at http://localhost:4001/
When pages are requested, the server injects a JS that starts a socket, on the Elixir side, the socket registers the path that the browser is visiting.
When changes happen to pages that are being visited, the browser is told to reload the page via the websocket.
+-- build - The built site
+-- lib
| +-- my_project.ex - See [Configuration](#configuration)
| +-- helpers.ex
+-- mix.exs - See [Mix configuration](#mix-configuration)
+-- priv
+-- locales - See [Localization](#localization)
| +-- en.yml
| +-- ...
+-- source
+-- javascripts
+-- layouts
+-- localizable
+-- templates
+-- partials
+-- static
+-- stylesheets
+-- templates
defmodule
MyProject
.
MixProject
do
use
Mix
.
Project
def
project
do
[
..
.
compilers:
Mix
.
compilers
()
++
[
:fermo
],
..
.
deps:
deps
()
]
end
defp
deps
do
[
{
:fermo
,
"
~> 0.5.1
"
}
]
end
end
Create a module (under lib) with a name matching your MixProject module defined in
[mix.exs](#mix-configuration)
.
This module must implement
build/0
, a function that returns an updated
[config](#config-object)
.
defmodule
MyProject
do
@moduledoc """
Documentation for MyProject.
"""
use
Fermo
def
build
do
config
=
initial_config
()
{
:ok
, config}
end
end
The command
use
Fermo
prepares the initial
config
structure.
In order to not have your template files automatically built as
simple files
use
:exclude
.
use
Fermo
, %{
exclude:
[
"
templates/*
"
,
"
layouts/*
"
,
"
javascripts/*
"
,
"
stylesheets/*
"
],
}
Most static site generators build one webpage for every source page (e.g. Hugo).
Middleman provides the very powerful but strangely named
proxy
, which allows you to produce many pages from one template. So, if you have a local JSON of YAML file, or even better an online CMS, as a source, you can build a page for each of your items without having to commit the to your Git repo.
In Fermo, dynamic, data-based pages are created with the
page
method in your project configuration's
build/0
method.
def
build
do
..
.
foo
=
..
.
# loaded from some external source
page
(
config,
"
templates/foo.html.slim
"
,
"
/foos/
#{
foo.slug
}
/index.html
"
,
%{
foo:
foo},
%{
locale:
:en
}
)
..
.
end
Currently, Fermo only supports SLIM templates for HTML.
There are various types of templates:
priv/source
will be built. The
partials
directory is exluded by default - see
excludes
.
Top level pages are called with the following parameters:
params
- the parameters passed directly to the template or partial,
context
- hash of contextual information.
:env
- the application environment,
:module
- the module of the compiled template,
:template
- the top-level page or partial template pathname, with path relative to the source root,
:page
- see below.
Information about the top-level page.
:template
- the template path and name relative to the source root,
:target
- the path of the generated file,
:path
- the online path of the page,
:params
- the parameters passed to the template,
:options
- other options, e.g. the locale.
Partials are also called with the same 2 parameters, but the values in
:page
are those of the top-level page, not the partial itself.
If you pass an
:i18n
key with a list of locales to Fermo, your locale files will be loaded at build time and files under
localizable
will be built for each locale.
defmodule
MyProject
do
@moduledoc """
Documentation for MyProject.
"""
use
Fermo
, %{
..
.
i18n:
[
:en
,
:fr
]
}
..
.
end
:localized_paths
Fermo can optionally create a mapping of translated paths for any page.
This allows you to easily manage language switching UIs and alternate language meta tags.
To activate localized_paths, you need to pass a flag in your initial config:
defmodule
MyProject
do
use
Fermo
, %{
..
.
i18n:
[
:en
,
:fr
],
path_map:
true
,
..
.
}
..
.
end
Then ensure you pass an
:id
and
:locale
in the options parameter of your Fermo.page/5 calls:
Fermo
.
page
(
config,
"
templates/my_template.html.slim
"
,
"
/posts/
#{
post.slug
}
/index.html
"
,
%{
post:
post},
%{
locale:
:fr
,
id:
"
post-
#{
post.id
}
"
}
)
When you do this, Fermo will collect together all pages with the same
:id
so when your template is called, it will have a
:localized_paths
Map available:
%{
..
.
localized_paths:
%{
en:
"
/posts/about-localization
"
,
fr:
"
/posts/a-propos-de-la-localisation
"
,
}
}
You can then use
:localized_paths
to build create links between the different language versions of a page.
You can do the same for non-dynamic localized pages too, by indicating the id in the template's frontmatter:
---
id
:
my-localized-page
---
Fermo was created as an improvement on Middleman, so its defaults tend to be the same its progenitor.