\section{Setup} \subsection{Prerequisites} To run N2O websites you need to install Erlang version 18 or higher. N2O works on Windows, Mac and Linux. \subsection{Kickstart Bootstrap} To try N2O you only need to fetch it from Github and build. We don't use fancy scripts, so building process is OTP compatible: bootstrap site is bundled as an Erlang release. \vspace{1\baselineskip} \begin{lstlisting} $ git clone git://github.com/synrc/n2o $ cd n2o/samples $ ./mad deps compile plan repl \end{lstlisting} \vspace{1\baselineskip} Now you can try: \footahref{http://localhost:8000}{http://localhost:8000}. On Linux you should do at first: \vspace{1\baselineskip} \begin{lstlisting} $ sudo apt-get install inotify-tools \end{lstlisting} \vspace{1\baselineskip} \newpage \subsection{Application Template} If you want to start using N2O inside your application, you can use Cowboy dispatch parameter for passing HTTP, REST, WebSocket and Static N2O endpoints: \vspace{1\baselineskip} \begin{lstlisting}[caption=sample.erl] -module(sample). -behaviour(supervisor). -behaviour(application). -export([init/1, start/2, stop/1, main/1]). main(A) -> mad:main(A). start(_,_) -> supervisor:start_link({local,review},review,[]). stop(_) -> ok. init([]) -> { ok, { { one_for_one, 5, 100 }, [spec()] } }. spec() -> ranch:child_spec(http, 100, ranch_tcp, port(), cowboy_protocol, env()). port() -> [ { port, wf:config(n2o,port,8000) } ]. env() -> [ { env, [ { dispatch, points() } ] } ]. static() -> { dir, "apps/sample/priv/static", mime() }. n2o() -> { dir, "deps/n2o/priv", mime() }. mime() -> [ { mimetypes, cow_mimetypes, all } ]. points() -> cowboy_router:compile([{'_', [ { "/static/[...]", n2o_static, static()}, { "/n2o/[...]", n2o_static, n2o()}, { "/ws/[...]", n2o_stream, []}, { '_', n2o_cowboy, []} ]}]). \end{lstlisting} \vspace{1\baselineskip} \newpage While Listing 1 is a little bit criptic we want to say that N2O intentionally not introduced here any syntax sugar. For any Erlang application you need to create application and supervisor behavior modules which we combined in the same Erlang file for simplicity. \paragraph{} Cowboy routing rules also leaved as is. We'd better to leave our efforts for making N2O protocol and N2O internals simplier. Here we can't fix a much. Just use this as template for bootstrapping N2O based applications. \subsection{Companion Dependencies} For raw N2O use with BERT message formatter you need only one N2O dependecy, but if you want to use DTL templates, JSON message formatter, SHEN JavaScript Compiler or NITRO Nitrogen DSL you can plug all of them separately. \vspace{1\baselineskip} \begin{lstlisting} https://github.com/synrc/n2o 2.9 https://github.com/synrc/nitro 2.9 https://github.com/synrc/kvs 2.9 https://github.com/synrc/active 2.9 https://github.com/synrc/shen 1.5 https://github.com/synrc/rest 1.5 https://github.com/spawnproc/bpe 1.5 https://github.com/spawnproc/forms 1.5 \end{lstlisting} \vspace{1\baselineskip} \newpage \subsection{Configuration} \vspace{1\baselineskip} \begin{lstlisting}[caption=sys.config] [{n2o, [{port,8000}, {app,review}, {route,routes}, {mq,n2o_mq}, {json,jsone}, {log_modules,config}, {log_level,config}, {log_backend,n2o_log}, {session,n2o_session}, {origin,<<"*">>}, {bridge,n2o_cowboy}, {pickler,n2o_pickle}, {erroring,n2o_error}]}, {kvs, [{dba,store_mnesia}, {schema, [kvs_user, kvs_acl, kvs_feed, kvs_subscription ]} ]} ]. \end{lstlisting} \vspace{1\baselineskip} \subsection*{Ports} N2O uses two ports for WebSocket and HTTP connections. \vspace{1\baselineskip} \begin{lstlisting} wf:config(n2o,port,443) wf:config(n2o,websocket_port,443) \end{lstlisting} \vspace{1\baselineskip} If you use server pages mode N2O will render HTML with nessesary ports values. For single page application mode you should redefine these ports inside the template: \vspace{1\baselineskip} \begin{lstlisting} \end{lstlisting} \vspace{1\baselineskip} \newpage \subsection*{Application} In {\bf app} setting you should place the name of your OTP application that will be treated by N2O and NITRO as a source for templates and other static data with {\bf code:priv\_dir}. \subsection*{Routes} Setting {\bf route} is a place for the name of Erlang module where resides mappings from URL to page modules. \subsection*{Logging} N2O supports logging API and you can plug different logging module. It ships with {\bf n2o\_io} and {\bf n2o\_log} modules which you can set in the {\bf log\_backend} option. This is how logging looks like in N2O: \vspace{1\baselineskip} \begin{lstlisting} wf:info(index,"Message: ~p",[Message]), \end{lstlisting} \vspace{1\baselineskip} First argument is a module from which function is being called. By using this N2O can filter all log messages with special filter settled with {\bf log\_modules} option. It says in which Erlang module function {\bf log\_modules/0} exists that returns allowed Erlang modules to log. Option {\bf log\_level} which specified in a similar way, it specifies the module with function {\bf log\_level/0} that could return one of {\bf none}, {\bf error}, {\bf warning} or {\bf info} atom values which means different error log levels. \vspace{1\baselineskip} \begin{lstlisting} -module(config). -compile(export_all). log_level() -> info. log_modules() -> [ login, index ]. \end{lstlisting} \vspace{1\baselineskip} \newpage \subsection*{Message Queue} In {\bf mq} settings you should place the name of Erlang module which supports message queue API. By default N2O provides {\bf n2o\_mq} module. \subsection*{Formatter} With {\bf formatter} option you may set the WebSocket channel termination formatter such as {\bf bert} or {\bf json}. If you will select json as formatter you may want also to chose a json encoder in {\bf json} option. By default in n2o enabled {\bf json} formatter and {\bf jsone} encoder. The main reason is that {\bf jsone} is written in pure erlang idiomatic code and is ready to run on LING without C NIF linkage. But you may want to switch to {\bf jsonx} on BEAM or whatever. \subsection*{Minimal Page} And then add a minimal {\bf index.erl} page: \vspace{1\baselineskip} \begin{lstlisting}[caption=index.erl] -module(index). -compile(export_all). -include_lib("nitro/include/nitro.hrl"). main() -> #span{body="Hello"}. \end{lstlisting} \vspace{1\baselineskip}