Before starting to write your Website, think carefully about the URLs you want to be available. Do you want your services to be bookmarkable (GET) or not (POST)? Do you want them to be attached to a path or to an Eliom identifier sent as parameter (non-attached coservice)? or both (attached coservice)?

Summary of service kinds:

IdentificationExplanation & use
Attached Servicepath (/_/_/)GETServes bookmarkable resources.
POSTServes non-bookmarkable resources. The fallback is a service without POST parameters (for example to come back after bookmarking the page).
Attached Coservicepath (/_/_/) and ?__eliom...= idGETServes bookmarkable resources. Shares its path with its fallback but distinguished by an identifier sent as GET parameter.
POSTServes non-bookmarkable resources. Shares its path with its fallback but distinguished by an identifier sent as POST parameter.
Non-attached Coservice?__eliom...= idGETServices identified only by an identifier sent as GET parameter, and available at any URL path (links or forms pointing at the current URL path). Bookmarkable.
POSTServices identified only by an identifier sent as POST parameter, and available at any URL path (links or forms pointing at the current URL path). Used for example for remote function calls. Not bookmarkable.

And they can serve (among others):

Html5Typed HTML5 pages
AppHTML5 pages belonging to an Eliom client/server application (functor)
Flow5Portions of HTML5 pages.
ActionActions (server side effects) with or without reloading the page
OcamlOCaml value to be sent to a client side OCaml program
StringAny OCaml string (array of byte)
RedirectionRedirection to another service
AnyTo be used to make the service chose what it sends
CustomizeDefining your own registration module (functor)

Remember that new services may be registered dynamically (for example to create a coservice that depends on previous interaction with the user), and you can choose their scope (site, group of sessions, sessions, or client process).

Predefined services

Eliom_service.​external_service to create links of form towards external Web sites

Eliom_service.​static_dir to create links towards static files. Eliom_service.​void_coservice' to create links or forms towards the current URL ...

Server side state

Session data is saved in Eliom references.

let count_ref =
  Eliom_reference.eref ~scope:Eliom_common.session 0
lwt count = Eliom_reference.get count_ref in
Eliom_reference.set count_ref (count + 1)

You can choose a reference to be persistant (value saved on hard drive) or volatile (in memory).


Sessions are relative to a browser, and implemented using browser cookies. But Eliom allows to create Eliom references with other scopes than session:


It is highly recommended to set a session group each time you open a session using one of Eliom_state.​set_service_session_group, Eliom_state.​set_volatile_data_session_group or Eliom_state.​set_persistent_data_session_group. The group name may for example be the user name or her uid. Then consider using scope group instead of session for saving user related data.

Client/server syntax

{client{ ... }}
{server{ ... }} optional
{shared{ ... }} used on both sides
  • Client values can be declared within server side code as {typ{ ... }}
  • Server side variables can be accessed (injected) in client code by prefixing them with an %-sign:
  ... let x = ... in {typ{ ... %x ... }} ...


obj##m : uwhen obj : <m : u prop> Js.t
obj##m <- e : unitwhen obj : <m : u prop> Js.t and e:u
obj##m(e_1, ..., e_n) : uwhen obj : <m : t_1 -> ... -> t_n -> u meth; ..> Js.t and e_i : t_i
jsnew constr (e1, ..., en) : uwhen constr : (t_1 -> ... -> t_n -> u Js.t) Js.constr and e_i : t_i


open Eliom_content.Html5.D
  (head (title (pcdata "")) [])
  (body [h1 ~a:[a_id "toto"; a_class ["blah"; "blih"]] 
          [pcdata "Hallo!"]])))

(you can also use Eliom_tools.​D.​html to ease the creation of the head tag.)

         (Eliom_service.static_dir ())
         ["dir" ; "image.jpg"])

Service parameters

open Eliom_parameter
(int "i" ** (string "s" ** bool "b"))
   (* /path?i=42&s=toto&b=on *)

(set string "s")
   (* /path?s=toto&s=titi&s=bobo *)

(list "l" (int "i"))
   (* /path?l[0]=11&l[1]=2&l[2]=42 *)

(suffix (int "year" ** int "month"))
   (* /path/2012/09 *)

Forms and links

open Eliom_content.Html5.D
a ~service:home_service [pcdata "Home"] ()
   (fun (name, password) ->
       [label ~a:[a_for name] [pcdata "Name: "];
        string_input ~input_type:`Text ~name:name ();
        br ();
          ~a:[a_placeholder "Password"]
        br ();
        string_input ~input_type:`Submit ~value:"Connect" ()
      ]]) ()






let open Lwt_js_events in
Lwt.async (mousedowns canvas
            (fun ev ->
               set_coord ev;
               line ev >>= fun () ->
               Lwt.pick [mousemoves
                           Dom_html.document line;
	                 mouseup Dom_html.document >>=

Map of modules