<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Ocsigen Blog</title>
  <link href="https://ocsigen.github.io/blog-archive/feed.xml" rel="self" />
  <link href="https://ocsigen.github.io" />
  <updated>2026-06-14T19:37:32+00:00</updated>
  <id>https://ocsigen.github.io/</id>
  <author>
    <name>Ocsigen Project</name>
  </author>
  
  <entry>
    <title>Ocsigen Start 2.18 released</title>
    <link href="https://ocsigen.github.io/blog-archive/2020/05/05/os/" />
    <updated>2020-05-05T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2020-05-05:/blog-archive/2020/05/05/os</id>
    <content type="html">&lt;p&gt;New release: Ocsigen Start 2.18&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://ocsigen.org/ocsigen-start/&quot;&gt;Ocsigen Start&lt;/a&gt; is a template for client-server Web and/or mobile app in OCaml or ReasonML.
It contains many standard features like user management, notifications, and many code examples.
Use it to &lt;a href=&quot;https://ocsigen.org/tuto/latest/manual/start&quot;&gt;learn Web/mobile development in OCaml&lt;/a&gt; or as a basis for your app.&lt;/p&gt;

&lt;p&gt;Last features include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Demo of new Ot_tongue widget&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See live examples here:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://ocsigen-1.inria.fr/ocsigen-start/demo/&quot;&gt;See an online demo of the default template&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.osdemo.mobile&quot;&gt;The same, as a mobile app for Android&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Be Sport is based on Ocsigen Start &lt;a href=&quot;https://www.besport.com/feed&quot;&gt;Web&lt;/a&gt; / &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.besport.www.mobile&quot;&gt;Android&lt;/a&gt; / &lt;a href=&quot;https://apps.apple.com/fr/app/be-sport/id1104216922&quot;&gt;iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
  <entry>
    <title>Ocsigen Toolkit 2.7 with new widget Ot_tongue</title>
    <link href="https://ocsigen.github.io/blog-archive/2020/05/04/ot/" />
    <updated>2020-05-04T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2020-05-04:/blog-archive/2020/05/04/ot</id>
    <content type="html">&lt;p&gt;New release: Ocsigen Toolkit 2.7&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://ocsigen.org/ocsigen-toolkit/&quot;&gt;Ocsigen Toolkit&lt;/a&gt; is a widget toolkit for developing mobile and Web apps
with &lt;a href=&quot;https://ocsigen.org/js_of_ocaml/&quot;&gt;js_of_ocaml&lt;/a&gt;. It is designed
to take advantage of &lt;a href=&quot;https://ocsigen.org/eliom/&quot;&gt;Eliom&lt;/a&gt;’s multi-tier programming paradigm.
All widgets can be created either on server or client side.&lt;/p&gt;

&lt;p&gt;This version introduces a new widget: Ot_tongue. It is a swipable panel,
coming from the bottom of the screen (or from another side).
Try it online with a mobile phone in &lt;a href=&quot;http://ocsigen-1.inria.fr/ocsigen-start/demo/demo-tongue&quot;&gt;Ocsigen Start’s demo&lt;/a&gt; or
on the app &lt;a href=&quot;https://beta.monclubpresdechezmoi.com/&quot;&gt;Mon club près de chez moi&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also test it on mobile apps:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.osdemo.mobile&quot;&gt;Ocsigen Start demo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Be Sport &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.besport.www.mobile&quot;&gt;Android&lt;/a&gt; / &lt;a href=&quot;https://apps.apple.com/fr/app/be-sport/id1104216922&quot;&gt;iOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
  <entry>
    <title>Ocsigen Start updated</title>
    <link href="https://ocsigen.github.io/blog-archive/2020/01/20/release/" />
    <updated>2020-01-20T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2020-01-20:/blog-archive/2020/01/20/release</id>
    <content type="html">&lt;p&gt;New release: Ocsigen Start 2.15&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://ocsigen.org/ocsigen-start/&quot;&gt;Ocsigen Start&lt;/a&gt; is a template for client-server Web and/or mobile app in OCaml or ReasonML.
It contains many standard features like user management, notifications, and many code examples.
Use it to &lt;a href=&quot;https://ocsigen.org/tuto/latest/manual/start&quot;&gt;learn Web/mobile development in OCaml&lt;/a&gt; or to quickly create your own Minimum Viable Product.
&lt;a href=&quot;https://ocsigen-1.inria.fr/ocsigen-start/demo/&quot;&gt;See an online demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last features include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Get rid of all remaining Camlp4 code&lt;/li&gt;
  &lt;li&gt;compatibility with OCaml 4.09&lt;/li&gt;
&lt;/ul&gt;

</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
  <entry>
    <title>Ocsigen Start and Ocsigen Server updated</title>
    <link href="https://ocsigen.github.io/blog-archive/2019/07/18/releases/" />
    <updated>2019-07-18T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2019-07-18:/blog-archive/2019/07/18/releases</id>
    <content type="html">&lt;p&gt;New releases:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ocsigen Start 2.2&lt;/li&gt;
  &lt;li&gt;Ocsigen Server 2.13&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://ocsigen.org/ocsigen-start/&quot;&gt;Ocsigen Start&lt;/a&gt; is a template for client-server Web and/or mobile app in OCaml or ReasonML.
It contains many standard features like user management, notifications, and many code examples.
Use it to &lt;a href=&quot;https://ocsigen.org/tuto/latest/manual/start&quot;&gt;learn Web/mobile development in OCaml&lt;/a&gt; or to quickly create your own Minimum Viable Product.
&lt;a href=&quot;https://ocsigen-1.inria.fr/ocsigen-start/demo/&quot;&gt;See an online demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last features include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Demo of “Pull to refresh page” feature (mobile apps)&lt;/li&gt;
  &lt;li&gt;Updated template&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://ocsigen.org/ocsigenserver/&quot;&gt;Ocsigen Server&lt;/a&gt; is a full featured Web Server.&lt;/p&gt;

&lt;p&gt;Last features include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Improve log system&lt;/li&gt;
  &lt;li&gt;Compatibility updates&lt;/li&gt;
&lt;/ul&gt;

</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
  <entry>
    <title>Learn Eliom - Graffiti tutorial updated</title>
    <link href="https://ocsigen.github.io/blog-archive/2019/06/25/graffiti/" />
    <updated>2019-06-25T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2019-06-25:/blog-archive/2019/06/25/graffiti</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://ocsigen.org/tuto/latest/manual/application&quot;&gt;Graffiti tutorial&lt;/a&gt;
explains step by step how to write a &lt;a href=&quot;http://ocsigen.org/graffiti&quot;&gt;multi-user
client-server drawing application&lt;/a&gt; with Eliom.&lt;/p&gt;

&lt;p&gt;It is the best starting point for beginners!&lt;/p&gt;

&lt;p&gt;An updated version of this tutorial is now online, thanks to
&lt;a href=&quot;https://github.com/corentinjuvigny&quot;&gt;corentinjuvigny&lt;/a&gt; and
&lt;a href=&quot;https://github.com/chrismamo1&quot;&gt;chrismamo1&lt;/a&gt;.&lt;/p&gt;

</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
  <entry>
    <title>Ocsigen Start and Ocsigen Toolkit reach 1.0!</title>
    <link href="https://ocsigen.github.io/blog-archive/2017/02/09/start/" />
    <updated>2017-02-09T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2017-02-09:/blog-archive/2017/02/09/start</id>
    <content type="html">&lt;p&gt;The Ocsigen team is very happy to announce the first release of two
major new projects:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://ocsigen.org/ocsigen-start/1.1.0/manual/intro&quot;&gt;Ocsigen Start&lt;/a&gt;: a Web/mobile application skeleton written with
Js_of_ocaml and Eliom. You can use this skeleton as a basis for
your own app, or to learn Web/mobile app development in OCaml.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://ocsigen.org/ocsigen-toolkit/&quot;&gt;Ocsigen Toolkit&lt;/a&gt;: a set of responsive widgets for your mobile
and Web applications in OCaml.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both projects are available via &lt;a href=&quot;https://opam.ocaml.org/&quot;&gt;OPAM&lt;/a&gt; and released under the
LGPL.&lt;/p&gt;

&lt;p&gt;Before installing, you can try out a demo of Ocsigen Start. The demo
is available&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://ocsigen.org/os/demo/&quot;&gt;on the Web&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;via the &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.osdemo.mobile&quot;&gt;Google Play store&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;as an Android &lt;a href=&quot;http://ocsigen.org/ocsigen-start/demo/osdemo.apk&quot;&gt;APK file&lt;/a&gt;; and&lt;/li&gt;
  &lt;li&gt;as an &lt;a href=&quot;http://ocsigen.org/ocsigen-start/demo/osdemo-ios.tgz&quot;&gt;iOS application&lt;/a&gt; to be installed via XCode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ocsigen Start provides the basic features for user management
(registration, activation links, password recovery, etc.), and some
useful libraries.  Remove the parts you don’t need for your own app.&lt;/p&gt;

&lt;p&gt;Ocsigen Start also contains many examples of code: remote procedure
calls, push notifications from the server, reactive pages, database
interaction, session data, internationalization, and some widgets from
Ocsigen Toolkit.&lt;/p&gt;

&lt;p&gt;Ocsigen Toolkit contains common widgets for mobile and Web apps,
written natively in OCaml and specifically designed for Eliom’s
multi-tier and multi-platform programming style.  You can also use
them in client-only Js_of_ocaml programs.  Many new widgets will be
added in future versions.&lt;/p&gt;

&lt;p&gt;Ocsigen Start and Ocsigen Toolkit are developed by the Ocsigen team at
&lt;a href=&quot;https://www.besport.com/&quot;&gt;Be Sport&lt;/a&gt;, at the &lt;a href=&quot;http://www.univ-paris-diderot.fr/&quot;&gt;Paris Diderot University&lt;/a&gt;, and at the
&lt;a href=&quot;https://www.irill.org/&quot;&gt;IRILL&lt;/a&gt;.&lt;/p&gt;

</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
  <entry>
    <title>News on the Eliom language</title>
    <link href="https://ocsigen.github.io/blog-archive/2017/02/06/eliomlang/" />
    <updated>2017-02-06T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2017-02-06:/blog-archive/2017/02/06/eliomlang</id>
    <content type="html">&lt;p&gt;The &lt;a href=&quot;https://ocsigen.org/eliom/&quot;&gt;Eliom framework&lt;/a&gt; is the part of the &lt;a href=&quot;https://ocsigen.org&quot;&gt;ocsigen project&lt;/a&gt; that aims to provide
high level libraries for developing client/server web applications.
It contains a &lt;a href=&quot;https://ocsigen.org/eliom/6.1/manual/ppx-syntax&quot;&gt;language extension&lt;/a&gt; of OCaml that allows implementing both the client
and the server parts of your application as a single program. It also
contains &lt;a href=&quot;https://ocsigen.org/eliom/manual/&quot;&gt;several libraries and utilities&lt;/a&gt; to facilitate web programming.&lt;/p&gt;

&lt;p&gt;The various Ocsigen libraries have received a lot of care
lately. Notably, we have reworked the &lt;a href=&quot;https://ocsigen.github.io/blog-archive/2016/12/12/eliom6/&quot;&gt;service API&lt;/a&gt;, we
have added support for mobile applications and, we have developed
&lt;a href=&quot;https://github.com/ocsigen/ocsigen-start&quot;&gt;ocsigen-start&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today, I will not talk about the ocsigen libraries. I will talk solely about
the language extension.&lt;/p&gt;

&lt;h2 id=&quot;the-current-language-extension&quot;&gt;The current language extension&lt;/h2&gt;

&lt;p&gt;The Eliom language extension extends OCaml with various annotations that
allows specifying where things are to be defined and executed.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* I&apos;m executed on the server *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* I&apos;m declared on the server *)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* But I will be executed on the client! *)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;(* I access values on the server and execute things on the client! *)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The semantics is that the server part is executed first,
then the web page is sent to the client,
then the client part is executed.
See &lt;a href=&quot;https://ocsigen.org/eliom/6.1/manual/ppx-syntax&quot;&gt;the documentation&lt;/a&gt; for detail on the current extension.&lt;/p&gt;

&lt;p&gt;The language extension is currently implemented using a PPX extension and
a custom (and a bit sophisticated) compilation scheme. Note here that I used
the word “language” extension on purpose: this is not a simple syntax extension,
the Eliom language has its own type system, semantics and compilation
scheme, which are extensions of the OCaml ones.&lt;/p&gt;

