N2O   
 Erlang Web Stack
Maxim Sokhatsky
Synrc Research Center
Micro REST
Python Flask
Ruby Sinatra
PHP Silex
  Scala Scalatra  
Concurrency in Mind
Ruby Celluloid
PHP React
PHP phpDaemon
  Java+Scala Play Akka  
SPA
Angular Meteor Ember
Chaplin Brunch
 Knockout    React    D3
Backbone   jQuery
Functional DSL
Scala Lift
   Erlang N2O   
Haskell BlazeHtml
OCaml Ocsigen
F# WebSharper
  Clojure  
Laser Enlive
Compojure Ring
Hiccup ClojureScript Om
http-kit aleph noir
JVM
Elixir  Weber 
              def action(_, conn) do
                     {:render, [project: "simpleTodo"], []}
              end
 
    def add([body: body], _conn) do
        {:json, [response: "ok"], [{"Content-Type", "application/json"}]}
    end
 
                  def wrong(_, _) do
                         {:redirect, "/"}
                  end
Erlang  ChicagoBoss 
DTL Engine
Database Connectivity
PubSub
Ruby on Rails like
 Nitrogen 
 N2O  ~2000 LOC 
One Process per Connection
Binary Page Construction 
Zero Bridge 
GProc Pub/Sub 
WebSockets, KVS DB, Shen
Tuned Layers
static and dynamic Routing Path
cleaned Query Parser
Session Cookies stored in ETS
cached DTL Templates
optimized Nitrogen DSL rendering
HTML Elements binaries
JavaScript Actions deferred
Layers Performance
                 components                TCP conn (K)
     PHP5 FCGI   Simple Script <?php ?>          5     
      Nitrogen   No session, No DSL, DTL         1   
           N2O   Sessions, DSL, DTL              7
           N2O   Sessions, no DSL, DTL           10
           N2O   No Sessions, no DSL, DTL        13 
                               On same machine 
             raw webserver performance
                              measured with wrk:   NGINX -- 60K 
Measuring Tools
  
        requests     pages/sec    latency (ms) 
     wrk       15K      13628.86      18.88   
      ab       10K       5464.63     190  
 httperf       10K       3623.50     200 
   siege        1K        884.51     430 
    
                               On same machine 
                 raw webserver performance
                                  measured with wrk:
      NGINX -- 60K 
    
        
Decreasing Latency
From 2x to ∞
    
Deliver HTML ASAP
 Deferred JavaScript delivery
    after 
    WebSocket
     connection established
<script>
TransitionProcess = '<0.7780.5>'
</script>
socket.send(["N2O",TransitionProcess]).
Dynamic HTML  cow 

 SPA  and  DTL 
Render both HTML and JavaScript using DSL :
#button { postback = login, source = [ user, pass ] }
 
Or render only JavaScript ..
#button { render = script,
                    id = ElementId,
                        postback = login, 
                                  source = [ user, pass ] }
.. when you develop SPA
Render
<input value="Login" id=
"temp563149"
 type="button"/>
$(
'#temp563149'
).bind(
'click'
,
     function anonymous(event)
         ws.send(Bert.encodebuf({
              source: Bert.binary(
'temp563149'
),
              pickle: Bert.binary('g2gCaINoAmgEZAA...'),
 
              linked: [ Bert.tuple(Bert.atom(
'user'
),
                                       utf8.toByteArray($(
'#user'
).val())),
                               Bert.tuple(Bert.atom(
'pass'
),
                                       utf8.toByteArray($(
'#pass'
).val())) ]
      }));
});
 
