Dream — a simple, yet feature-complete Web framework

I am pleased to announce Dream, a very easy-to-use Web framework with high performance, secure defaults, and thorough documentation!


It is available now from opam, with opam install dream.1.0.0~alpha2.

Dream offers:

…and more, yet Dream sticks to a simple programming model:

Indeed, for those who like algebra, there is a certain structure to Dream. However, that’s not the point of this post!

Dream is meant to be very easy to understand. It sticks to base types, introducing only a few types of its own, and uses existing languages, such as HTML for templates, and URLs for routes. Dream itself is one module in one opam package, which lives in a monorepo. The docs are on one page.

Dream is loosely coupled. Even though Dream offers many defaults, it is unopinionated, and you can quickly configure or replace anything. For example, it is easy to use TyXML for templates, and Dream happily supports such usage with examples.

Security-sensitive features, such as cookies, are arranged so that simple and obvious usage is automatically secure. Wherever security still depends on the Dream app, the docs highlight it. Dream has selected a modern cipher as a default, supports key rotation, and offers suggestions for other purposes, such as password hashing. It implements and abstracts away all of the OWASP security guidelines that are relevant to its level.

Dream is designed for full internationalization. It has a centralized error handler that intercepts even lower-level HTTP errors, so that you can decorate them with your app’s own error template, and leak no hardcoded strings. Dream’s URL encoders favor internationalized (UTF-8) URIs, and the router accepts them.

Finally, Dream is designed for a wide range of applications, including with or without a proxy, standalone or embedded in larger binaries, and with external static assets or assets compiled in.


Dream is very extensively documented. See…

  • Examples, the first several of which make up a tutorial. Each example is a complete project.
  • The online playground, which features many of the examples, and is itself a Dream app!
  • The API docs.

In particular, see


Dream has already received several very helpful contributions, and more are very welcome! See CONTRIBUTING.md. I must also acknowledge all the people working on Dream’s dependecies and prior art. In particular, Dream relies heavily on the HTTP and WebSocket servers primarily by Spiros Eliopoulos (@seliopou) and Antonio Nuno Monteiro (@anmonteiro).

Apart from accepting code, docs, and examples, Dream will happily link to:

  • Blogs and articles, as different people learn best from different presentations.
  • “Downstream” libraries to use with Dream.

For example, Thibaut Mattio (@tmattio) is working on dream-livereload, a live-reloading middleware for Dream, similar to the example, which he also contributed! Once dream-livereload is slightly more mature, Dream will link to it from its README.

There is also dream-serve, a live-reloading static site server based on Dream and libuv, which was used to develop the docs.


Dream is currently in an alpha state. It is thought (by me) to be internally quite stable. However, there will probably be various API tweaks before release 1.0.0.

My current, rough plan is to release several alphas of Dream over six months or so. The releases will address:

  1. Flow control for very large responses, and getting the “advanced” part of the I/O API to be as close to zero-copy and non-allocating as possible (or reasonable).
  2. Remaining (optional) security enhancements, such as a default content security policy.
  3. Remaining session improvements, such as re-keying.
  4. Friction in handling of JSON, database access, etc. This is not properly part of or due to Dream, but it should be addressed for a better Web development experience.
  5. Multicore and effects support.

That’s all. Let’s bring OCaml to the Web! Happy Web programming!


For readers who saw the repo during the earlier “leak,” the main updates are:

  • A large number of new examples, including deployment.
  • The playground, which runs the examples, and itself served as a test.
  • An esy-based quick start script.

There have also been very many smaller changes to the code, API, and the rest of the docs, but the above changes are the biggest “chunks.” The rest is too much to detail :slight_smile:


I’ve been using dream for a project since the “leak”, and it is dope! Fantastic work with the documentation and design <3


I was always wondering how does the source code that uses templates work with OCaml tooling, in particular with merlin, ocp-indent, ocaml-format, tuareg and other editor modes?

1 Like

It doesn’t work well in practice with anything other than syntax highlighting. Note that you control the syntax mode with the extension. If your template is mostly HTML, you can name it foo.eml.html.

The intent is that the templates should contain mostly HTML in a large project, and most of them would be in their own template/ subdirectory. OCaml tooling wouldn’t be needed for these mostly-HTML files. For a still-small, but real example of this, see the Playground’s client.eml.html.

The one-file .ml projects with templates, where tooling is a problem, are mostly good for the very first steps of getting started, and examples.

There is also an issue about this in the repo, #55 " how to apply ocamlformat".

Note that, as in the announcement text, you can use Dream with other templaters, including TyXML, which has an HTML PPX. In addition, if you are using Reason, you can use TyXML JSX. Either of these options interacts well with tooling, as far as I know.

I didn’t make TyXML the default because it considerably increases the Dream learning curve for getting basic tasks done. However, Dream still supports the choice of using TyXML with examples and links.


A playground … incredible. Fantastic job antron.

1 Like

This is a completely random note, but you might find it interesting to try to use the node child_process module to show how to use dream as a “custom server” for nextjs, as one of the more exotic examples.

1 Like