&lt;p&gt;The current implementation of our language, based on PPX, started to
show its limits in terms of flexibility, convenience and with respect to
the safety guarantees it can provide. This is why I started, as part
of my PhD thesis, to redesign and improve it.&lt;/p&gt;

&lt;h2 id=&quot;formalizing-the-eliom-language&quot;&gt;Formalizing the Eliom language&lt;/h2&gt;

&lt;p&gt;Our first goal was to formalize the Eliom language as an extension of the OCaml
language. Formalizing the language allowed us to better understand its type 
system and semantics, which led to various improvements and bug fixes.
The formalization was &lt;a href=&quot;https://hal.archives-ouvertes.fr/hal-01349774&quot;&gt;published in APLAS 2016&lt;/a&gt;. In this paper,
we present a (rather simple) type system based on two distinct type
universes and the notion of converters, that allows passing values from
the server to the client. We also show that the intuitive semantics
of Eliom, that server code is executed immediately and client code is executed
later in the exact same order it was encountered, does correspond to the
compilation scheme used to slice Eliom programs into a server program and a
client program.&lt;/p&gt;

&lt;p&gt;In the the current implementation, when passing
a server value of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo.t&lt;/code&gt; to the client. It also has type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo.t&lt;/code&gt;,
but the type is now the one available on the client. The actual object
can also be transformed while passing the client/server boundary using
&lt;a href=&quot;https://ocsigen.org/eliom/6.1/manual/clientserver-wrapping&quot;&gt;wrappers&lt;/a&gt;. Unfortunately, this API is very difficult to use, not
flexible and quite unsafe. Instead, we propose to use converters.
Converters can be though as a pair of function: a server serialization
function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ty_server -&amp;gt; string&lt;/code&gt; and a client deserialization function
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string -&amp;gt; ty_client&lt;/code&gt; (the actual implementation will be a bit different to make (de)serializer composable).
The correctness of a converter depends of course on the good behavior of these
two functions, but the language guarantees that they will be used together
properly and each sides will properly respect the types of the converter.&lt;/p&gt;

&lt;p&gt;By using converters, we can provide a convenient programming model and make
Eliom much easier to extend. We demonstrated this with multiple examples in
&lt;a href=&quot;https://hal.archives-ouvertes.fr/hal-01407898&quot;&gt;another paper published in IFL 2016&lt;/a&gt;.
Unfortunately, a proper implementation of converters is only possible
with some form of ad-hoc polymorphism, which involve using modular implicits.&lt;/p&gt;

&lt;h2 id=&quot;implementing-the-eliom-language&quot;&gt;Implementing the Eliom language&lt;/h2&gt;

&lt;p&gt;In order to actually implement all these new things, I started to work on an
extension of the OCaml compiler capable of handling the Eliom language
constructs. Working directly in the compiler has several advantages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We can implement the actual type system of Eliom directly.&lt;/li&gt;
  &lt;li&gt;Easier to extend with new features.&lt;/li&gt;
  &lt;li&gt;Much better error messages.&lt;/li&gt;
  &lt;li&gt;A simpler and faster compilation scheme.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current work-in-progress compiler is available in the repository
&lt;a href=&quot;https://github.com/ocsigen/ocaml-eliom&quot;&gt;ocsigen/ocaml-eliom&lt;/a&gt;. A minimal runtime,
along with various
associated tools are available in &lt;a href=&quot;https://github.com/ocsigen/eliomlang&quot;&gt;ocsigen/eliomlang&lt;/a&gt;.
A (perpetually broken) playground containing an extremely bare-bone
website using eliomlang without the complete framework is available in &lt;a href=&quot;https://github.com/ocsigen/eliomlang-playground&quot;&gt;ocsigen/eliomlang-playground&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, the work on using this new compiler to compile the Eliom framework can be followed via &lt;a href=&quot;https://github.com/ocsigen/eliom/pull/459&quot;&gt;this pull-request&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;going-further&quot;&gt;Going further&lt;/h2&gt;

&lt;p&gt;A more in-depth presentation of the Eliom language can be found &lt;a href=&quot;https://www.irif.fr/~gradanne/papers/eliom/talk_gallium.pdf&quot;&gt;here&lt;/a&gt;.
The &lt;a href=&quot;https://hal.archives-ouvertes.fr/hal-01349774&quot;&gt;APLAS paper&lt;/a&gt; is quite formal and is mostly aimed at people
that want to really understand the minute details of the language. The
&lt;a href=&quot;https://hal.archives-ouvertes.fr/hal-01407898&quot;&gt;IFL paper&lt;/a&gt;, on the other hand, should be accessible to most OCaml programmers
(even those who don’t know Eliom) and demonstrates how to use the new Eliom
constructs to build nice, tierless and typesafe libraries for client/server
web programming.&lt;/p&gt;

&lt;h2 id=&quot;the-future&quot;&gt;The future&lt;/h2&gt;

&lt;p&gt;The work on the Eliom language is far from done. A current area of work
is to extend the OCaml module language to be aware of the Eliom annotations.
A particularly delicate (but promising!) area is the ability to use
Eliom annotations inside functors.
A second area of work is that of stabilizing, debugging and documenting the patched compiler.
Finally, a difficulty raised by this new compiler is that existing build systems,
and in particular ocamlbuild, do not handle the Eliom compilation scheme
very well. Some details on this can be found &lt;a href=&quot;https://github.com/ocsigen/eliom/pull/459&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wish this progress report has awaken your appetite for well-typed
and modular tierless programming in OCaml. I hope I will be able to
share more news in a few months.&lt;/p&gt;

&lt;p&gt;Happy Eliom programming!&lt;/p&gt;
</content>
    <author>
      <name>Gabriel `Drup` Radanne</name>
    </author>
  </entry>
  
  <entry>
    <title>Lwt 2.7.0</title>
    <link href="https://ocsigen.github.io/blog-archive/2017/01/06/lwt.2.7.0/" />
    <updated>2017-01-06T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2017-01-06:/blog-archive/2017/01/06/lwt.2.7.0</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/ocsigen/lwt/releases/tag/2.7.0&quot;&gt;Lwt 2.7.0&lt;/a&gt; was released today. This release aims to (1) improve communication between maintainers and users, and (2) prepare for (minor) &lt;a href=&quot;https://github.com/ocsigen/lwt/issues/308&quot;&gt;breaking changes&lt;/a&gt; to some APIs in Lwt 3.0.0 (planned for April).&lt;/p&gt;

&lt;p&gt;To this end:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Lwt now uses deprecation warnings (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[@deprecated]&lt;/code&gt;), especially for upcoming breaking changes. This required dropping support for OCaml 4.01.&lt;/li&gt;
  &lt;li&gt;There is a gradual, communicative, conservative &lt;a href=&quot;https://github.com/ocsigen/lwt/issues/293&quot;&gt;process&lt;/a&gt; for deprecation and breaking. Maintainers of packages in OPAM get &lt;a href=&quot;https://github.com/ocsigen/lwt/issues/308&quot;&gt;notified proactively&lt;/a&gt;. If you have code not published in OPAM, watch the Lwt repo, recompile the code at least once in three months, or subscribe to the Lwt &lt;a href=&quot;https://github.com/ocsigen/lwt/issues/309&quot;&gt;announcements issue&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;If a planned breaking change is a bad idea, please let the maintainers know when you see the warning.&lt;/li&gt;
  &lt;li&gt;Lwt now uses &lt;a href=&quot;http://semver.org/&quot;&gt;semantic versioning&lt;/a&gt;. The major version will grow slowly but steadily, but this does not mean that the whole API is being redesigned or broken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are releasing a package to OPAM that depends on Lwt, it is not
recommended to constrain Lwt to its current major version. A major
release of Lwt will break only a few APIs, and your package is likely
not to be affected – if it is, you will be notified. You may, however,
wish to constrain Lwt to a major version in your private or production
code.&lt;/p&gt;

&lt;h3 id=&quot;additional-changes&quot;&gt;Additional changes&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;The main OPAM package &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lwt&lt;/code&gt; is getting rid of some optional dependencies in 3.0.0, which are now installable through separate OPAM packages &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lwt_ssl&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lwt_glib&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lwt_react&lt;/code&gt;. This is to reduce recompilation of Lwt when installing OPAM packages &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lablgtk&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Values of types &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a Lwt.t&lt;/code&gt; are now called &lt;em&gt;promises&lt;/em&gt; rather than &lt;em&gt;threads&lt;/em&gt;. This should eliminate a lot of confusion for beginners.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lwt 2.7.0 also has a number of more ordinary changes, such as bug fixes
and the addition of bindings to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;writev&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readv&lt;/code&gt;. See the &lt;a href=&quot;https://github.com/ocsigen/lwt/releases/tag/2.7.0&quot;&gt;full
changelog&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;future-work&quot;&gt;Future work&lt;/h3&gt;

&lt;p&gt;I am working on an all-new manual, including fully rewritten API documentation with examples. It should be ready towards the end of winter.&lt;/p&gt;

&lt;p&gt;My hope is that all the above allows Lwt to be taken progressively into the future, at the same time making development more open and more humane.&lt;/p&gt;

&lt;p&gt;Discuss &lt;a href=&quot;https://www.reddit.com/r/ocaml/comments/5mdl0g/lwt_270_is_out_ocamls_promise_library_featuring/&quot;&gt;on reddit&lt;/a&gt;!&lt;/p&gt;

</content>
    <author>
      <name>Anton Bachin</name>
    </author>
  </entry>
  
  <entry>
    <title>Eliom 6.0&#58; mobile and Web apps in OCaml</title>
    <link href="https://ocsigen.github.io/blog-archive/2016/12/12/eliom6/" />
    <updated>2016-12-12T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2016-12-12:/blog-archive/2016/12/12/eliom6</id>
    <content type="html">&lt;p&gt;We are very happy to announce the release of &lt;a href=&quot;https://github.com/ocsigen/eliom/releases/tag/6.0.0&quot;&gt;Ocsigen Eliom 6.0&lt;/a&gt;,
which follows the recent releases of
&lt;a href=&quot;https://github.com/ocsigen/ocsigenserver/releases/tag/2.8&quot;&gt;Ocsigen Server 2.8&lt;/a&gt;
and &lt;a href=&quot;https://github.com/ocsigen/js_of_ocaml/releases/tag/2.8.3&quot;&gt;Ocsigen Js_of_ocaml 2.8.x&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;New features include a friendlier service API that retains the
expressive power of our service system. Additionally, Eliom can now be
used to build cross-platform Web/mobile applications (Android, iOS, …).&lt;/p&gt;

&lt;h2 id=&quot;what-is-eliom&quot;&gt;What is Eliom?&lt;/h2&gt;

&lt;p&gt;Eliom is a framework for developing client/server web
applications. Both the server and the client parts of the application
are written in OCaml, as a single program. Communication between
server and client is straightforward, e.g., one can just call a
server-side function from client-side code.&lt;/p&gt;

&lt;p&gt;Eliom makes extensive use of the OCaml language features. It provides
advanced functionality like a powerful session mechanism and support
for functional reactive Web pages.&lt;/p&gt;

&lt;h2 id=&quot;friendly-service-apis&quot;&gt;Friendly service APIs&lt;/h2&gt;

&lt;p&gt;Services are a key concept in Eliom, used for building the pages that
are sent to the user, for accessing server-side data, for performing
various actions, and so on. Eliom 6.0 provides a friendlier API for
defining and registering services, thus making Eliom more
approachable.&lt;/p&gt;

