ExBanner

______ ____
/ ____/ __/ __ )____ _____ ____ ___ _____
/ __/ | |/_/ __ / __ `/ __ \/ __ \/ _ \/ ___/
/ /____> </ /_/ / /_/ / / / / / / / __/ /
/_____/_/|_/_____/\__,_/_/ /_/_/ /_/\___/_/

ASCII art banners for Elixir applications.

Installation

def deps do
[
{:exbanner, "~> 0.1"}
]
end

Requires Elixir 1.15+ and OTP 25+.

Startup banner

Tell ExBanner which application owns the banner:

# config/config.exs
config :exbanner, otp_app: :my_app

Then create priv/banner.txt in your application:

$[gold] __ __ _
| \/ |_ _ / \ _ __ _ __
| |\/| | | | | / _ \ | '_ \| '_ \
| | | | |_| | / ___ \| |_) | |_) |
|_| |_|\__, | /_/ \_\ .__/| .__/
|___/ |_| |_|$[reset]
$[dimgray]$app v$version | Elixir $elixir_version | OTP $otp_release$[reset]

ExBanner starts before your application, so the banner is printed before any of your logs. It works with mix run, iex -S mix, mix phx.server and releases.

Without otp_app ExBanner prints nothing, so a library that depends on ExBanner never prints a banner in your application unless you opt in. When otp_app is set and priv/banner.txt does not exist, ExBanner prints a default banner with the application name in the :standard font.

A failure while printing the startup banner is logged as a warning and never stops your application.

Placeholders

banner.txt is plain text. ExBanner replaces these placeholders, in the same style as Logger formats:

Placeholder Value
$app The otp_app name
$version Application version
$description Application description
$elixir_version System.version()
$otp_release System.otp_release()
$exbanner_version ExBanner version
$node node()
$hostname Host name
$release RELEASE_NAME, empty outside a release
$schedulers System.schedulers_online()

Only known names are replaced. Any other $ stays as written, so ASCII art with $$$$ is safe. A placeholder is read as a whole word: $app_name is not $app followed by _name, and stays literal.

Add your own values with :vars, as a map, a keyword list or an {module, function, args} tuple that returns one. Your values win over the built-in ones.

config :exbanner, otp_app: :my_app, vars: %{env: config_env()}

Colors

Write any Bunt color or style between brackets: $[red], $[gold], $[darkorange], $[bright], $[underline], $[reset]. Background colors use the _background suffix, as in $[darkblue_background].

ExBanner adds a reset at the end of a banner that uses colors. Colors are removed when ANSI is disabled and in :log mode. Unknown colors stay in the text and are logged as a warning. Sequences that move the cursor or clear the screen are not accepted.

Configuration

Option Default Description
:otp_app nil Application that owns the banner. Required to print anything.
:location priv/banner.txt of :otp_app A path, or {:priv, app, "file.txt"}. A missing file logs a warning and prints the default banner.
:mode :console :console writes to stdout, :log uses Logger.info/1, :off disables the startup banner.
:mix_tasks :all :all, :none, or a list of task names such as ["phx.server", "run"].
:vars %{} Extra placeholders.
:font_paths [] Directories with your own .flf fonts.

The startup banner also appears in mix tasks such as mix test and mix ecto.migrate. To limit it:

# only when the application runs
config :exbanner, mix_tasks: ["phx.server", "run"]
# or never in tests
# config/test.exs
config :exbanner, mode: :off

iex -S mix counts as run. Releases have no mix tasks and always print the banner.

To print the banner yourself, set mode: :off and call ExBanner.show/0 where you want it.

Rendering text

iex> ExBanner.print("Hello", font: :small)
_ _ _ _
| || |___| | |___
| __ / -_) | / _ \
|_||_\___|_|_\___/
:ok
iex> ExBanner.render("Hello", font: :slant)
{:ok, " __ __ ____ \n ..."}
iex> ExBanner.render!("Hello")
" _ _ _ _ \n ..."
iex> ExBanner.render("Hello", font: :crazy)
{:error, {:unknown_font, "crazy"}}
Function Returns
render(text, opts) {:ok, string} or {:error, reason}
render!(text, opts) The string, or raises ExBanner.Error
print(text, opts) :ok, raises on errors
show() Prints the startup banner, ignoring mode: :off and :mix_tasks
fonts() The bundled font names

Options:

Option Default Description
:font :standard A bundled font, a font in :font_paths, or a path to a .flf file
:width 80 Line width. Longer text wraps at word boundaries, like figlet -w.
:color nil Bunt color, print/2 only
:device :stdio IO device, print/2 only

Characters the font does not have are rendered without accents when possible (ç becomes c), and as ? otherwise. They are never dropped silently.

Fonts

Font License Source
:banner BSD-3-Clause FIGlet 2.2.5
:big BSD-3-Clause FIGlet 2.2.5
:block BSD-3-Clause FIGlet 2.2.5
:bubble BSD-3-Clause FIGlet 2.2.5
:digital BSD-3-Clause FIGlet 2.2.5
:ivrit BSD-3-Clause FIGlet 2.2.5
:lean BSD-3-Clause FIGlet 2.2.5
:mini BSD-3-Clause FIGlet 2.2.5
:mnemonic BSD-3-Clause FIGlet 2.2.5
:script BSD-3-Clause FIGlet 2.2.5
:shadow BSD-3-Clause FIGlet 2.2.5
:slant BSD-3-Clause FIGlet 2.2.5
:small BSD-3-Clause FIGlet 2.2.5
:small_script BSD-3-Clause FIGlet 2.2.5
:small_shadow BSD-3-Clause FIGlet 2.2.5
:small_slant BSD-3-Clause FIGlet 2.2.5
:standard BSD-3-Clause FIGlet 2.2.5
:term BSD-3-Clause FIGlet 2.2.5
:ansi_compact MIT Loic Cressot
:classy MIT Loic Cressot
:coder_mini MIT Loic Cressot
:font_font MIT Oscar Cole
:linguaholic_mini_block MIT Linguaholic
:linguaholic_neon MIT Linguaholic
:linguaholic_rounded MIT Linguaholic
:linguaholic_shadow_3d MIT Linguaholic

Your own fonts

Popular fonts such as Crazy, Doom, Epic or ANSI Shadow are not bundled because their files carry no license that allows redistribution. The full list, with the reason for each font, is in ISSUES.md.

You can still use them. Download the .flf file and point ExBanner to its directory:

config :exbanner, font_paths: [Path.expand("../priv/fonts", __DIR__)]
ExBanner.print("Hello", font: :crazy)
ExBanner.print("Hello", font: "/path/to/crazy.flf")

Fonts in :font_paths take precedence over bundled fonts with the same name. Fonts are parsed on first use and cached with :persistent_term.

Security

ExBanner never evaluates code from banner.txt or from font files. Control characters, ANSI escape sequences and Unicode bidirectional overrides are removed from banner.txt, from placeholder values, from rendered text and from font glyphs, so a hostname or an environment variable cannot inject terminal sequences or fake log lines. Placeholder values are always a single line. Only ExBanner emits ANSI sequences, from a fixed list of colors and styles. Font and color names are never converted to atoms.

License

ExBanner is released under the MIT license. Bundled fonts keep their own licenses: see LICENSE and priv/fonts/LICENSE.figlet.