
<erl>


box(Str) ->
    {'div',[{class,"box"}],
     {pre,[], yaws_api:htmlize(Str)}}.

tbox(T) ->
    box(lists:flatten(io_lib:format("~p",[T]))).


out(A) ->
    [{ssi, "TAB.inc", "%%",[{"yapp_intro", "choosen"}]},
     {ehtml,
      {'div', [{id, "entry"}],

       [{h1, [], "Yaws applications - Yapps"},

        {p, [],
         "Yaws applications, Yapps, are actually ordinary Erlang/OTP "
         "applications with some optional information in their "
         ".app files and the web pages in the priv/docroot directory "
         "as default. The Yaws applications handler takes care of adding, "
         "and removing, the applications into a running server. "
         " When anyone access the server with an URL that matches the path for an "
         " added application, the docroot will be temporarily switched to where the web "
         " pages for that application are located."},

        {h2,[], "Using the application handler"},
        {h3,[], "Installing"},
        {p, [],
        ["The application handler is named just yapp and is located in the "
         "directory yaws/applications/yapp. Yaws itself should have been built first, "
         "then in the yapp directory we do",
         {ol, [],[
          {li,[],{pre,[], "make"}},
          {li,[],[{pre,[], "make docs"}," - if we want documentation"]},
          {li,[],[{pre,[], "make install"}," - unless yaws was installed with make local_install"]}
                  ]
         }]},

        {h3,[], "Setting up yaws.conf"},
        {p,[], "First we include the ebin directory of the yapp handler "
          "application by adding the line "
        },
        box("ebin_dir = /<yaws_root>/{applications,lib}/yapp/ebin"),
        {p,[],
        "The \"applications\" part is used for a local_installed Yaws, and \"lib\""
        " for a real installed one. Then we make sure that the yapp handler "
        " application is started when Yaws is started, by using the runmod directive"},
        box("runmod = yapp"),
        {p,[],
         "For every virtual server that we want to use yapps we add yapp as an "
         "arg_rewrite_mod and set the opaque parameter yapp_server_id to a unique "
         "name."},
        box("
<server myexternalserver>
        port = 8000
        listen = 0.0.0.0
        docroot = /yawsdocrootpath/www
        arg_rewrite_mod = yapp
        <opaque>
           yapp_server_id = edo
        </opaque>
</server>
"),
        {p,[],
         "The web applications that are configured in the Yapp registry will be loaded "
         "into Yaws configuration when the yapp application is started. A prerequisite "
         "is that the applications are found in the Erlang code loader path. There is "
         "also an option to define yapps in yaws.conf for every server directly by using "
         "the opaque parameter bootstrap_yapps = webapp1, webapp2 etc. "},
        {p,[],
         "For instance the yapp handler application (named yapp) is a yapp in itself, "
         "got it?, that provides a web gui to list active yapps and add/remove yapps "
         "from the registry. But since we can not add itself to the registry before it "
         "is added we have to bootstrap into the server when Yaws is started. "},
        box("
<server myinternalserver>
        port = 8001
        listen = 0.0.0.0
        docroot = /docrootpath/www
        arg_rewrite_mod = yapp
        <opaque>
           yapp_server_id = ido
           bootstrap_yapps = yapp
        </opaque>
</server>"
           ),
        {h3,[],"Executing"},
        {p,[],
         "The current default Yapp registry implementation uses Mnesia, we have made "
         "it easy to plug in other future registry implementations by configuring the "
         "yapp.app file, but Mnesia is recommended to be future proof for clustered "
         "application servers. In order to use mnesia one has to prepare a schema, "
         "we start an erlang shell with the same node name as Yaws is using: "},
        {p,[],{pre,[],
               "erl -sname node_name
1> mnesia:create_schema([node()])."}},
        {p,[],["(we can leave out the -sname options, then the mnesia schema name will "
               "be \"nonode@nohost\") then we exit and start yaws with the same name: ",
               {pre,[],"yaws -sname node_name"}]},
        {p,[],["Now we can access the yapp handler web console from a browser with url:",
               {pre,[],"http://myinternalserver:8001/yapp/"}]},

        {h2,[],"Making yapps"},
        {p,[],
         [ "In order to make a \"yapp\" we need to know how to make an ordinary Erlang "
           "application, that is we will need a directory layout as specified by the ",

           {a,[{href, "https://www.erlang.org/doc/design_principles/des_princ.html"     }],
            "design principles"},
           " and a proper appname.app file in the ebin directory. "
           "Yaws itself or yapp are standard applications and can serve as introductionary "
           "examples. "]},
        {h3,[], "Internal paths"},
        {p,[],
         "Making paths to other documents in the same web application using root paths "
         "like href=\"/doc2.html\" will not work since a yapp is always below the top. "
         "Instead use relative paths href=\"doc2.html\" or use the prepath library "
         "function in any .yaws file: href=yapp:prepath(A) ++ \"doc2.html\", "
         "where A is a <code>#arg</code> record."},
        {h3,[],"Appmods"},
        {p,[],
             "The yapp handler takes care of throwing in \"private\" appmods for a yapp "
             "when it is accessed. The appmods modules are put in the applications ebin "
             "directory as any other Erlang module and configured in the .app file "
             "with the the environment variable yapp_appmods. For instance; if we "
             "have a yapp named yappx with root path \"/yappx\" and add: "},
         box("
  {env, [
         {yapp_appmods,[{\"ctrl\",yappx_controller}]}
        ]},
"),
         {p,[],"to the env part in the yappx.app file, an access to the URL "
          "http://servername/yappx/ctrl will cause a call to the "
          "yappx_controller:out/1 function, while http://servername/yappy/ctrl "
          "will not do it. "
         },
        {h3,[],"Opaque variables"},
        {p,[],[
             "In a similar way the yapp handler adds \"private\" opaques for a yapp "
             "with the the environment variable yapp_opaque. "
             "As an example ", {a,[{href,"https://erlyweb.org/"}], "ErlyWeb "},
             "applications uses both appmods and opaques in yaws.conf. These can "
             "be put in the  .app file instead if one makes a yapp of it:"]},
         box("
 {application, myapp1,
 [{description,\"myapp1 is an erlyweb yapp\"},
  {vsn,\"0.1\"},
  {modules,[]},
  {registered, []},
%  {mod,{myapp1_app,[]}}, %% Only needed if the application needs to be started
  {env, [
         {yapp_docroot,\"www\"},
         {yapp_appmods,[{\"erlyweb\",erlyweb}]},
         {yapp_opaque,[{\"appname\",\"myapp1\"}]}
        ]},
  {applications,[kernel,stdlib]}]}.
"),
        {p,[],"Also note that the docroot is www instead of the default priv/docroot in "
              "ErlyWeb applications."},

        {h2,[],"Problems"},
        {p,[],"Embedded ssi directives in ehtml parts do not work."}
       ]
      }
     },
     {ssi, "END2",[],[]}
    ].

</erl>