Elements
Plug  your JavaScript controls
                  
           
body() -> [ #textboxlist { },
 
                                                  #grid { },
and talk with them using BERT
 through WebSockets
Actions
    
Client Updates are sent as Actions
which are evaluated as JavaScript strings
    
    
    render_action(Record) -> 
    
            wf:f("alert(\"~s\");",  [wf:js_escape(Record#alert.text)]). 
    
    
        
wf:wire(#alert{text="Hello, World!"}).
    
    
        Element render
could create Actions 
    
    
        Action could include rendered Elements
    
    
    Triggered Action may send Events
JS Compiler  200 LOC 
Preserves Semantics
-compile({parse_transform,shen}).
M = lists:foldl(fun(X, Acc) -> Acc + X end, 0, [1,2,3,4]),
$ erlc sample.erl
  m = [1,2,3,4].reduce( function(x,acc) { return acc + x; }, 0);
 
1. Human Readable Output 
2. No Runtimes 
3. Strong Dynamic Typing 
4. Compact Language, Sane Syntax
   Synrc Shen, JScala                      [1,2,3,4] 
   CoffeeScript, LiveScript                [1,2,4]
   TypeScript                              [1,2,3] 
   Ur, Fay, Roy, Elm, Haxe, F*, WebSharper [3,4]
   ClojureScript                           [4]
   OberonJS                                [1,3,4]
   Wisp                                    [1,2,4]
Why  Erlang to JS  ?
Validation Rules 
Business Rules
Prototyping
Static Content Generation 
Single Environment
SPA  React  ERL
    User = #react{
        render = fun(This) -> #h1{body=value(email,This)} end
            },
    CommentList = #react{
        props = [{data,[]}],
        render = fun(This) -> 
            Users = lists:map(fun(Item) ->
                User#react{props=Item} end, value(data,This)),
            Users
        end },
 
 SPA  React  JS
var user = React.createClass({
        render: function() {
                return React.DOM.h1(null,value('email',this));
       }});
var commentlist = React.createClass({props: {data:[]},
       render: function() {
	       var users = value('data',this).map(function(item) {
	               return user({props: item});
	       });
                return users;
       }});
 
 Erlang AST  CMPTBL
Brace (Joxa /w Erlang AST)
Elixir, Erlang
Synrc Shen JavaScript Compiler
can handle each Erlang language that
compiles to Erlang AST*
 DTL  Sample
main
() ->
    Body = 
wf
:
render
(
body
()
)
,
    [ 
#dtl
{
 file = 
"login"
, 
                
bindings
= [ {
body
, Body }
]
 
} ].
 
body
() ->
    [ 
#span { 
text 
= "Login: " },
      
#textbox 
{ 
id 
= 
user
},
      
#span 
{ 
text 
= 
"Pass: " 
},
      
#password 
{ 
id 
= 
pass
},
 
    
#button 
{ 
    text 
    = "Login"
    , 
postback = 
login
, source = 
[
user
,
pass
]
} ].
 
event
(
login
) -> 
wf
:
user
(
wf
:
q
(
user
)
),
wf
:
redirect
(
).
 
 Idiomatic  Chat  
-module ( chat ).
event (chat) -> wf:send (chat, wf:q (message) ),
body () -> 
    wf:async ( fun() -> loop() end, chat ),
   [ #panel { id=history }, #textbox { id=message }, 
                 #button { postback=chat } ].
loop () -> 
    receive Message -> 
         wf:insert_bottom ( history, #span { text=Message } ),
          wf:flush () end, loop ().
 
N2O in  Elixir 
defmodule Sample.Index do
    def event(:init) do :wf.reg(:room) end
    def event({:chat,pid}) do pid <- {:message, :wf.q(:message)} end
    def event(e) do :wf.info('Unknown Event ~p',[e]) end
    def main() do :dtl.new(file: "index", bindings: [title: "Elixir N2O", body: body()]) end
    def body() do { :ok, pid } = :wf.async(fn() -> loop() end)
                  [ :div.new(id: :history),  
                    :textbox.new(id: :message), 
                    :button.new(id: :send, body: "Chat", postback: {:chat,pid}, source: [:message]) ] end
    def loop() do receive do
            {:message, message} ->   :wf.insert_bottom(:history, [ :span.new(body: message), :br.new() ])
                :wf.flush(:room)
            unknown -> :wf.info('Unknown Looper Message ~p',[unknown]) end
        loop() end  end
 N2O in  Joxa 
(ns lispchat (require erlang joxa-core n2o wf))
(defn+ body() [(n2o/panel   {:id :history})
               (n2o/textbox {:id :message})
               (n2o/button  {:id :send}
                            {:body "Chat"}
                            {:postback :chat}
                            {:source [:message]}) ])
(defn+ main() [(n2o/dtl {:app :n2o_sample}
                        {:file "index"}
                        {:bindings [{:title "Title"} {:body (body)}]})])
(defn+ speak(m) (wf/insert_bottom :history (n2o/span {:body m})))
(defn+ event(body)
    (case body
        (:init (speak ["Hello" (n2o/br)]))
        (:chat (speak [(wf/q :message) (n2o/br)]))))
(defn+ test() (do 
                (event :init)
                (wf/info "hello ~p~n" [(main)])))
  JSON 
proplists <-> JSON 243x
   Library                   Type    Enc    Dec
   -------------             ------- ------ -------
   jsonx                     C NIF   1048   998
   jiffy                     C NIF   2652   2234
   yaws2                     Erlang  14208  12653  Xen 
   jsonerl                   Erlang  14549  14899
   mochijson2                Erlang  16787  16512
   jsx                       Erlang  27188  18333
  JSON PT 
proplists <=> #rec{}
        
-module(users).
-behaviour(n2o_rest).
-compile({parse_transform, n2o_rest}).
-include("users.hrl").
-rest_record(user).
from_json(Proplist, #user{}) -> #user{}.
to_json(Record) -> proplist().
 
 
 REST  Sample
-compile({parse_transform, n2o_rest}).
-include("users.hrl").
-rest_record(user).
init() -> ets:new(users, [public, named_table, {keypos, #user.id}]).
populate(Users) -> ets:insert(users, Users).
exists(Id) -> ets:member(users, wf:to_list(Id)).
get() -> ets:tab2list(users).
get(Id) -> [User] = ets:lookup(users, wf:to_list(Id)), User. 
delete(Id) -> ets:delete(users, wf:to_list(Id)).
post(#user{} = User) -> ets:insert(users, User);
post(Data) -> post(from_json(Data, #user{})).
 KVS  REST API
   POST/PUT kvs:add(#user{}).
         DELETE kvs:remove(user,2).
PUT/PATCH kvs:put(#user{id=2}).
                GET kvs:entries(Feed,user).
                GET kvs:get(user,2).
                GET kvs:all(user).
Events
From JavaScript 
Everything is sent as an Event
               Postback event/1
                    Control control_event/2
                            API api_event/3
Handle events in Erlang...
    
Events Nature
    
        
    
Events are enveloped by BERT
as #ev{}
    
    -record
( ev,
               { name :: api_event | control_event | event | atom () ,
                  payload
    ,
                  trigger
    ,
                  module
     ::
     atom
    () } ).
You can define your own entry points
Postback Events
Create Page Logic with
Postback Events event/1
main() -> [ #button  {  postback =  login } ] .
event(login) -> wf:info("Logged User: ~p", [wf:user()]).
Control Events
Handle Data from Controls with
Control Events control_event/2
render_element( E = #myelement { } ) -> do_render( E ).
control_event(Trigger, Data) -> 
      wf:info("Received Data ~p from JavaScript Control ~p",
             [ Data, Trigger ] ).
 
... when you cteate your own Elements
    
API Events
    
        
    Wire Erlang and JavaScript with
API Events api_event/3
main() -> wf:wire(
#api { name = notify, tag = api3 
} ), [ ].
api_event(Event, Args, Req) ->
 
      wf:info( "Received from JavaScript: ~p", [ Args ] ).
                                         document.notify('Hello from JavaScript').
  Community  
Sources
HTML and TeX Handbook
IRC FreeNode