diff --git a/.gitignore b/.gitignore
index ac732da..2013848 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+doc/*.html
+!doc/tpl.html
_build
deps/**
ebin/**
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..5d72b03
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,21 @@
+SOURCE_DOCS := $(wildcard *.md)
+
+EXPORTED_DOCS=\
+ $(SOURCE_DOCS:.md=.html)
+
+RM=/bin/rm
+
+PANDOC=pandoc
+
+PANDOC_HTML_OPTIONS=--standalone --highlight-style=tango --template tpl.html -f gfm --to html5
+
+%.html : %.md
+ $(PANDOC) $(PANDOC_HTML_OPTIONS) -o $@ $<
+
+
+.PHONY: all clean
+
+all : $(EXPORTED_DOCS)
+
+clean:
+ - $(RM) -f $(EXPORTED_DOCS)
diff --git a/doc/build.sh b/doc/build.sh
new file mode 100755
index 0000000..188a5ee
--- /dev/null
+++ b/doc/build.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+cd $(dirname $(realpath $0))
+
+make clean
+make
+
+# fix internal doc links
+sed -i 's/https:\/\/github\.com\/doc\/\([a-zA-Z_-]*\)\.md/\1.html/g' *.html
+sed -i 's/\"\([a-zA-Z_-]*\)\.md\([a-zA-Z_-#]*\)\"/\"\1.html\2\"/g' *.html
+sed -i 's/\"doc\/\([a-zA-Z_-]*\)\.md\"/\"\1.html\"/g' *.html
+sed -i 's/\"\([a-zA-Z_-]*\)\.md\"/\"\1.html\"/g' *.html
+
+# fix external doc links
+sed -i 's/maps\.html\#/http:\/\/erlang.org\/doc\/man\/maps\.html#/g' *.html
+sed -i 's/unicode\.html\#/http:\/\/erlang.org\/doc\/man\/unicode\.html#/g' *.html
+sed -i 's/maps\.md\#/http:\/\/erlang.org\/doc\/man\/maps\.html#/g' *.html
+sed -i 's/unicode\.md\#/http:\/\/erlang.org\/doc\/man\/unicode\.html#/g' *.html
+
+# cleans up the indentation of code blocks
+sed -i 's/ *:first-child{margin-top:0!important}body>*:last-child{margin-bottom:0!important}@media screen{body{box-shadow:0 0 0 1px #cacaca,0 0 0 4px #eee}}h1,h2,h3,h4,h5,h6{margin:20px 0 10px;padding:0;font-weight:bold;-webkit-font-smoothing:subpixel-antialiased;cursor:text}h1{font-size:28px;color:#000}h2{font-size:24px;border-bottom:1px solid #ccc;color:#000}h3{font-size:18px;color:#333}h4{font-size:16px;color:#333}h5{font-size:14px;color:#333}h6{color:#777;font-size:14px}p,blockquote,table,pre{margin:15px 0}ul{padding-left:30px}ol{padding-left:30px}ol li ul:first-of-type{margin-top:0}hr{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;border:0 none;color:#ccc;height:4px;padding:0}body>h2:first-child{margin-top:0;padding-top:0}body>h1:first-child{margin-top:0;padding-top:0}body>h1:first-child+h2{margin-top:0;padding-top:0}body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child{margin-top:0;padding-top:0}a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6{margin-top:0;padding-top:0}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p,ul li>:first-child,ol li>:first-child{margin-top:0}dl{padding:0}dl dt{font-size:14px;font-weight:bold;font-style:italic;padding:0;margin:15px 0 5px}dl dt:first-child{padding:0}dl dt>:first-child{margin-top:0}dl dt>:last-child{margin-bottom:0}dl dd{margin:0 0 15px;padding:0 15px}dl dd>:first-child{margin-top:0}dl dd>:last-child{margin-bottom:0}blockquote{border-left:4px solid #DDD;padding:0 15px;color:#777}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}table{border-collapse:collapse;border-spacing:0;font-size:100%;font:inherit}table th{font-weight:bold;border:1px solid #ccc;padding:6px 13px}table td{border:1px solid #ccc;padding:6px 13px}table tr{border-top:1px solid #ccc;background-color:#fff}table tr:nth-child(2n){background-color:#f8f8f8}img{max-width:100%}code,tt{margin:0 2px;padding:0 5px;white-space:nowrap;border:1px solid #eaeaea;background-color:#f8f8f8;border-radius:3px;font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;color:#333}pre>code{margin:0;padding:0;white-space:pre;border:0;background:transparent}.highlight pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre code,pre tt{background-color:transparent;border:0}.poetry pre{font-family:Georgia,Garamond,serif!important;font-style:italic;font-size:110%!important;line-height:1.6em;display:block;margin-left:1em}.poetry pre code{font-family:Georgia,Garamond,serif!important;word-break:break-all;word-break:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto;white-space:pre-wrap}sup,sub,a.footnote{font-size:1.4ex;height:0;line-height:1;vertical-align:super;position:relative}sub{vertical-align:sub;top:-1px}@media print{body{background:#fff}img,pre,blockquote,table,figure{page-break-inside:avoid}body{background:#fff;border:0}code{background-color:#fff;color:#333!important;padding:0 .2em;border:1px solid #dedede}pre{background:#fff}pre code{background-color:white!important;overflow:visible}}@media screen{body.inverted{color:#eee!important;border-color:#555;box-shadow:none}.inverted body,.inverted hr .inverted p,.inverted td,.inverted li,.inverted h1,.inverted h2,.inverted h3,.inverted h4,.inverted h5,.inverted h6,.inverted th,.inverted .math,.inverted caption,.inverted dd,.inverted dt,.inverted blockquote{color:#eee!important;border-color:#555;box-shadow:none}.inverted td,.inverted th{background:#333}.inverted h2{border-color:#555}.inverted hr{border-color:#777;border-width:1px!important}::selection{background:rgba(157,193,200,0.5)}h1::selection{background-color:rgba(45,156,208,0.3)}h2::selection{background-color:rgba(90,182,224,0.3)}h3::selection,h4::selection,h5::selection,h6::selection,li::selection,ol::selection{background-color:rgba(133,201,232,0.3)}code::selection{background-color:rgba(0,0,0,0.7);color:#eee}code span::selection{background-color:rgba(0,0,0,0.7)!important;color:#eee!important}a::selection{background-color:rgba(255,230,102,0.2)}.inverted a::selection{background-color:rgba(255,230,102,0.6)}td::selection,th::selection,caption::selection{background-color:rgba(180,237,95,0.5)}.inverted{background:#0b2531;background:#252a2a}.inverted body{background:#252a2a}.inverted a{color:#acd1d5}}.highlight .c{color:#998;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .k,.highlight .o{font-weight:bold}.highlight .cm{color:#998;font-style:italic}.highlight .cp{color:#999;font-weight:bold}.highlight .c1{color:#998;font-style:italic}.highlight .cs{color:#999;font-weight:bold;font-style:italic}.highlight .gd{color:#000;background-color:#fdd}.highlight .gd .x{color:#000;background-color:#faa}.highlight .ge{font-style:italic}.highlight .gr{color:#a00}.highlight .gh{color:#999}.highlight .gi{color:#000;background-color:#dfd}.highlight .gi .x{color:#000;background-color:#afa}.highlight .go{color:#888}.highlight .gp{color:#555}.highlight .gs{font-weight:bold}.highlight .gu{color:#800080;font-weight:bold}.highlight .gt{color:#a00}.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{font-weight:bold}.highlight .kt{color:#458;font-weight:bold}.highlight .m{color:#099}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .nb{color:#0086b3}.highlight .nc{color:#458;font-weight:bold}.highlight .no{color:#008080}.highlight .ni{color:#800080}.highlight .ne,.highlight .nf{color:#900;font-weight:bold}.highlight .nn{color:#555}.highlight .nt{color:#000080}.highlight .nv{color:#008080}.highlight .ow{font-weight:bold}.highlight .w{color:#bbb}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#099}.highlight .sb,.highlight .sc,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .bp{color:#999}.highlight .vc,.highlight .vg,.highlight .vi{color:#008080}.highlight .il{color:#099}.highlight .gc{color:#999;background-color:#eaf2f5}.type-csharp .highlight .k,.type-csharp .highlight .kt{color:#00F}.type-csharp .highlight .nf{color:#000;font-weight:normal}.type-csharp .highlight .nc{color:#2b91af}.type-csharp .highlight .nn{color:#000}.type-csharp .highlight .s,.type-csharp .highlight .sc{color:#a31515}
diff --git a/doc/index.md b/doc/index.md
new file mode 100644
index 0000000..2f1d9e6
--- /dev/null
+++ b/doc/index.md
@@ -0,0 +1,305 @@
+# elli - Erlang web server for HTTP APIs
+
+[![Hex.pm][hex badge]][hex package]
+[![Documentation][doc badge]][docs]
+[![Erlang][erlang badge]][erlang downloads]
+[![Travis CI][travis badge]][travis builds]
+[![Coverage Status][coveralls badge]][coveralls link]
+[![MIT License][license badge]](LICENSE)
+
+[travis builds]: https://travis-ci.org/elli-lib/elli
+[travis badge]: https://travis-ci.org/elli-lib/elli.svg
+[hex badge]: https://img.shields.io/hexpm/v/elli.svg
+[hex package]: https://hex.pm/packages/elli
+[latest release]: https://github.com/elli-lib/elli/releases/latest
+[erlang badge]: https://img.shields.io/badge/erlang-%E2%89%A518.0-red.svg
+[erlang downloads]: http://www.erlang.org/downloads
+[doc badge]: https://img.shields.io/badge/docs-edown-green.svg
+[docs]: doc/README.md
+[coveralls badge]: https://coveralls.io/repos/github/elli-lib/elli/badge.svg?branch=develop
+[coveralls link]: https://coveralls.io/github/elli-lib/elli?branch=develop
+[license badge]: https://img.shields.io/badge/license-MIT-blue.svg
+
+Elli is a webserver you can run inside your Erlang application to
+expose an HTTP API. Elli is a aimed exclusively at building
+high-throughput, low-latency HTTP APIs. If robustness and performance
+is more important than general purpose features, then `elli` might be
+for you. If you find yourself digging into the implementation of a
+webserver, `elli` might be for you. If you're building web services,
+not web sites, then `elli` might be for you.
+
+Elli is used in production at Wooga and Game Analytics. Elli requires
+OTP 18.0 or newer.
+
+
+## Installation
+
+To use `elli` you will need a working installation of Erlang 18.0 (or later).
+
+Add `elli` to your application by adding it as a dependency to your
+[`rebar.config`](http://www.rebar3.org/docs/configuration):
+
+```erlang
+{deps, [elli]}.
+```
+
+Afterwards you can run:
+
+```sh
+$ rebar3 compile
+```
+
+
+## Usage
+```sh
+$ rebar3 shell
+```
+
+```erlang
+%% starting elli
+1> {ok, Pid} = elli:start_link([{callback, elli_example_callback}, {port, 3000}]).
+```
+
+## Examples
+
+### Callback Module
+
+The best source to learn how to write a callback module
+is [src/elli_example_callback.erl](src/elli_example_callback.erl) and
+its [generated documentation](doc/elli_example_callback.md). There are a bunch
+of examples used in the tests as well as descriptions of all the events.
+
+A minimal callback module could look like this:
+
+```erlang
+-module(elli_minimal_callback).
+-export([handle/2, handle_event/3]).
+
+-include_lib("elli/include/elli.hrl").
+-behaviour(elli_handler).
+
+handle(Req, _Args) ->
+ %% Delegate to our handler function
+ handle(Req#req.method, elli_request:path(Req), Req).
+
+handle('GET',[<<"hello">>, <<"world">>], _Req) ->
+ %% Reply with a normal response. `ok' can be used instead of `200'
+ %% to signal success.
+ {ok, [], <<"Hello World!">>};
+
+handle(_, _, _Req) ->
+ {404, [], <<"Not Found">>}.
+
+%% @doc Handle request events, like request completed, exception
+%% thrown, client timeout, etc. Must return `ok'.
+handle_event(_Event, _Data, _Args) ->
+ ok.
+```
+
+
+### Supervisor Childspec
+
+To add `elli` to a supervisor you can use the following example and adapt it to
+your needs.
+
+```erlang
+-module(fancyapi_sup).
+-behaviour(supervisor).
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ ElliOpts = [{callback, fancyapi_callback}, {port, 3000}],
+ ElliSpec = {
+ fancy_http,
+ {elli, start_link, [ElliOpts]},
+ permanent,
+ 5000,
+ worker,
+ [elli]},
+
+ {ok, { {one_for_one, 5, 10}, [ElliSpec]} }.
+```
+
+
+## Features
+
+Here's the features Elli _does_ have:
+
+* [Rack][]-style request-response. Your handler function gets a
+ complete request and returns a complete response. There's no
+ messaging, no receiving data directly from the socket, no writing
+ responses directly to the socket. It's a very simple and
+ straightforward API. Have a look at [`elli_example_callback`](elli_example_callback.md)
+for examples.
+
+* Middlewares allow you to add useful features like compression,
+encoding, stats, but only have it used when needed. No features you
+don't use on the critical path.
+
+* Short-circuiting of responses using exceptions, allows you to use
+ "assertions" that return for example 403 permission
+ denied. `is_allowed(Req) orelse throw({403, [], <<"Permission
+ denied">>})`.
+
+* Every client connection gets its own process, isolating the failure
+of a request from another. For the duration of the connection, only
+one process is involved, resulting in very robust and efficient
+code.
+
+* Binaries everywhere for strings.
+
+* Instrumentation inside the core of the webserver, triggering user
+ callbacks. For example when a request completes, the user callback
+ gets the `request_complete` event which contains timings of all the
+different parts of handling a request. There's also events for
+clients unexpectedly closing a connection, crashes in the user
+callback, etc.
+
+* Keep alive, using one Erlang process per connection only active
+when there is a request from the client. Number of connections is
+only limited by RAM and CPU.
+
+* Chunked transfer in responses for real-time push to clients
+
+* Basic pipelining. HTTP verbs that does not have side-effects(`GET`
+ and `HEAD`) can be pipelined, ie. a client supporting pipelining
+can send multiple requests down the line and expect the responses
+to appear in the same order as requests. Elli processes the
+requests one at a time in order, future work could make it possible
+to process them in parallel.
+
+* SSL using built-in Erlang/OTP ssl, nice for low volume admin
+interfaces, etc. For high volume, you should probably go with
+nginx, stunnel or ELB if you're on AWS.
+
+* Implement your own connection handling, for WebSockets, streaming
+ uploads, etc. See [`elli_example_callback_handover`](elli_example_callback_handover.md).
+
+## Extensions
+
+* [elli_access_log](https://github.com/elli-lib/elli_access_log):
+Access log
+* [elli_basicauth](https://github.com/elli-lib/elli_basicauth):
+Basic auth
+* [elli_chatterbox](https://github.com/elli-lib/elli_chatterbox):
+HTTP/2 support
+* [elli_cloudfront](https://github.com/elli-lib/elli_cloudfront):
+CloudFront signed URLs
+* [elli_cookie](https://github.com/elli-lib/elli_cookie):
+Cookies
+* [elli_date](https://github.com/elli-lib/elli_date):
+"Date" header
+* [elli_fileserve](https://github.com/elli-lib/elli_fileserve):
+Static content
+* [elli_prometheus](https://github.com/elli-lib/elli_prometheus):
+Prometheus
+* [elli_stats](https://github.com/elli-lib/elli_stats):
+Real-time statistics dashboard
+* [elli_websockets](https://github.com/elli-lib/elli_websocket):
+WebSockets
+* [elli_xpblfe](https://github.com/elli-lib/elli_xpblfe):
+X-Powered-By LFE
+
+## About
+
+From operating and debugging high-volume, low-latency apps we have
+gained some valuable insight into what we want from a webserver. We
+want simplicity, robustness, performance, ease of debugging,
+visibility into strange client behaviour, really good instrumentation
+and good tests. We are willing to sacrifice almost everything, even
+basic features to achieve this.
+
+With this in mind we looked at the big names in the Erlang
+community: [Yaws][], [Mochiweb][], [Misultin][] and [Cowboy][]. We
+found [Mochiweb][] to be the best match. However, we also wanted to
+see if we could take the architecture of [Mochiweb][] and improve on
+it. `elli` takes the acceptor-turns-into-request-handler idea found
+in [Mochiweb][], the binaries-only idea from [Cowboy][] and the
+request-response idea from [WSGI][]/[Rack][] (with chunked transfer
+being an exception).
+
+On top of this we built a handler that allows us to write HTTP
+middleware modules to add practical features, like compression of
+responses, HTTP access log with timings, a real-time statistics
+dashboard and chaining multiple request handlers.
+
+## Aren't there enough webservers in the Erlang community already?
+
+There are a few very mature and robust projects with steady
+development, one recently ceased development and one new kid on the
+block with lots of interest. As `elli` is not a general purpose
+webserver, but more of a specialized tool, we believe it has a very
+different target audience and would not attract effort or users away
+from the big names.
+
+## Why another webserver? Isn't this just the NIH syndrome?
+
+[Yaws][], [Mochiweb][], [Misultin][], and [Cowboy][] are great
+projects, hardened over time and full of very useful features for web
+development. If you value developer productivity, [Yaws][] is an
+excellent choice. If you want a fast and lightweight
+server, [Mochiweb][] and [Cowboy][] are excellent choices.
+
+Having used and studied all of these projects, we believed that if we
+merged some of the existing ideas and added some ideas from other
+communities, we could create a core that was better for our use cases.
+
+It started out as an experiment to see if it is at all possible to
+significantly improve and it turns out that for our particular use
+cases, there is enough improvement to warrant a new project.
+
+## What makes Elli different?
+
+Elli has a very simple architecture. It avoids using more processes
+and messages than absolutely necessary. It uses binaries for
+strings. The request-response programming model allows middlewares to
+do much heavy lifting, so the core can stay very simple. It has been
+instrumented so as a user you can understand where time is spent. When
+things go wrong, like the client closed the connection before you
+could send a response, you are notified about these things so you can
+better understand your client behaviour.
+
+## Performance
+
+"Hello World!" micro-benchmarks are really useful when measuring the
+performance of the webserver itself, but the numbers usually do more
+harm than good when released. I encourage you to run your own
+benchmarks, on your own hardware. Mark Nottingham has some
+[very good pointers](http://www.mnot.net/blog/2011/05/18/http_benchmark_rules)
+about benchmarking HTTP servers.
+
+[Yaws]: https://github.com/klacke/yaws
+[Mochiweb]: https://github.com/mochi/mochiweb
+[Misultin]: https://github.com/ostinelli/misultin
+[Cowboy]: https://github.com/ninenines/cowboy
+[WSGI]: https://www.python.org/dev/peps/pep-3333/
+[Rack]: https://github.com/rack/rack
+
+
+## Modules ##
+
+
+
+
+
+## License
+
+Elli is licensed under [The MIT License](LICENSE).
+
+Copyright (c) 2012-2016 Knut Nesheim, 2016-2018 elli-lib team
diff --git a/doc/tpl.html b/doc/tpl.html
new file mode 100644
index 0000000..506b5f2
--- /dev/null
+++ b/doc/tpl.html
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ index
+
+
+
+
+
+
+ $body$
+
+
diff --git a/rebar.config b/rebar.config
index 94ac836..ad12c77 100644
--- a/rebar.config
+++ b/rebar.config
@@ -6,6 +6,7 @@
{docs, [
{deps, [{edown, "0.8.1"}]},
{edoc_opts, [
+ {preprocess, true},
{def, [
{'EXAMPLE_CONF',"[{callback,elli_example_callback},{callback_args,[]}]"}
]},
diff --git a/src/elli.app.src b/src/elli.app.src
index 5a160dc..9c1f243 100644
--- a/src/elli.app.src
+++ b/src/elli.app.src
@@ -1,7 +1,7 @@
{application, elli,
[
{description, "Erlang web server for HTTP APIs"},
- {vsn, "3.0.0"},
+ {vsn, "3.1.0"},
{modules, [
elli,
elli_example_callback,