&lt;p&gt;The new API makes extensive use of OCaml’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Generalized_algebraic_data_type&quot;&gt;GADTs&lt;/a&gt;, and provides
a single entry-point that supports most kinds of services
(&lt;a href=&quot;https://ocsigen.org/eliom/api/server/Eliom_service#VALcreate&quot;&gt;Eliom_service.create&lt;/a&gt;). For more information, refer
to the &lt;a href=&quot;https://ocsigen.org/eliom/dev/manual/server-services&quot;&gt;Eliom manual&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;mobile-applications&quot;&gt;Mobile applications&lt;/h2&gt;

&lt;p&gt;Eliom 6.0 allows one to build applications for multiple mobile
platforms (including iOS, Android, and Windows) with the same codebase
as for a Web application, and following standard Eliom idioms.&lt;/p&gt;

&lt;p&gt;To achieve this, we have made available the Eliom service APIs
&lt;a href=&quot;https://ocsigen.org/eliom/manual/clientserver-services&quot;&gt;on the client&lt;/a&gt;. Thus, the user interface can be
produced directly on the mobile device, with remote calls only when
absolutely necessary.&lt;/p&gt;

&lt;p&gt;To build an Eliom 6.0 mobile application easily, we recommend that you
use our soon-to-be-released &lt;a href=&quot;https://github.com/ocsigen/ocsigen-start&quot;&gt;Ocsigen Start&lt;/a&gt; project, which
provides a mobile-ready template application
(&lt;a href=&quot;https://ocsigen.org/tuto/manual/mobile&quot;&gt;walkthrough&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;compatibility&quot;&gt;Compatibility&lt;/h2&gt;

&lt;p&gt;Eliom 6.0 supports the last 3 major versions of OCaml (4.02 up to
4.04). Additionally, Eliom is compatible with and builds on the
latest Ocsigen releases, including
&lt;a href=&quot;https://github.com/ocsigen/ocsigenserver/releases/tag/2.8&quot;&gt;Ocsigen Server 2.8&lt;/a&gt;,
&lt;a href=&quot;https://github.com/ocsigen/js_of_ocaml/releases/tag/2.8.3&quot;&gt;Js_of_ocaml 2.8.x&lt;/a&gt;, and &lt;a href=&quot;https://github.com/ocsigen/tyxml/releases/tag/4.0.1&quot;&gt;TyXML 4.0.x&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;future&quot;&gt;Future&lt;/h2&gt;

&lt;p&gt;The Ocsigen team is busy working on new features. Notably, we are
developing an &lt;a href=&quot;https://github.com/ocsigen/ocaml-eliom&quot;&gt;OCaml compiler&lt;/a&gt; specifically tuned for
Eliom. Additionally, we are planning a transition to the
&lt;a href=&quot;https://github.com/mirage/ocaml-cohttp&quot;&gt;Cohttp&lt;/a&gt; HTTP backend.&lt;/p&gt;

&lt;h2 id=&quot;support&quot;&gt;Support&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://ocsigen.org/eliom/Eliom60&quot;&gt;Migration guide&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/eliom/issues&quot;&gt;Issue tracker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sympa.inria.fr/sympa/info/ocsigen&quot;&gt;Mailing list&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;IRC: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#ocsigen&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc.freenode.net&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
  <entry>
    <title>TyXML 4.0.0</title>
    <link href="https://ocsigen.github.io/blog-archive/2016/05/20/tyxml4/" />
    <updated>2016-05-20T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2016-05-20:/blog-archive/2016/05/20/tyxml4</id>
    <content type="html">&lt;p&gt;It is with great pleasure that we are announcing the release of &lt;a href=&quot;https://github.com/ocsigen/tyxml/releases/tag/4.0.0&quot;&gt;TyXML 4.0.0&lt;/a&gt;. The major features of this new release are a new PPX syntax extension that allows to use the standard HTML syntax and an improved user experience for both old and new TyXML users.&lt;/p&gt;

&lt;h2 id=&quot;what-is-tyxml-&quot;&gt;What is TyXML ?&lt;/h2&gt;

&lt;p&gt;TyXML is a library for building statically correct HTML5 and SVG documents.
It provides a set of combinators which use the OCaml type system to ensure the validity of the generated document. TyXML’s combinators can be used to build textual HTML and SVG, but also DOM trees or reactive interfaces, using &lt;a href=&quot;https://ocsigen.org/eliom/manual/clientserver-html&quot;&gt;Eliom&lt;/a&gt; and &lt;a href=&quot;https://ocsigen.org/js_of_ocaml/api/Tyxml_js&quot;&gt;Js_of_ocaml&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;new-tyxml-manual-and-improved-documentation&quot;&gt;New TyXML manual and improved documentation&lt;/h2&gt;

&lt;p&gt;A new TyXML manual is now available &lt;a href=&quot;https://ocsigen.org/tyxml/4.0/manual/intro&quot;&gt;here&lt;/a&gt;. The documentation of the various TyXML modules was also improved. Do not hesitate to provide feedback via &lt;a href=&quot;https://github.com/ocsigen/tyxml/issues&quot;&gt;our bug tracker&lt;/a&gt;!&lt;/p&gt;

&lt;h2 id=&quot;html-syntax-with-the-new-ppx-syntax-extension&quot;&gt;HTML syntax with the new PPX syntax extension&lt;/h2&gt;

&lt;p&gt;It is now possible to use the standard HTML syntax:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Tyxml&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_ocaml&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;a href=&apos;ocaml.org&apos;&amp;gt;OCaml!&amp;lt;/a&amp;gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It supports insertion of OCaml code inside the HTML and can be used with all the TyXML modules (such as &lt;a href=&quot;https://ocsigen.org/js_of_ocaml/api/Tyxml_js&quot;&gt;Js_of_ocaml&lt;/a&gt; and &lt;a href=&quot;https://ocsigen.org/eliom/manual/clientserver-html&quot;&gt;Eliom&lt;/a&gt;) and with SVG. A complete overview can be found &lt;a href=&quot;https://ocsigen.org/tyxml/4.0/manual/ppx&quot;&gt;in the manual&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This new PPX syntax extension leverages the (awesome) &lt;a href=&quot;https://github.com/aantron/markup.ml&quot;&gt;Markup.ml&lt;/a&gt; library and was contributed by &lt;a href=&quot;https://github.com/aantron&quot;&gt;Anton Bachin&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;others&quot;&gt;Others&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Toplevel printers are now available for the base HTML and SVG implementations:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Tyxml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Oh!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Tyxml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Oh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The HTML and SVG combinators have received numerous improvements to make them more consistent and easier to use. This means that several modules and functions have been renamed and some types have been changed, which breaks compatibility with previous TyXML versions.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A healthy amount of new elements and attributes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The full changelog is available &lt;a href=&quot;https://github.com/ocsigen/tyxml/releases/tag/4.0.0&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;compatibility&quot;&gt;Compatibility&lt;/h2&gt;

&lt;p&gt;This new version breaks compatibility. Compatible versions of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt; and Eliom are available in the respective &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; branches.
A compatible &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt; version should be released shortly™.&lt;/p&gt;

&lt;p&gt;TyXML 4.0.0 is only available on OCaml &amp;gt;= 4.02.&lt;/p&gt;

&lt;h2 id=&quot;the-future&quot;&gt;The future&lt;/h2&gt;

&lt;p&gt;While nothing is decided yet, some work has already started to enhance the syntax extension with &lt;a href=&quot;https://github.com/ocsigen/tyxml/pull/128&quot;&gt;type safe templating&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy HTML and SVG hacking!&lt;/p&gt;
</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
  <entry>
    <title>Ocsigen&#58; step by step tutorial for client-server Web application (2/2)</title>
    <link href="https://ocsigen.github.io/blog-archive/2016/03/30/tuto-graffiti2/" />
    <updated>2016-03-30T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2016-03-30:/blog-archive/2016/03/30/tuto-graffiti2</id>
    <content type="html">&lt;p&gt;This is the end of the tutorial about writing a collaborative Web drawing
in OCaml. Have a look at
&lt;a href=&quot;http://ocsigen.org/tuto/manual/application&quot;&gt;the full tutorial&lt;/a&gt;
if you haven’t read the first part or if you want a version with full
colors and links.&lt;/p&gt;

&lt;p&gt;In the last part, we’ve seen how to create a client-server Web application
in OCaml. The server generates a Web page and sends it together with an
OCaml program (compiled to JavaScript) to the browser.&lt;/p&gt;

&lt;p&gt;We will now see how to draw on the canvas, program mouse events with Lwt,
and do server to client communication on a bus.&lt;/p&gt;

&lt;h2 id=&quot;collaborative-drawing-application&quot;&gt;Collaborative drawing application&lt;/h2&gt;

&lt;h3 id=&quot;drawing-on-a-canvas&quot;&gt;Drawing on a canvas&lt;/h3&gt;

&lt;p&gt;We now want to draw something on the page using an HTML5 canvas. The
drawing primitive is defined in the client-side function called
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw&lt;/code&gt; that just draws a line between two given points in a canvas.&lt;/p&gt;

&lt;p&gt;To start our collaborative drawing application, we define another
client-side function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init_client&lt;/code&gt;, which just draws a single
line for now.&lt;/p&gt;

&lt;p&gt;Here is the (full) new version of the program:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;(* Modules opened in the shared-section are available in client-
     and server-code *)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Eliom_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Lwt&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graffiti_app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;graffiti&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;700&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;CSS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_of_t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;CSS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rgb&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strokeStyle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineWidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;beginPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;moveTo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineTo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stroke&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canvas_elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;canvas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_width&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_height&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;your browser doesn&apos;t support canvas&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;canvas_elt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init_client&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canvas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Eliom_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_canvas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;canvas_elt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getContext&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_2d_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineCap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Graffiti_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;c&quot;&gt;(* Cf. section &quot;Client side side-effects on the server&quot; *)&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init_client&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;javascript-datatypes-in-ocaml&quot;&gt;JavaScript datatypes in OCaml&lt;/h3&gt;

&lt;p&gt;Here we use the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Js.string&lt;/code&gt;
  from Js_of_ocaml’s library to convert an OCaml string
  into a JS string.&lt;/p&gt;

&lt;h3 id=&quot;client-side-side-effect-on-the-server&quot;&gt;Client side side-effect on the server&lt;/h3&gt;

&lt;p&gt;What sounds a bit weird at first, is a very convenient practice for
  processing request in a client-server application: If a client value
  is created while processing a request, it will be evaluated on the
  client once it receives the response and the document is created;
  the corresponding side effects are then executed.
  For example, the line&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init_client&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;creates a client value for the sole purpose of performing side
  effects on the client.  The client value can also be named (as
  opposed to ignored via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;), thus enabling server-side
  manipulation of client-side values (see below).&lt;/p&gt;

&lt;h3 id=&quot;single-user-drawing-application&quot;&gt;Single user drawing application&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;(Lwt, Mouse events with Lwt)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We now want to catch mouse events to draw lines with the mouse like
with the &lt;em&gt;brush&lt;/em&gt; tools of any classical drawing application. One
solution would be to mimic typical JavaScript code in OCaml; for
example by using function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dom_events.listen&lt;/code&gt;
that is the Js_of_ocaml’s equivalent of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addEventListener&lt;/code&gt;. However, this solution is at least as verbose
as the JavaScript equivalent, hence not satisfactory. Js_of_ocaml’s
library provides a much easier way to do that with the help of Lwt.&lt;/p&gt;

&lt;p&gt;Replace the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init_client&lt;/code&gt; of the previous example by the
following piece of code, then compile and draw!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init_client&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canvas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Eliom_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_canvas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;canvas_elt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getContext&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_2d_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineCap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set_coord&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elementClientPosition&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canvas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clientX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clientY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y0&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_line&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;set_coord&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;oldx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compute_line&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;

  &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Lwt_js_events&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mousedowns&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canvas&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;set_coord&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
           &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pick&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mousemoves&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	      &lt;span class=&quot;n&quot;&gt;mouseup&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We use two references &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; to record the last mouse
position.  The function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_coord&lt;/code&gt; updates those references from
mouse event data.  The function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_line&lt;/code&gt; computes the
coordinates of a line from the initial (old) coordinates to the new
coordinates–the event data sent as a parameter.&lt;/p&gt;

&lt;p&gt;The last four lines of code implement the event-handling loop.  They
can be read as follows: for each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mousedown&lt;/code&gt; event on the canvas,
do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_coord&lt;/code&gt;, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line&lt;/code&gt; (this will draw a dot), then
behave as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;first&lt;/code&gt; of the two following lines that terminates:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;For each mousemove event on the document, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line&lt;/code&gt; (never
terminates)&lt;/li&gt;
  &lt;li&gt;If there is a mouseup event on the document, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;more-on-lwt&quot;&gt;More on Lwt&lt;/h3&gt;

&lt;p&gt;Functions in Eliom and Js_of_ocaml which do not implement just a
computation or direct side effect, but rather wait for user activity,
or file system access, or need a unforeseeable amount of time to return
are defined &lt;em&gt;with Lwt&lt;/em&gt;; instead of returning a value of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;
they return an Lwt thread of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a Lwt.t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The only way to use the result of such functions (ones that return
values in the &lt;em&gt;Lwt monad&lt;/em&gt;), is to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.bind&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It is convenient to define an infix operator like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then the code&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;is conceptually similar to&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;but only for functions returning a value in the Lwt monad.&lt;/p&gt;

&lt;p&gt;For more clarity, there is a syntax extension for Lwt, defining
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let%lwt&lt;/code&gt; to be used instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; for Lwt functions:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lwt&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.return&lt;/code&gt; creates a terminated thread from a value: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.return : &apos;a -&amp;gt; &apos;a Lwt.t&lt;/code&gt; Use it when you must
return something in the Lwt monad (for example in a service handler,
or often after a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.bind&lt;/code&gt;).&lt;/p&gt;

&lt;h4 id=&quot;why-lwt&quot;&gt;Why Lwt?&lt;/h4&gt;

&lt;p&gt;An Eliom application is a cooperative program, as the server must be
able to handle several requests at the same time.  Ocsigen is using
cooperative threading instead of the more widely used preemptive
threading paradigm. It means that no scheduler will interrupt your
functions whenever it wants. Switching from one thread to another is
done only when there is a &lt;em&gt;cooperation point&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We will use the term &lt;em&gt;cooperative functions&lt;/em&gt; to identify functions
implemented in cooperative way, that is: if something takes
(potentially a long) time to complete (for example reading a value
from a database), they insert a cooperation point to let other threads
run.  Cooperative functions return a value in the Lwt monad
(that is, a value of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a Lwt.t&lt;/code&gt; for some type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.bind&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.return&lt;/code&gt; do not introduce cooperation points.&lt;/p&gt;

&lt;p&gt;In our example, the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events.mouseup&lt;/code&gt; may introduce
a cooperation point, because it is unforeseeable when this event
happens. That’s why it returns a value in the Lwt monad.&lt;/p&gt;

&lt;p&gt;Using cooperative threads has a huge advantage: given that you know
precisely where the cooperation points are, &lt;em&gt;you need very few
mutexes&lt;/em&gt; and you have &lt;em&gt;very low risk of deadlocks&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;Using Lwt is very easy and does not cause trouble, provided you never
use &lt;em&gt;blocking functions&lt;/em&gt; (non-cooperative functions).  &lt;em&gt;Blocking
functions can cause the entre server to hang!&lt;/em&gt; Remember:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use the functions from module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_unix&lt;/code&gt; instead of module
 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unix&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;Use cooperative database libraries (like PG’Ocaml for Lwt),&lt;/li&gt;
  &lt;li&gt;If you want to use a non-cooperative function, detach it in another
preemptive thread using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_preemptive.detach&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;If you want to launch a long-running computation, manually insert
cooperation points using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_unix.yield&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.bind&lt;/code&gt; does not introduce any cooperation point.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;handling-events-with-lwt&quot;&gt;Handling events with Lwt&lt;/h3&gt;

&lt;p&gt;The module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events&lt;/code&gt;
  allows easily defining event listeners using Lwt.  For example,
  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events.click&lt;/code&gt; takes a
  DOM element and returns an Lwt thread that will wait until a click
  occures on this element.&lt;/p&gt;

&lt;p&gt;Functions with an ending “s” (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events.clicks&lt;/code&gt;,
  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events.mousedowns&lt;/code&gt;, …) start again waiting after the
  handler terminates.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.pick&lt;/code&gt; behaves as the first thread
  in the list to terminate, and cancels the others.&lt;/p&gt;

&lt;h2 id=&quot;collaborative-drawing-application-1&quot;&gt;Collaborative drawing application&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;(Client server communication)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to see what other users are drawing, we now want to do the
following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Send the coordinates to the server when the user draw a line, then&lt;/li&gt;
  &lt;li&gt;Dispatch the coordinates to all connected users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We first declare a type, shared by the server and the client,
describing the color (as RGB values) and coordinates of drawn lines.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We annotate the type declaration with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[@@deriving json]&lt;/code&gt; to allow
type-safe deserialization of this type. Eliom forces you to use this
in order to avoid server crashes if a client sends corrupted data.
This is defined using a JSON plugin for
&lt;a href=&quot;https://github.com/whitequark/ppx_deriving&quot;&gt;ppx_deriving&lt;/a&gt;, which you
need to install. You need to do that for each type of data sent by the
client to the server.  This annotation can only be added on types
containing exclusively basic types, or other types annotated with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[@@deriving json]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we create an Eliom bus to broadcast drawing events to all client
with the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_bus.create&lt;/code&gt;.
This function take as parameter the type of
values carried by the bus.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Eliom_bus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;derive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To write draw commands into the bus, we just replace the function
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init_client&lt;/code&gt; by:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_line&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Eliom_bus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bus&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally, to interpret the draw orders read on the bus, we add the
following line at the end of function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init_client&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;  &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_bus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now you can try the program using two browser windows to see that the
lines are drawn on both windows.&lt;/p&gt;

&lt;h3 id=&quot;communication-channels&quot;&gt;Communication channels&lt;/h3&gt;

&lt;p&gt;Eliom provides multiple ways for the server to send unsolicited data
  to the client:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_bus.t&lt;/code&gt; are broadcasting channels where
client and server can participate (see also «a_api project=”eliom”
subproject=”client” | type Eliom_bus.t » in the client
API).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_react&lt;/code&gt; allows sending
&lt;a href=&quot;http://erratique.ch/software/react/doc/React&quot;&gt;React events&lt;/a&gt; from
the server to the client, and conversely.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_comet.Channel.t&lt;/code&gt; are one-way communication channels
allowing finer-grained control. It allows sending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_stream&lt;/code&gt;
to the client.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_react&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_bus&lt;/code&gt; are implemented over
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_coment&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;It is possible to control the idle behaviour with module
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_comet.Configuration&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;color-and-size-of-the-brush&quot;&gt;Color and size of the brush&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;(Widgets with Ocsigen-widgets)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this section, we add a color picker and slider to choose the size
of the brush. For the colorpicker we used a widget available in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ocsigen-widgets&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To install Ocsigen widgets, do:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;opam pin add ocsigen-widgets https://github.com/ocsigen/ocsigen-widgets.git
opam install ocsigen-widgets
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile.options&lt;/code&gt;, created by Eliom’s distillery, add
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocsigen-widgets.client&lt;/code&gt; to the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLIENT_PACKAGES&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CLIENT_PACKAGES := ... ocsigen-widgets.client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To create the widget, we add the following code in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init_client&lt;/code&gt; immediately after canvas configuration:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* Color of the brush *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colorpicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ow_color_picker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;150&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;Ow_color_picker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append_at&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colorpicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;Ow_color_picker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init_handler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colorpicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We subsequently add a simple HTML5 slider to change the size of the
brush. Near the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canvas_elt&lt;/code&gt; definition, simply add the following
code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_id&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;slider&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_input_min&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.;&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_input_max&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Range&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Form.int&lt;/code&gt; is a typing information telling that this input takes
an integer value. This kind of input can only be associated to
services taking an integer as parameter.&lt;/p&gt;

&lt;p&gt;We then add the slider to the page body, as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;canvas_elt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To change the size and the color of the brush, we replace the last
line of the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compute_line&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init_client&lt;/code&gt; by:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rgb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ow_color_picker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_rgb&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colorpicker&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size_slider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Eliom_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slider&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int_of_string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size_slider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rgb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;oldx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally, we need to add a stylesheet in the headers of our page. To
easily create the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; HTML element, we use the function
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_tools.F.head&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_tools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;graffiti.css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];]&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;js&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canvas_elt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You need to install the corresponding stylesheets and images into your
project. The stylesheet files should go to the directory
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static/css&lt;/code&gt;.
File &lt;a href=&quot;http://ocsigen.org/tuto/files/tutorial/static/css/graffiti.css&quot;&gt;graffiti.css&lt;/a&gt; is a custom-made CSS file.&lt;/p&gt;

&lt;p&gt;You can then test your application (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make test.byte&lt;/code&gt;).&lt;/p&gt;

&lt;h3 id=&quot;ocsigen-widgets&quot;&gt;Ocsigen-widgets&lt;/h3&gt;

&lt;p&gt;Ocsigen-widgets is a Js_of_ocaml library providing useful widgets
  for your Eliom applications. You can use it for building complex
  user interfaces.&lt;/p&gt;

&lt;h2 id=&quot;sending-the-initial-image&quot;&gt;Sending the initial image&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;(Services sending other data types)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To finish the first part of the tutorial, we want to save the current
drawing on server side and send the current image when a new user
arrives. To do that, we will use the
&lt;a href=&quot;http://www.cairographics.org/cairo-ocaml/&quot;&gt;Cairo binding&lt;/a&gt; for OCaml.&lt;/p&gt;

&lt;p&gt;For using Cairo, first, make sure that it is installed (it is
available as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cairo2&lt;/code&gt; via OPAM). Second, add it to the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SERVER_PACKAGES&lt;/code&gt; in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile.options&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SERVER_PACKAGES := ... cairo2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw_server&lt;/code&gt; function below is the equivalent of the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw&lt;/code&gt; function on the server side and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image_string&lt;/code&gt;
function outputs the PNG image in a string.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;draw_server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;surface&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ARGB32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;surface&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rgb_floats_from_ints&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rgb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;(* Set thickness of brush *)&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_line_width&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_line_join&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;JOIN_ROUND&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_line_cap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ROUND&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;rgb_floats_from_ints&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rgb&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_source_rgb&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move_to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line_to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;(* Apply the ink *)&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stroke&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
     &lt;span class=&quot;c&quot;&gt;(* Output a PNG in a string *)&lt;/span&gt;
     &lt;span class=&quot;nn&quot;&gt;Cairo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;PNG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write_to_stream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;surface&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
     &lt;span class=&quot;nn&quot;&gt;Buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;draw_server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_bus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We also define a service that sends the picture:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageservice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_string&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;eliom_registration&quot;&gt;Eliom_registration&lt;/h3&gt;

&lt;p&gt;The module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration&lt;/code&gt; defines several modules with
  registration functions for a variety of data types. We have already
  seen &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.Html5&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.App&lt;/code&gt;.
  The module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.String&lt;/code&gt; sends arbitrary byte output
  (represented by an OCaml string). The handler function must return
  a pair consisting of the content and the content-type.&lt;/p&gt;

&lt;p&gt;There are also several other output modules, for example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.File&lt;/code&gt; to send static files&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.Redirection&lt;/code&gt; to create a redirection towards another page&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.Any&lt;/code&gt; to create services that decide late what
they want to send&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.Ocaml&lt;/code&gt; to send any OCaml data to be used in a
client side program&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.Action&lt;/code&gt; to create service with no output
(the handler function just performs a side effect on the server)
and reload the current page (or not). We will see an example of actions
in the next chapter.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;loading-the-initial-image&quot;&gt;Loading the initial image&lt;/h3&gt;

&lt;p&gt;We now want to load the initial image once the canvas is created.  Add
the following lines just between the creation of the canvas context and the
creation of the slider:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* The initial image: *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_img&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;canvas&quot;&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageservice&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drawImage&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You are then ready to try your graffiti-application by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make test.byte&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note, that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile&lt;/code&gt; from the distillery automatically adds
the packages defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SERVER_PACKAGES&lt;/code&gt; as an extension in your
configuration file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;local/etc/graffiti/graffiti-test.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;extension findlib-package=&quot;cairo2&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
    <author>
      <name>Ocsigen team</name>
    </author>
  </entry>
  
  <entry>
    <title>Ocsigen&#58; step by step tutorial for client-server Web application (1/2)</title>
    <link href="https://ocsigen.github.io/blog-archive/2016/03/15/tuto-graffiti1/" />
    <updated>2016-03-15T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2016-03-15:/blog-archive/2016/03/15/tuto-graffiti1</id>
    <content type="html">&lt;p&gt;This post (and the following one) is a step by step tutorial about
client-server Web applications in OCaml. You can find the full
tutorial &lt;a href=&quot;http://ocsigen.org/tuto/manual/application&quot;&gt;here&lt;/a&gt;. It
introduces the basics of Web programming with OCaml: type-checking
HTML, defining services, using lightweight threads, writing a
client-server program …&lt;/p&gt;

&lt;p&gt;We will write a collaborative drawing application. It is a
client-server Web application displaying an area where users can draw
using the mouse, and see what other users are drawing at the same time
and in real-time.&lt;/p&gt;

&lt;p&gt;The final eliom code is available for download
&lt;a href=&quot;https://github.com/ocsigen/graffiti/tree/master/simple&quot;&gt;on github&lt;/a&gt;.
&lt;a href=&quot;https://github.com/ocsigen/graffiti/releases/tag/eliom-5.0&quot;&gt;Git tag eliom-5.0&lt;/a&gt;
has been tested against Eliom 5.0.&lt;/p&gt;

&lt;p&gt;The application is running online &lt;a href=&quot;http://ocsigen.org/graffiti/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;basics&quot;&gt;Basics&lt;/h2&gt;

&lt;p&gt;To get started, we recommend using Eliom’s distillery, a program which
creates scaffolds for Eliom projects. The following command creates a
very simple project called graffiti in the directory graffiti:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ eliom-distillery -name graffiti -template basic.ppx -target-directory graffiti
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;my-first-page&quot;&gt;My first page&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;(Services, Configuration file, Static validation of HTML)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our web application consists of a single page for now. Let’s start by
creating a very basic page. We define the service that will implement
this page by the following declaration:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Eliom_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* provides functions to create HTML nodes *)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;graff&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Page title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you are using eliom-distillery just replace the content of the
eliom-file by the above lines and run&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make test.byte
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will compile your application and run ocsigenserver on it. (Refer
to the manual on how to compile your project “by hand”.)&lt;/p&gt;

&lt;p&gt;Your page is now available at URL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:8080/graff&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;services&quot;&gt;Services&lt;/h3&gt;

&lt;p&gt;Unlike typical web programming techniques (CGI, PHP, …), with Eliom you do not need to write one file per URL. The application can be split into multiple files as per the developer’s style. What matters is that you eventually produce a single module (*.cmo or *.cma) for the whole website.&lt;/p&gt;

&lt;p&gt;Module
&lt;a href=&quot;http://ocsigen.org/eliom/5.0/api/client/Eliom_service&quot;&gt;Eliom_service&lt;/a&gt;
allows to create new entry points to your web site, called services.
In general, services are attached to a URL and generate a web page.
Services are represented by OCaml values, through which you must
register a function that will generate a page.&lt;/p&gt;

&lt;p&gt;Parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~path&lt;/code&gt; corresponds to the URL where you want to attach your service. It is a list of strings. The value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&quot;foo&quot;; &quot;bar&quot;]&lt;/code&gt; corresponds to URL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo/bar&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&quot;dir&quot;; &quot;&quot;]&lt;/code&gt; corresponds to URL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dir/&lt;/code&gt; (that is: the default page of the directory dir).&lt;/p&gt;

