## Installation

    opam install js_of_ocaml js_of_ocaml-ppx

## Project setup

Create a new directory and initialize a dune project:

    mkdir hello_jsoo && cd hello_jsoo

Create the following files:

### dune-project

    (lang dune 3.0)

### dune

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

### main.ml

    open Js_of_ocaml

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

## Build

    dune build

This produces `_build/default/main.bc.js`.

## Run in browser

Create an HTML file to load the JavaScript:

### index.html

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

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

## Run in Node.js

    node _build/default/main.bc.js

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

    let () = print_endline "Hello from OCaml!"

## DOM manipulation example

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

### main.ml

    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

### index.html

    <!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>

## Development workflow

For faster iteration during development, use:

    dune build -w

This watches for file changes and rebuilds automatically.

## Next steps

- PPX syntax - Learn the syntax for JavaScript interop
- JavaScript interop - Use existing JavaScript libraries
- Exporting to JS - Make OCaml code callable from JavaScript