{0 Quick Start}

This guide walks you through creating your first js_of_ocaml application.

{1:installation Installation}

{v
opam install js_of_ocaml js_of_ocaml-ppx
v}

{1:project-setup Project setup}

Create a new directory and initialize a dune project:

{v
mkdir hello_jsoo && cd hello_jsoo
v}

Create the following files:

{2 dune-project}

{v
(lang dune 3.0)
v}

{2 dune}

{v
(executable
 (name main)
 (modes js)
 (libraries js_of_ocaml)
 (preprocess (pps js_of_ocaml-ppx)))
v}

{2 main.ml}

{@ocaml[
open Js_of_ocaml

let () =
  let message = Js.string "Hello from OCaml!" in
  Dom_html.window##alert message
]}

{1:build Build}

{v
dune build
v}

This produces [_build/default/main.bc.js].

{1:run-browser Run in browser}

Create an HTML file to load the JavaScript:

{2 index.html}

{v
<!DOCTYPE html>
<html>
<head>
  <title>Hello js_of_ocaml</title>
</head>
<body>
  <script src="_build/default/main.bc.js"></script>
</body>
</html>
v}

Open [index.html] in a browser. You should see an alert with "Hello from OCaml!".

{1:run-nodejs Run in Node.js}

{v
node _build/default/main.bc.js
v}

Note: [alert] is not available in Node.js. For Node.js, use:

{@ocaml[
let () = print_endline "Hello from OCaml!"
]}

{1:dom-example DOM manipulation example}

Here's a more complete example that manipulates the DOM:

{2 main.ml}

{@ocaml[
open Js_of_ocaml

let create_button text onclick =
  let doc = Dom_html.document in
  let button = Dom_html.createButton doc in
  button##.textContent := Js.some (Js.string text);
  button##.onclick := Dom_html.handler (fun _ ->
    onclick ();
    Js._true);
  button

let () =
  let doc = Dom_html.document in
  let body = doc##.body in

  (* Create a counter display *)
  let counter = ref 0 in
  let display = Dom_html.createDiv doc in
  let update_display () =
    display##.textContent := Js.some (Js.string (string_of_int !counter))
  in
  update_display ();

  (* Create buttons *)
  let incr_btn = create_button "+" (fun () ->
    incr counter;
    update_display ()
  ) in
  let decr_btn = create_button "-" (fun () ->
    decr counter;
    update_display ()
  ) in

  (* Add to page *)
  Dom.appendChild body decr_btn;
  Dom.appendChild body display;
  Dom.appendChild body incr_btn
]}

{2 index.html}

{v
<!DOCTYPE html>
<html>
<head>
  <title>Counter</title>
  <style>
    button { font-size: 24px; margin: 10px; }
    div { font-size: 48px; display: inline-block; min-width: 100px; text-align: center; }
  </style>
</head>
<body>
  <script src="_build/default/main.bc.js"></script>
</body>
</html>
v}

{1:dev-workflow Development workflow}

For faster iteration during development, use:

{v
dune build -w
v}

This watches for file changes and rebuilds automatically.

{1:next-steps Next steps}

- {{!page-"ppx"}PPX syntax} - Learn the syntax for JavaScript interop
- {{!page-"javascript-interop"}JavaScript interop} - Use existing JavaScript libraries
- {{!page-"rev-bindings"}Exporting to JS} - Make OCaml code callable from JavaScript