&lt;h3 id=&quot;configuration-file&quot;&gt;Configuration file&lt;/h3&gt;

&lt;p&gt;In the directory of the project created by the Eliom-distillery, you can find the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;graffiti.conf.in&lt;/code&gt;. This file is used in conjunction with the variables in Makefile.options to generate the ocsigenserver configuration file.&lt;/p&gt;

&lt;p&gt;Once you start up your application via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make test.byte&lt;/code&gt;, the configuration file becomes available at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;local/etc/graffiti/graffiti-test.conf&lt;/code&gt;. It contains various directives for Ocsigen server (port, log files, extensions to be loaded, etc.), taken from Makefile.options, and something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;host&amp;gt;
  &amp;lt;static dir=&quot;static&quot; /&amp;gt;
  &amp;lt;eliommodule module=&quot;/path_to/graffiti.cma&quot; /&amp;gt;
  &amp;lt;eliom /&amp;gt;
&amp;lt;/host&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;eliommodule ... /&amp;gt;&lt;/code&gt; asks the server to load Eliom module
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;graffiti.cma&lt;/code&gt;, containing the Eliom application, at startup and
attach it to this host (and site).&lt;/p&gt;

&lt;p&gt;Extensions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;static ... /&amp;gt;&lt;/code&gt; (staticmod) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;eliom /&amp;gt;&lt;/code&gt; are called successively:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If they exist, files from the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/path_to/graffiti/static&lt;/code&gt;
will be served,&lt;/li&gt;
  &lt;li&gt;Otherwise, Server will try to generate pages with Eliom (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;eliom /&amp;gt;&lt;/code&gt;),&lt;/li&gt;
  &lt;li&gt;Otherwise it will generate a 404 (Not found) error (default).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;static-validation-of-html&quot;&gt;Static validation of HTML&lt;/h3&gt;

