N2O
    is Fast and Furious ~ 15K
        
                Web Framework for Erlang
            
        
            over Async WebSockets
                
                    with Nitrogen DSL and Templates
                
                supports
                 Zepto or
                 jQuery
REST 
                    included
Composability
N2O consists of 
set of layers 
you could easy tune or replace
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 
Speed Disclaimer
  
              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:
      NGNIX -- 60K 
    
        
Latency
    
Deliver HTML ASAP
 Deffered JavaScript delivery
    after 
    WebSocket
     connection established
    
        
<script>
TransitionProcess = '<0.7780.5>'
</script>
socket.send(["N2O",TransitionProcess]).
Templates
    
    
    
Plug your own fast Template Engine
    
    
                          #'EEX' { file = "template",
    
            
                   
     
         
bindings = [ { title, Title }, 
 
                                    
      
                      { body, Body } ] }
 
    
    
Routes
    
    
    
Redefine you own fast Routing
    
    
        
            
            route(<<"/">>) -> {index, []};
        
    
    
    route(<<"/index">>) -> {index, []};
    
    route(<<"/hello">>) -> {hello, []};
                 
 
    
REST
Develop your REST apps fast
init()          -> ets:new(users, [named_table,{keypos,1}]),
                       ets:insert(users, ?USERS).
get([])        -> ets:foldl(fun(C,Acc) -> [C|Acc] end,[],users);
get(Id)       -> ets:lookup(users,Id).
delete(Id) -> ets:delete(users,Id).
put(User)  -> ets:insert(users,User).
exists(Id)  -> ets:member(users,Id).
 
Mix DSL and DTL
Render both HTML and JavaScript with DSL :
#button { postback = login, source = [ user, pass ] }
 
Or render only JavaScript ..
#button { render = script,
                  id = ElementId,
                     postback = login, 
                                source = [ user, pass ] }
.. when you develop with Templates approach
Actions
    
Client Updates are sent as an Actions
which are a JavaScript Strings for eval
    
    
    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
Elements
Plug  your JavaScript controls
                  
           
body() -> [ #textboxlist { },
 
                                                #grid { },
and talk with them on Erlang
 through WebSockets
Sample Login
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
(
).
 
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())) ]
      }));
});
 
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').
Resources
Sources
HTML and TeX Handbook
Twitter