&lt;p&gt;There are several ways to create pages for Eliom. You can generate
pages as strings (as in other web frameworks). However, it is
preferable to generate HTML in a way that provides compile-time HTML
correctness guarantees. This tutorial achieves this by using
module &lt;a href=&quot;http://ocsigen.org/eliom/5.0/api/client/Eliom_content.Html5.D&quot;&gt;Eliom_content.​Html5.​D&lt;/a&gt;, which is implemented using the TyXML
library. The module defines a construction function for each HTML5
tag.&lt;/p&gt;

&lt;p&gt;Note that it is also possible to use the usual HTML syntax directly in OCaml.&lt;/p&gt;

&lt;p&gt;The TyXML library (and thus &lt;a href=&quot;http://ocsigen.org/eliom/5.0/api/client/Eliom_content.Html5.D&quot;&gt;Eliom_content.​Html5.​D&lt;/a&gt;) is very strict and compels you to respect HTML5 standard (with some limitations). For example if you write:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hallo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You will get an error message similar to the following, referring to the end of line 2:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error: This expression has type ([&amp;gt; `PCDATA ] as &apos;a) Html5.elt
       but an expression was expected of type
         Html5_types.head_content_fun Html5.elt
       Type &apos;a is not compatible with type Html5_types.head_content_fun =
           [ `Base
           | `Command
           | `Link
           | `Meta
           | `Noscript of [ `Link | `Meta | `Style ]
           | `Script
           | `Style ]
       The second variant type does not allow tag(s) `PCDATA
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Html5_types.​head_content_fun&lt;/code&gt; is the type of content allowed inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;base&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;command&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;link&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;meta&amp;gt;&lt;/code&gt;, etc.). Notice that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;lt;PCDATA&lt;/code&gt; (i.e. raw text) is not included in this polymorphic variant type.&lt;/p&gt;

&lt;p&gt;Most functions take as parameter the list representing its contents. See other examples below. Each of them take un optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?a&lt;/code&gt; parameter for optional HTML attributes. Mandatory HTML attributes correspond to mandatory OCaml parameters. See below for examples.&lt;/p&gt;

&lt;h3 id=&quot;lwt&quot;&gt;Lwt&lt;/h3&gt;

&lt;p&gt;Important warning: All the functions you write must be written in a cooperative manner using Lwt. Lwt is a convenient way to implement concurrent programs in OCaml, and is now also widely used for applications unrelated to Ocsigen.&lt;/p&gt;

&lt;p&gt;For now we will just use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.return&lt;/code&gt; function as above. We will come back to Lwt programming later. You can also have a look at the Lwt programming guide.&lt;/p&gt;

&lt;h2 id=&quot;execute-parts-of-the-program-on-the-client&quot;&gt;Execute parts of the program on the client&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;(Service sending an application,
Client and server code, Compiling a web application with server and client parts, Calling JavaScript methods with Js_of_ocaml)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To create our first service, we used the function &lt;a href=&quot;http://ocsigen.org/eliom/5.0/api/client/Eliom_registration.Html5#VALregister_service&quot;&gt;Eliom_registration.​Html5.​register_service&lt;/a&gt;, as all we wanted to do was return HTML5. But we actually want a service that corresponds to a full Eliom application with client and server parts. To do so, we need to create our own registration module by using the functor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.App&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graffiti_app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;graffiti&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It is now possible to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;My_app&lt;/code&gt; for registering our main service
(now at URL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Graffiti_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can now add some OCaml code to be executed by the browser. For this purpose, Eliom provides a syntax extension to distinguish between server and client code in the same file. We start by a very basic program, that will display a message to the user by calling the JavaScript function alert. Add the following lines to the program:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Eliom_lib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After running again make test.byte, and visiting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:8080/&lt;/code&gt;, the browser will load the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;graffiti.js&lt;/code&gt;, and open an alert-box.&lt;/p&gt;

&lt;h3 id=&quot;splitting-the-code-into-server-and-client-parts&quot;&gt;Splitting the code into server and client parts&lt;/h3&gt;

&lt;p&gt;At the very toplevel of your source file (i.e. not inside modules or other server- /client-parts), you can use the following constructs to indicate which side the code should run on.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%client ... ]&lt;/code&gt; : the list of enclosed definitions is client-only code (similarly for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%server ... ]&lt;/code&gt;). With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%shared ... ]&lt;/code&gt;, the code is used both on the server and client.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let%client&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let%server&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let%shared&lt;/code&gt;: same as above for a single definition.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%client.start]&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%server.start]&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%shared.start]&lt;/code&gt;: these set the default location for all definitions that follow, and which do not use the preceding constructs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If no location is specified, the code is assumed to be for the server.&lt;/p&gt;

&lt;p&gt;The above constructs are implemented by means of PPX, OCaml’s new mechanism for implementing syntax extensions. See &lt;a href=&quot;http://ocsigen.org/eliom/5.0/manual/ppx-syntax&quot;&gt;Ppx_eliom&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client parts are executed once, when the client side process is launched.&lt;/strong&gt; The client process is not restarted after each page change.&lt;/p&gt;

&lt;p&gt;In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Makefile&lt;/code&gt; created by the distillery, we automatically split the code into client and server parts, compile the server part as usual, and compile the client part to a JavaScript file using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;client-values-on-the-server&quot;&gt;Client values on the server&lt;/h3&gt;

&lt;p&gt;Additionally, it is possible to create client values within the server code by the following quotation:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typ&lt;/code&gt; is the type of an expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr&lt;/code&gt; on the client. Note, that such a client value is abstract on the server, but becomes concrete, once it is sent to the client with the next request.&lt;/p&gt;

&lt;p&gt;(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typ&lt;/code&gt; can be ommitted if it can be inferred from the usage of the client value in the server code.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client values are executed on the client after the service returns.&lt;/strong&gt; You can use client values when a service wants to ask the client to run something, for example binding some event handler on some element produced by the service.&lt;/p&gt;

&lt;h3 id=&quot;js_of_ocaml&quot;&gt;Js_of_ocaml&lt;/h3&gt;

&lt;p&gt;The client-side parts of the program are compiled to JavaScript by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt;. (Technically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt; compiles OCaml bytecode to JavaScript.) It is easy to bind JavaScript libraries so that OCaml programs can call JavaScript functions. In the example, we are using the &lt;a href=&quot;http://ocsigen.org/js_of_ocaml/2.7/api/Dom_html&quot;&gt;Dom_html&lt;/a&gt; module, which is a binding that allows the manipulation of an HTML page.&lt;/p&gt;

&lt;p&gt;Js_of_ocaml is using a syntax extension to call JavaScript methods:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obj##m a b c&lt;/code&gt; to call the method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; of object &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obj&lt;/code&gt; with parameters &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obj##.m&lt;/code&gt; to get a property,&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obj##.m := e&lt;/code&gt; to set a property, and&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new%js constr a b c&lt;/code&gt; to call a JavaScript constructor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information can be found in the Js_of_ocaml manual, in the module
&lt;a href=&quot;http://ocsigen.org/js_of_ocaml/2.7/api/Ppx_js&quot;&gt;Ppx_js&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;accessing-server-side-variables-on-client-side-code&quot;&gt;Accessing server side variables on client side code&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;(Executing client side code after loading a page,
Sharing server side values,
Converting an HTML value to a portion of page (a.k.a. Dom node),
Manipulating HTML node ‘by reference’)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The client side process is not strictly separated from the server side. We can access some server variables from the client code. For instance:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Graffiti_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;ignore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;
               &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sprintf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;You came %i times to this page&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Graffiti&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here, we are increasing the reference count each time the page is accessed. When the page is loaded and the document is in-place, the client program initializes the value inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%client ... ]&lt;/code&gt;, and thus triggers an alert window. More specifically, the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;, in the scope of the client value on the server is made available to the client value using the syntax extension &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~%c&lt;/code&gt;. In doing so, the server side value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt; is displayed in a message box on the client.&lt;/p&gt;

&lt;p&gt;###Injections: Using server side values in client code&lt;/p&gt;

&lt;p&gt;Client side code can reference copies of server side values using syntax &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~%variable&lt;/code&gt;. Values sent that way are weakly type checked: the name of the client side type must match the server side one. If you define a type and want it to be available on both sides, declare it in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%shared ... ]&lt;/code&gt;. The Eliom manual provides more information on the &lt;a href=&quot;http://ocsigen.org/eliom/5.0/api/ppx/Ppx_eliom&quot;&gt;Eliom’s syntax extension&lt;/a&gt; and its &lt;a href=&quot;http://ocsigen.org/eliom/5.0/manual/workflow-compilation#compilation&quot;&gt;compilation process&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that the value of an injection into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%client ... ]&lt;/code&gt; section is sent only once when starting the application in the browser, and not synced automatically later. In contrast, the values of injections into client values which are created during a request are sent alongside the next response.&lt;/p&gt;

&lt;h2 id=&quot;next-week&quot;&gt;Next week&lt;/h2&gt;

&lt;p&gt;In next tutorial, we will turn the program into a collaborative drawing
application, and learn:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How to draw on a canvas,&lt;/li&gt;
  &lt;li&gt;How to program mouse events with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;More about Lwt,&lt;/li&gt;
  &lt;li&gt;How to create communication channels with the server&lt;/li&gt;
  &lt;li&gt;How to create other types of services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The impatient can find the full tutorial
&lt;a href=&quot;http://ocsigen.org/tuto/manual/application&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Vincent Balat</name>
    </author>
  </entry>
  
  <entry>
    <title>Ocsigen&#58; client-server widgets</title>
    <link href="https://ocsigen.github.io/blog-archive/2016/02/22/tutorial-widgets/" />
    <updated>2016-02-22T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2016-02-22:/blog-archive/2016/02/22/tutorial-widgets</id>
    <content type="html">&lt;p&gt;This short tutorial is an example of client-server Eliom application. It gives an example of client-server widgets. You can find the original version of this tutorial (and many others) &lt;a href=&quot;http://ocsigen.org/tuto/manual/tutowidgets&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is probably a good starting point if you know OCaml well, and want to quickly learn how to write a client-server Eliom application with a short example and concise explanations. For more detailed explanations, see the &lt;a href=&quot;http://ocsigen.org/tuto/manual/application&quot;&gt;“Graffiti” tutorial&lt;/a&gt;, or read the manuals.&lt;/p&gt;

&lt;p&gt;The goal is to show that, unlike many JavaScript libraries that build their widgets programmatically (by instantiating classes or calling functions), Eliom enables server-side widget generation, before sending them to the client. Pages can thus be indexed by search engines.&lt;/p&gt;

&lt;p&gt;This tutorial also shows that it is possible to use the same code to build the widget either on client or server side.&lt;/p&gt;

&lt;p&gt;We choose a very simple widget, that could be the base for example for implementing a drop-down menu. It consists of several boxes with a title and a content. Clicking on the title opens or closes the content. Furthermore, it is possible to group some of the boxes together to make them behave like radio buttons: when you open one of them, the previously opened one is closed.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ocsigen.org/tuto/files/tutorial/tutowidgets/ex-final.png&quot; alt=&quot;Screenshot&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;first-step-define-an-application-with-a-basic-service&quot;&gt;First step: define an application with a basic service&lt;/h2&gt;

&lt;p&gt;The following code defines a client-server Web application with only one service, registered at URL / (the root of the website).&lt;/p&gt;

&lt;p&gt;The code also defines a client-side application (section &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%client ... ]&lt;/code&gt;) that appends a client-side generated widget to the page. Section &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%%shared ... ]&lt;/code&gt; is compiled on both the server and client side programs. Alternatively, you can write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let%client&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let%server&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let%shared&lt;/code&gt; (default) to define values on client side, on server side, or on both sides.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Eliom_content&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Html5&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ex_app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ex&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Ex_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_tools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ex&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ex.css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Welcome to Ocsigen!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mywidget&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lwt&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_js_events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;appendChild&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To compile it, first create a project by calling&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;eliom-distillery -name ex -template basic.ppx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The name of the project must match the name given to the functor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.App&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After you adapt the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ex.eliom&lt;/code&gt;, you can compile by calling make, and run the server by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make test.byte&lt;/code&gt;. Download the &lt;a href=&quot;http://ocsigen.org/tuto/files/tutorial/tutowidgets/ex.css&quot;&gt;CSS file&lt;/a&gt; and place it in directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static/css&lt;/code&gt;. Then open a browser window and go to URL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:8080&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Screenshot:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ocsigen.org/tuto/files/tutorial/tutowidgets/ex1.png&quot; alt=&quot;Screenshot&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;more-explanations&quot;&gt;More explanations&lt;/h3&gt;

&lt;p&gt;This section gives very quick explanations on the rest of the program. For more detailed explanations, see the tutorial for the graffiti app or the manual of each of the projects.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The client side program is sent with the first page belonging to the application (registered through module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ex_app&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;##&lt;/code&gt; is used to call a JS method from OCaml and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;##.&lt;/code&gt; to access a JS object field (See Js_of_ocaml’s documentation: &lt;a href=&quot;http://ocsigen.org/js_of_ocaml/api/Ppx_js&quot;&gt;Ppx_js&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;If there are several services in your application, the client-side program will be sent only with the first page, and will not stop if you go to another page of the application.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt&lt;/code&gt; is the concurrent library used to program threads on both client and server sides. The syntax &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let%lwt a = e1 in e2&lt;/code&gt; allows waiting (without blocking the rest of the program) for an Lwt thread to terminate before continuing. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e2&lt;/code&gt; must ben a Lwt thread itself. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt.return&lt;/code&gt; enables creating an already-terminated Lwt thread.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events&lt;/code&gt; defines a convenient way to program interface events (mouse, keyboard, …). For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events.onload&lt;/code&gt; is a Lwt thread that waits until the page is loaded. There are similar functions to wait for other events, e.g., for a click on an element of the page, or for a key press.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;second-step-bind-the-button&quot;&gt;Second step: bind the button&lt;/h2&gt;

&lt;p&gt;To make the widget work, we must bind the click event. Replace function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mywidget&lt;/code&gt; by the following lines:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Lwt_js_events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mywidget&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Once again, we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events&lt;/code&gt;. Function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clicks&lt;/code&gt; is used to bind a handler to clicks on a specific element.&lt;/li&gt;
  &lt;li&gt;Function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt; runs an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt&lt;/code&gt; thread asynchronously (without waiting for its result).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lwt_js_events.clicks elt f&lt;/code&gt; calls function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; for each mouseclick on element &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elt&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;To_dom.of_element&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Js.string&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Js.to_bool&lt;/code&gt; are conversion functions between OCaml values and JS values.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;third-step-generating-the-widget-on-server-side&quot;&gt;Third step: Generating the widget on server side&lt;/h2&gt;

&lt;p&gt;The following version of the program shows how to generate the widget on server side, before sending it to the client.&lt;/p&gt;

&lt;p&gt;The code is exactly the same, with the following modifications:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We place function mywidget out of client section.&lt;/li&gt;
  &lt;li&gt;The portion of code that must be run on client side (binding the click event) is written as a &lt;em&gt;client value&lt;/em&gt;, inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[%client (... : unit) ]&lt;/code&gt;. This code will be executed by the client-side program when it receives the page. Note that you must give the type (here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;), as the type inference for client values is currently very limited. The client section may refer to server side values, using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~%x&lt;/code&gt; syntax. These values will be serialized and sent to the client automatically with the page.&lt;/li&gt;
  &lt;li&gt;We include the widget on the server side generated page instead of adding it to the page from client side.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Eliom_content&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Html5&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ex_app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ex&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt_js_events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mywidget&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Ex_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_tools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ex&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ex.css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Welcome to Ocsigen!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
                   &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;fourth-step-widget-usable-either-on-client-or-server-sides&quot;&gt;Fourth step: widget usable either on client or server sides&lt;/h2&gt;

&lt;p&gt;If you make function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mywidget&lt;/code&gt; &lt;em&gt;shared&lt;/em&gt;, it will be available both on server and client sides:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Screenshot:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ocsigen.org/tuto/files/tutorial/tutowidgets/ex2.png&quot; alt=&quot;Screenshot&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;fifth-step-close-last-window-when-opening-a-new-one&quot;&gt;Fifth step: close last window when opening a new one&lt;/h2&gt;

&lt;p&gt;To implement this, we record a client-side reference to a function for closing the currently opened window.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Eliom_content&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Html5&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ex_app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ex&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;close_last&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt_js_events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close_last&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;close_last&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mywidget&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Ex_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;appendChild&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;client side&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_tools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ex&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ex.css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Welcome to Ocsigen!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;server side&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;server side&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;server side&quot;&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;last-step-several-sets-of-widgets&quot;&gt;Last step: several sets of widgets&lt;/h2&gt;

&lt;p&gt;Now we want to enable several sets of widgets in the same page. A single reference no longer suffices. In the following version, the server-side program asks the client-side program to generate two different references, by calling function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new_set&lt;/code&gt;. This function returns what we call a &lt;em&gt;client value&lt;/em&gt;. Client values are values of the client side program that can be manipulated on server side (but not evaluated). On server side, they have an abstract type.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Eliom_content&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Html5&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;D&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ex_app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ex&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_set&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;elt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Js&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt_js_events&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;switch_visibility&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mywidget&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Ex_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_set&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_set&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;appendChild&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Dom_html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;##.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;To_dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;of_element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;client side&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
       &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_tools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ex&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ex.css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pcdata&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Welcome to Ocsigen!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;server side&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;server side&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;mywidget&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Click me&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;server side&quot;&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Screenshot:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://ocsigen.org/tuto/files/tutorial/tutowidgets/ex-final.png&quot; alt=&quot;Screenshot&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;and-now&quot;&gt;And now?&lt;/h2&gt;

&lt;h3 id=&quot;calling-server-functions&quot;&gt;Calling server functions&lt;/h3&gt;

&lt;p&gt;An important feature missing from this tutorial is the ability to call server functions from the client-side program (“server functions”). You can find a quick description of this in this &lt;a href=&quot;http://ocsigen.org/tuto/manual/how-to-call-a-server-side-function-from-client-side&quot;&gt;mini HOWTO&lt;/a&gt; or in &lt;a href=&quot;http://ocsigen.org/eliom/manual/clientserver-communication#rpc&quot;&gt;Eliom’s manual&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;services&quot;&gt;Services&lt;/h3&gt;

&lt;p&gt;For many applications, you will need several services. By default, client-side Eliom programs do not stop when you follow a link or send a form. This enables combining rich client side features (playing music, animations, stateful applications …) with traditional Web interaction (links, forms, bookmarks, back button …). Eliom proposes several ways to identify services, either by the URL (and parameters), or by a session identifier (we call this kind of service a coservice). Eliom also allows creating new (co-)services dynamically, for example coservices depending on previous interaction with a user. More information on the service identification mechanism in &lt;a href=&quot;http://ocsigen.org/eliom/manual/server-services&quot;&gt;Eliom’s manual&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;sessions&quot;&gt;Sessions&lt;/h3&gt;

&lt;p&gt;Eliom also offers a rich session mechanism, with scopes (see &lt;a href=&quot;http://ocsigen.org/eliom/manual/server-state&quot;&gt;Eliom’s manual&lt;/a&gt;).&lt;/p&gt;
</content>
    <author>
      <name>Vincent Balat</name>
    </author>
  </entry>
  
  <entry>
    <title>Ocsigen, the basics</title>
    <link href="https://ocsigen.github.io/blog-archive/2016/02/08/tutorial-basics/" />
    <updated>2016-02-08T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2016-02-08:/blog-archive/2016/02/08/tutorial-basics</id>
    <content type="html">&lt;p&gt;Following last week release,
I’m starting today a series of tutorials about the Ocsigen framework. For the impatient, most of these tutorials are already available on &lt;a href=&quot;http://ocsigen.org/tuto&quot;&gt;Ocsigen&lt;/a&gt;’s Web site.&lt;/p&gt;

&lt;p&gt;In this first tutorial, we show how to use the Ocsigen framework (mainly Eliom) to write a lightweight Web site by generating pages using OCaml functions.
Even though Eliom makes it possible to write complete client-server Web and mobile apps,
you can still use Eliom even if you don’t need all these features (for example if you don’t want HTML type checking or client side features). Besides, this will allow you to extend your Web site in a full Web application if you need, later on. This tutorial is also a good overview of the basics of Eliom.&lt;/p&gt;

&lt;h2 id=&quot;a-service-generating-a-page&quot;&gt;A service generating a page&lt;/h2&gt;

&lt;p&gt;The following code shows how to create a service that answers requests at URL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://.../aaa/bbb&lt;/code&gt;, by invoking an Ocaml function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; of type:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; generates HTML as a string, taking as argument the list of URL parameters (GET parameters).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;A&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;B&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_service&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;aaa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bbb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_paramer.any&lt;/code&gt; means that the service takes any GET parameter.&lt;/p&gt;

&lt;p&gt;We recommend to use the program eliom-distillery to generate a template for your application (a Makefile and a default configuration file for Ocsigen Server).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ eliom-distillery -name mysite -template basic.ppx -target-directory mysite
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Put the piece of code above in file mysite.eliom, compile and run the server by doing:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make test.byte
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Your page is now available at URL http://localhost:8080/aaa/bbb.&lt;/p&gt;

&lt;p&gt;If you dont want to use the Makefile provided by eliom-distillery, just replace mysite.eliom by a file mysite.ml, compile and run with&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ocamlfind ocamlc -package eliom.server -thread -c mysite.ml
$ ocsigenserver -c mysite.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mysite.conf&lt;/code&gt; is adapted from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;local/etc/mysite/mysite-test.conf&lt;/code&gt; by replacing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mysite.cma&lt;/code&gt; by your cmo.&lt;/p&gt;

&lt;h2 id=&quot;post-service&quot;&gt;POST service&lt;/h2&gt;

&lt;p&gt;Services using the POST HTTP method are created using the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_service.​Http.​post_service&lt;/code&gt;. To create a service with POST parameters, first you must create a service without POST parameters, and then the service with POST parameters, with the first service as fallback. The fallback is used if the user comes back later without POST parameters, for example because he put a bookmark on this URL.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getp&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;...&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Eliom_registration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_post_service&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fallback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main_service&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post_params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Eliom_parameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;going-further&quot;&gt;Going further&lt;/h2&gt;

&lt;p&gt;That is probably all you need for a very basic Web site in OCaml.
But Ocsigen provides many tools to write more advanced Web sites
and applications:&lt;/p&gt;

&lt;p&gt;Instead of generating HTML in OCaml strings, we highly recommend to use
&lt;em&gt;typed HTML&lt;/em&gt;. It is very easy to use, once you have learned the basics,
and helps a lot to efficiently write modular and valid HTML.
To do this, use module
&lt;a href=&quot;http://ocsigen.org/eliom/api/server/Eliom_registration.Html5&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.Html5&lt;/code&gt;&lt;/a&gt;
instead of
&lt;a href=&quot;http://ocsigen.org/eliom/api/server/Eliom_registration.Html_text&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.Html_text&lt;/code&gt;&lt;/a&gt;.
See this
&lt;a href=&quot;http://ocsigen.org/tuto/manual/application#tyxml&quot;&gt;tutorial&lt;/a&gt;
for more information, a comprehensive documentation
&lt;a href=&quot;http://ocsigen.org/tyxml/manual/&quot;&gt;here&lt;/a&gt;,
and a more advanced manual
&lt;a href=&quot;http://ocsigen.org/eliom/manual/clientserver-html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have a look at Eliom’s API documentation to see other kinds of services,
for example &lt;a href=&quot;http://ocsigen.org/eliom/api/server/Eliom_registration.Redirection&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eliom_registration.Redirection&lt;/code&gt;&lt;/a&gt;
to create HTTP redirections.&lt;/p&gt;

&lt;p&gt;Eliom also has a way to typecheck forms and GET or POST parameters.
By giving a description of the parameters your service expects,
Eliom will check their presence automatically, and convert them
for you to OCaml types.
See
&lt;a href=&quot;http://ocsigen.org/tuto/manual/interaction&quot;&gt;this tutorial&lt;/a&gt;
and &lt;a href=&quot;http://ocsigen.org/eliom/manual/server-params&quot;&gt;this manual page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Eliom also has other ways to identify services (besides just the PATH
in the URL). For example Eliom can identify a service just by a parameter
(whatever the path is). This is called &lt;em&gt;non-attached coservices&lt;/em&gt; and
this makes it possible for instance to have the same feature on every page
(for example a connection service).
See
&lt;a href=&quot;http://ocsigen.org/tuto/manual/interaction&quot;&gt;this tutorial&lt;/a&gt;
and &lt;a href=&quot;http://ocsigen.org/eliom/manual/server-services&quot;&gt;this manual page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the main features of Eliom is the ability to write complete
Web and mobile applications in OCaml. Annotations are used to
separate the code to be executed server-side from the client code.
Client functions are translated into Javascript using
&lt;a href=&quot;http://ocsigen.org/js_of_ocaml/&quot;&gt;Ocsigen Js_of_ocaml&lt;/a&gt;.
See
&lt;a href=&quot;http://ocsigen.org/tuto/manual/tutowidgets&quot;&gt;this tutorial&lt;/a&gt; for
a quick introduction,
or &lt;a href=&quot;http://ocsigen.org/tuto/manual/application&quot;&gt;this one&lt;/a&gt; for a
more comprehensive one.
You can also have a look at
&lt;a href=&quot;http://ocsigen.org/eliom/manual/clientserver-applications&quot;&gt;this manual page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another interesting feature of Eliom is its session model, that uses a
very simple interface to record session data server-side.
It is even possible to choose
the &lt;em&gt;scope&lt;/em&gt; of this data: either a browser, or a tab, or even a group
of browsers (belonging for instance to a same user).
See
&lt;a href=&quot;http://ocsigen.org/tuto/manual/interaction#eref&quot;&gt;this section&lt;/a&gt;
and the beginning of
&lt;a href=&quot;http://ocsigen.org/eliom/manual/server-state&quot;&gt;this manual page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We suggest to continue your reading by one of these tutorials:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://ocsigen.org/tuto/manual/tutowidgets&quot;&gt;A quick start tutorial for client-server Eliom applications&lt;/a&gt; (for the people already familiar with OCaml, Lwt, etc.)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://ocsigen.org/tuto/manual/application&quot;&gt;A step by step tutorial for client-server Eliom applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://ocsigen.org/tuto/manual/interaction&quot;&gt;A tutorial on server side dynamic Web site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
    <author>
      <name>Vincent Balat</name>
    </author>
  </entry>
  
  <entry>
    <title>January 2016 Ocsigen releases</title>
    <link href="https://ocsigen.github.io/blog-archive/2016/02/01/january-2016-releases/" />
    <updated>2016-02-01T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2016-02-01:/blog-archive/2016/02/01/january-2016-releases</id>
    <content type="html">&lt;p&gt;We are excited to announce the releases of&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/eliom/releases/tag/5.0.0&quot;&gt;Eliom 5.0&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/js_of_ocaml/releases/tag/2.7&quot;&gt;js_of_ocaml 2.7&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/tyxml/releases/tag/3.6.0&quot;&gt;TyXML 3.6&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/reactiveData/releases/tag/0.2&quot;&gt;reactiveData 0.2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These releases are the result of many months of work by the Ocsigen
team, and bring a range of improvements.&lt;/p&gt;

&lt;h2 id=&quot;ppx&quot;&gt;PPX&lt;/h2&gt;

&lt;p&gt;Eliom 5.0 comes with a &lt;a href=&quot;http://ocsigen.org/eliom/5.0/manual/ppx-syntax&quot;&gt;PPX-based
language&lt;/a&gt; (for OCaml
4.02.x). This follows our PPX extensions for
&lt;a href=&quot;https://ocsigen.org/js_of_ocaml/2.7/api/Ppx_js&quot;&gt;js_of_ocaml&lt;/a&gt; and
&lt;a href=&quot;https://ocsigen.org/lwt/2.5.1/api/Ppx_lwt&quot;&gt;Lwt&lt;/a&gt;. The new syntax is
more flexible than our previous Camlp4-based one, and we recommend it
for new projects. Nevertheless, the Camlp4-based syntax remains
available.&lt;/p&gt;

&lt;h2 id=&quot;shared-reactive-programming&quot;&gt;Shared reactive programming&lt;/h2&gt;

&lt;p&gt;Recent versions of Eliom provided client-side support for (functional)
reactive programming. Eliom 5.0 additionally supports &lt;a href=&quot;http://ocsigen.org/eliom/5.0/manual/clientserver-react&quot;&gt;“shared”
(client-server) reactive
programming&lt;/a&gt;,
where the reactive signals have meaning both on the server and the
client. This means that the initial version of the page is produced
(on the server) with the same code that takes care of the dynamic
updates (on the client).&lt;/p&gt;

&lt;h2 id=&quot;enhanced-js_of_ocaml-library&quot;&gt;Enhanced js_of_ocaml library&lt;/h2&gt;

&lt;p&gt;The js_of_ocaml library provides additional bindings for established
JavaScript APIs. This includes&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://ocsigen.org/js_of_ocaml/2.7/api/Geolocation&quot;&gt;geolocation&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://ocsigen.org/js_of_ocaml/2.7/api/MutationObserver&quot;&gt;mutation
observers&lt;/a&gt;, and&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://ocsigen.org/js_of_ocaml/2.7/api/Worker&quot;&gt;web workers&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A new JavaScript-specific &lt;a href=&quot;http://ocsigen.org/js_of_ocaml/2.7/api/Jstable&quot;&gt;table
module&lt;/a&gt; is also
available.&lt;/p&gt;

&lt;h2 id=&quot;ppx_deriving&quot;&gt;ppx_deriving&lt;/h2&gt;

&lt;p&gt;js_of_ocaml provides a new &lt;a href=&quot;https://github.com/ocsigen/js_of_ocaml/pull/364&quot;&gt;JSON
  plugin&lt;/a&gt; for
  &lt;a href=&quot;https://github.com/whitequark/ppx_deriving&quot;&gt;ppx_deriving&lt;/a&gt;. This can
  be used for serializing OCaml data structures to JSON in a type-safe
  way. The plugin remains compatible with its Camlp4-based predecessor
  with respect to the serialization format.&lt;/p&gt;

&lt;h2 id=&quot;under-the-hood&quot;&gt;Under the hood&lt;/h2&gt;

&lt;p&gt;In addition to providing various fixes, we have improved the
performance of various Ocsigen components. Notably:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A &lt;a href=&quot;https://github.com/ocsigen/eliom/pull/233&quot;&gt;range of patches related to request
data&lt;/a&gt; result in
measurably smaller size for the produced pages.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The js_of_ocaml compiler becomes faster via improvements in
&lt;a href=&quot;https://github.com/ocsigen/js_of_ocaml/commit/3991c07b15d88c89bad43de8303b0e0a553b2eed&quot;&gt;bytecode
parsing&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;reactiveData employs
&lt;a href=&quot;https://github.com/ocsigen/reactiveData/pull/12&quot;&gt;diffing&lt;/a&gt; to detect
data structure changes, leading to more localized incremental
updates.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;community&quot;&gt;Community&lt;/h2&gt;

&lt;p&gt;The Ocsigen team always welcomes your feedback and contributions.
Stay in touch via &lt;a href=&quot;https://github.com/ocsigen&quot;&gt;GitHub&lt;/a&gt; and our
&lt;a href=&quot;https://sympa.inria.fr/sympa/subscribe/ocsigen&quot;&gt;mailing list&lt;/a&gt;!&lt;/p&gt;
</content>
    <author>
      <name>The Ocsigen team</name>
    </author>
  </entry>
  
  <entry>
    <title>TodoMVC: a reactive version</title>
    <link href="https://ocsigen.github.io/blog-archive/2015/10/07/react-example-todomvc/" />
    <updated>2015-10-07T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2015-10-07:/blog-archive/2015/10/07/react-example-todomvc</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://todomvc.com/&quot;&gt;TodoMVC&lt;/a&gt; is a project which offers the same Todo
application implemented using &lt;a href=&quot;https://en.wikipedia.org/wiki/Model-view-controller&quot;&gt;MV*&lt;/a&gt; concepts in most of the
popular JavaScript MV* frameworks. One of the aims of TodoMVC is to
enable a fair comparison between several frameworks, by providing
implementations of the same application. A &lt;a href=&quot;http://ocsigen.org/js_of_ocaml/&quot;&gt;js_of_ocaml (JSOO)&lt;/a&gt;
version is now available:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/tree/master/jsoo/todomvc-react&quot;&gt;Source code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://slegrand45.github.io/examples_ocsigen.site/jsoo/todomvc-react/&quot;&gt;Demo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our version is powered by the &lt;a href=&quot;http://erratique.ch/software/react&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React&lt;/code&gt;&lt;/a&gt; module for &lt;a href=&quot;https://en.wikipedia.org/wiki/Functional_reactive_programming&quot;&gt;functional
reactive programming (FRP)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post, we outline the architecture of our implementation, with
a particular emphasis on how it applies MVC and FRP concepts.&lt;/p&gt;

&lt;h2 id=&quot;mvc&quot;&gt;MVC&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Model-view-controller&quot;&gt;MVC&lt;/a&gt;, which stands for &lt;em&gt;Model-View-Controller&lt;/em&gt;, is a software
architecture very commonly used for implementing user interfaces. MVC
divides an application into three components:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;the &lt;em&gt;Model&lt;/em&gt; manages the data, logic and rules of the application;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;the &lt;em&gt;Controller&lt;/em&gt; manages events from the view, and accordingly
updates the model;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;the &lt;em&gt;View&lt;/em&gt; generates an output presentation (a web page for
instance) based on the model data.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the Todo application, we have three corresponding OCaml
modules. &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L38&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Model&lt;/code&gt;&lt;/a&gt; mainly contains the task list and the new
task field value. It uses &lt;a href=&quot;https://ocsigen.org/js_of_ocaml/api/Deriving_Json&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Deriving_Json&lt;/code&gt;&lt;/a&gt; to convert
the data to JSON and vice versa, in order to be able to save and
restore the application state. This module is otherwise written with
basic OCaml code. &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L111&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Controller&lt;/code&gt;&lt;/a&gt; produces new models
according to the actions it receives. Whenever a new model is built,
the model becomes the new reactive signal value. We will elaborate on
this point later. &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L175&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;View&lt;/code&gt;&lt;/a&gt; builds the HTML to display the
page. It receives as input the dynamic data from the model. The HTML
also contains the event management code needed to emit the
corresponding actions.&lt;/p&gt;

&lt;p&gt;Besides these three MVC modules, the application uses three
helpers. &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L14&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storage&lt;/code&gt;&lt;/a&gt;
contains the functions to read and write a string value in the browser
local storage. This module is used to save and restore the application
data in JSON
format. &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L94&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Action&lt;/code&gt;&lt;/a&gt;
contains all the actions available from the user
interface. &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L3&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReactList&lt;/code&gt;&lt;/a&gt;
contains a single function to ease the creation of a reactive list via
the &lt;a href=&quot;https://github.com/hhugo/reactiveData&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReactiveData&lt;/code&gt; library&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;react&quot;&gt;React&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://erratique.ch/software/react&quot;&gt;React&lt;/a&gt; is an OCaml module for &lt;a href=&quot;https://en.wikipedia.org/wiki/Functional_reactive_programming&quot;&gt;functional reactive programming
(FRP)&lt;/a&gt;. In our TodoMVC example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React&lt;/code&gt; provides a way to
automatically refresh the view whenever a new model is built by the
controller. To achieve this goal, the application uses a reactive
signal which carries the model values (which vary over time). The
model value may initially be equal to the &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L60-L65&quot;&gt;empty model&lt;/a&gt;. When
this value is modified by the controller, &lt;em&gt;i.e.,&lt;/em&gt; after a new model
has been generated, the view automatically refreshes its reactive
parts.&lt;/p&gt;

&lt;h2 id=&quot;mixing-mvc-and-frp&quot;&gt;Mixing MVC and FRP&lt;/h2&gt;

&lt;p&gt;The following figure shows what happens when the user interacts with
the application, &lt;em&gt;e.g.,&lt;/em&gt; by adding a new task, or by clicking on a
checkbox to select a specific task:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/posts/2015/react-example-todomvc-steps.png&quot; alt=&quot;MVC with `React`&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;the view sends the action to the controller;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;the controller gets the current model from the reactive signal, and
builds a new model accordingly to the action;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;the controller sets this new model as the new reactive signal
value;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;the view reacts to the newly-available model (new signal value) and
updates itself with the corresponding data.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We proceed to describe our implementation of the above scheme, with an
emphasis on the reactive features.&lt;/p&gt;

&lt;h3 id=&quot;initialization&quot;&gt;Initialization&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L393&quot;&gt;main function&lt;/a&gt; creates the reactive signal with an initial
(possibly empty) model. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; value is of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Model.t&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* ... *)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React.S.create&lt;/code&gt; returns a tuple, the first part of which is a
primitive signal; the second part is a function used by the controller
&lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L170&quot;&gt;to set a new model as the new signal value&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;reactive-attribute&quot;&gt;Reactive attribute&lt;/h3&gt;

&lt;p&gt;We first explain how the CSS style of a HTML node &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L267-L299&quot;&gt;becomes
reactive&lt;/a&gt;. In the Todo application, the task list is
displayed in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;section&amp;gt;&lt;/code&gt; HTML tag. The CSS style of this HTML node
must contain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;visibility: hidden;&lt;/code&gt; if the tasks list is empty, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;visibility: visible;&lt;/code&gt; otherwise (&lt;em&gt;i.e.,&lt;/em&gt; if the number of tasks is
greater than zero). The style attribute of this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;section&amp;gt;&lt;/code&gt; node must
therefore change according to the model content:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;css_visibility&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We use the &lt;a href=&quot;https://ocsigen.org/js_of_ocaml/api/Tyxml_js&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tyxml_js&lt;/code&gt;&lt;/a&gt; module to safely build the HTML
code. The first thing to note is that we use the reactive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;R.Html5&lt;/code&gt;
submodule, not the plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Html5&lt;/code&gt; submodule. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a_style&lt;/code&gt; function
implements a reactive attribute; it expects a reactive signal as its
argument. Here we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React.S.map&lt;/code&gt;, which has the signature &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&apos;a -&amp;gt;
&apos;b) -&amp;gt; &apos;a React.signal -&amp;gt; &apos;b React.signal&lt;/code&gt;. The first argument to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css_visibility&lt;/code&gt; function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;css_visibility&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;visibility: hidden;&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;visibility: visible;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you can see, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css_visibility&lt;/code&gt; receives a model &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; as its
argument. When wrapped by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React.S.map&lt;/code&gt; as above, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css_visibility&lt;/code&gt;
operates on signals. The function returns the right style, depending
on whether the list of tasks is empty or not.&lt;/p&gt;

&lt;p&gt;The second argument to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React.S.map&lt;/code&gt; is the value named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;, which is
the primitive signal. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; is the first value returned by the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React.S.create&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Each time the signal value gets updated by the controller, the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css_visibility&lt;/code&gt; function is automatically called with the new signal
value (a new model) as its argument, and the style attribute is
automatically modified.&lt;/p&gt;

&lt;h3 id=&quot;reactive-list&quot;&gt;Reactive list&lt;/h3&gt;

&lt;p&gt;Reactive attributes alone would not suffice to build a user
interface. We also need a reactive list of child nodes. Such a list is
for example needed to display the task list. (&lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L267-L299&quot;&gt;The source code section
is the same as for the first
example.&lt;/a&gt;) It
is a list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;li&amp;gt;&lt;/code&gt; nodes contained in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; node. We accordingly
have a reactive node, as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_class&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;todo-list&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rl&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As before, we use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;R.Html5&lt;/code&gt; module. This time we do not use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;R.Html5&lt;/code&gt; to build an attribute, but rather a (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;) node. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rl&lt;/code&gt;
contains the node’s children:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ReactList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;visible_tasks&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We create the reactive list via the helper module
&lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L3&quot;&gt;ReactList&lt;/a&gt;. As for the previous example, we use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React.S.map&lt;/code&gt; to build a reactive signal, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; being again the
primitive signal. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;visible_tasks&lt;/code&gt; function generates the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;li&amp;gt;&lt;/code&gt;
elements from the task list, filtered by the current selected
visibility:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;visible_tasks&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;visibility&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;visibility&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_visible&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;todo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;visibility&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Completed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;completed&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Active&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;completed&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;All&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_visible&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fold_left&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;todo_item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Following the same principle as for the reactive attribute, each time
the signal value gets updated by the controller, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;li&amp;gt;&lt;/code&gt; nodes are
automatically refreshed.&lt;/p&gt;

&lt;h3 id=&quot;signal-typing&quot;&gt;Signal typing&lt;/h3&gt;

&lt;p&gt;You may have noticed that the code &lt;a href=&quot;https://github.com/slegrand45/examples_ocsigen/blob/d6766d404a449d0b1d36ad3cd916b0c444390a19/jsoo/todomvc-react/todomvc.ml#L89-L91&quot;&gt;includes the following
types&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;These types are used whenever type annotations are required, &lt;em&gt;e.g.,&lt;/em&gt;
for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt; function from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Controller&lt;/code&gt; module:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* ... *)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;comparison-with-the-elm-implementation&quot;&gt;Comparison with the Elm implementation&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://elm-lang.org/&quot;&gt;Elm&lt;/a&gt; is a functional programming language
dedicated to frontend web application development. Elm was designed by
Evan Czaplicki. The language should feel familiar to OCaml
programmers.&lt;/p&gt;

&lt;p&gt;Our TodoMVC example is based on the &lt;a href=&quot;https://github.com/evancz/elm-todomvc&quot;&gt;Elm
implementation&lt;/a&gt;, which follows
the structure used in &lt;a href=&quot;https://github.com/evancz/elm-architecture-tutorial/&quot;&gt;all Elm
programs&lt;/a&gt;: a
model, an update function, and a view. Like Elm, our example uses the
functional reactive programming style, enabled in our case by the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;React&lt;/code&gt; library and the reactive modules &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tyxml_js.R&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReactiveData&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The combination of OCaml, js_of_ocaml, and functional reactive
programming provides a killer feature combination for building rich
web clients. Additionally, OCaml static typing can provide
compile-time HTML validity checking (via TyXML), thus increasing
reliability.&lt;/p&gt;

</content>
    <author>
      <name>Stéphane Legrand</name>
    </author>
  </entry>
  
  <entry>
    <title>Summer Ocsigen releases</title>
    <link href="https://ocsigen.github.io/blog-archive/2015/08/17/releases/" />
    <updated>2015-08-17T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2015-08-17:/blog-archive/2015/08/17/releases</id>
    <content type="html">&lt;p&gt;We are happy to announce the releases of&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/eliom/releases/tag/4.2&quot;&gt;Eliom 4.2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/ocsigenserver/releases/tag/2.6&quot;&gt;Server 2.6&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/js_of_ocaml/releases/tag/2.6&quot;&gt;js_of_ocaml 2.6&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocsigen/tyxml/releases/tag/3.5.0&quot;&gt;TyXML 3.5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also welcome a new member in the ocsigen team, &lt;a href=&quot;https://github.com/vasilisp&quot;&gt;Vasilis Papavasileiou&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Key changes in the various releases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;PPX support for js_of_ocaml with OCaml &amp;gt;= 4.02.2.
See documentation &lt;a href=&quot;http://ocsigen.org/js_of_ocaml/2.6/api/Ppx_js&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;This was also the occasion to introduce a new syntax for object
literals, and to improve the Camlp4 syntax (w.r.t. to
locations). Both syntaxes emit the same code, and are perfectly
compatible.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Support for dynlink in js_of_ocaml.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Logging improvements in Eliom and Server, in particular on
the client side.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A healthy amount of bugfixes.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next releases will probably see major changes. The current plan
is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Replace Server’s internals with cohttp, as part of our
move towards Mirage-compatible libraries. See &lt;a href=&quot;https://github.com/ocsigen/ocsigenserver/issues/54&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Shared_react, which allows to build reactive pages from server side. See &lt;a href=&quot;https://github.com/ocsigen/eliom/issues/162&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;PPX for Eliom.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Support for async/core in js_of_ocaml.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have fun with Ocsigen!&lt;/p&gt;
</content>
    <author>
      <name>Gabriel Radanne</name>
    </author>
  </entry>
  
  <entry>
    <title>Welcome to the Ocsigen Blog!</title>
    <link href="https://ocsigen.github.io/blog-archive/2015/07/29/welcome/" />
    <updated>2015-07-29T00:00:00+00:00</updated>
    <id>tag:ocsigen.github.io,2015-07-29:/blog-archive/2015/07/29/welcome</id>
    <content type="html">&lt;p&gt;The &lt;a href=&quot;https://www.ocsigen.org&quot;&gt;Ocsigen&lt;/a&gt; project finally has a blog. We are planning to
publish news from the wider Ocsigen community, tutorials, and more.&lt;/p&gt;

&lt;p&gt;Ocsigen encompasses the building blocks that you need in order to
efficiently develop Web applications in &lt;a href=&quot;https://www.ocaml.org&quot;&gt;OCaml&lt;/a&gt;.  Among other
libraries and tools, Ocsigen provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://ocsigen.org/js_of_ocaml/&quot;&gt;js_of_ocaml&lt;/a&gt;, which is a compiler from OCaml to JavaScript;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://ocsigen.org/ocsigenserver&quot;&gt;Ocsigen Server&lt;/a&gt;, which is a web server implemented in OCaml;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://ocsigen.org/lwt&quot;&gt;Lwt&lt;/a&gt;, which is a cooperative thread library for OCaml;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://ocsigen.org/tyxml&quot;&gt;TyXML&lt;/a&gt;, which is a library for generating valid HTML and SVG
content; last but not least,&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://ocsigen.org/eliom&quot;&gt;Eliom&lt;/a&gt;, which puts everything together to provide a modern
language for developing web applications, with tight integration
between client and server.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy hacking, and stay tuned!&lt;/p&gt;

</content>
    <author>
      <name>The Ocsigen Team</name>
    </author>
  </entry>
  
</feed>
