# \[ANN\] StippleMakie.jl - easy integration of Makie plots into GenieFramework

**URL:** <https://discourse.julialang.org/t/ann-stipplemakie-jl-easy-integration-of-makie-plots-into-genieframework/123632>\
**Category:** Package Announcements\
**Tags:** package, genie, makie, stipple\
**Created:** [December 9, 2024, 8:20pm UTC](https://discourse.julialang.org/t/ann-stipplemakie-jl-easy-integration-of-makie-plots-into-genieframework/123632 "2024-12-09T20:20:29Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![hhaensel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hhaensel/32/1207_2.png) [@hhaensel](https://discourse.julialang.org/u/hhaensel)\
**Post date:** [December 9, 2024, 8:20pm UTC](https://discourse.julialang.org/t/ann-stipplemakie-jl-easy-integration-of-makie-plots-into-genieframework/123632/1 "2024-12-09T20:20:29Z")

</div>

# [ANN] StippleMakie

Having started off at the hackathon of JuliaCon 2024 we’re happy that we can finally release the first version of StippleMakie.  
It brings together the best of two worlds - the completeness of the GenieFramework UI with the beauty and richness of Makie plots.

The figures resize with the html layout

### Demo App

Here’s a small demo app.

```julia
using Stipple, Stipple.ReactiveTools, StippleUI
using StippleMakie

Stipple.enable_model_storage(false)

@app MakieDemo begin
    @out fig1 = MakieFigure()
    @out fig2 = MakieFigure()
    @in hello = false

    @onbutton hello begin
        @notify "Hello World!"
    end

    @onchange isready begin
        init_makiefigures( __model__ )
        
        onready(fig1) do
            Makie.scatter(fig1.fig[1, 1], (0:4).^3)
            Makie.heatmap(fig2.fig[1, 1], rand(5, 5))
            Makie.lines(fig2.fig[1, 2], cos.(0:2π/100:2π))
        end
    end
end

UI::ParsedHTMLString = column(style = "height: 80vh; width: 100%", [
    h4("MakiePlot 1")
    cell(col = 4, class = "full-width", makie_figure(:fig1))
    h4("MakiePlot 2")
    cell(col = 5, class = "full-width", makie_figure(:fig2))
    (btn("Hello", @click(:hello), color = "primary"))
])

ui() = UI

route("/") do
    WGLMakie.Page()
    model = @init MakieDemo    
    html!(ui, layout = Stipple.ReactiveTools.DEFAULT_LAYOUT(head_content = [makie_dom(model)]), model = model, context = @ __MODULE__ )
end

up(open_browser = true)

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/c/8/c8aafe2d103afb104c5637a07a71c448cff08947.png)

### Hosting

StippleMakie is running two websocket stacks in parallel. If your provider doesn’t allow two ports to be used you can configure a basepath for the Makie stack and a proxy server to separate the two. We have `configure_makie_server!()` and `nginx_conf()` to make this setup as easy as possible.

### Kudos

- to Simon Danisch who gave me a boost in understanding of Bonito’s websocket stack
- to the organizers of the hackathon; without them this package would not have come into existence
- to Adrian Salceanu for the coffee 😉

---

<div class="post-metadata">

**Author:** ![g-gundam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/g-gundam/32/47593_2.png) [@g-gundam](https://discourse.julialang.org/u/g-gundam)\
**Post date:** [December 9, 2024, 8:56pm UTC](https://discourse.julialang.org/t/ann-stipplemakie-jl-easy-integration-of-makie-plots-into-genieframework/123632/2 "2024-12-09T20:56:49Z")

</div>

> [@hhaensel](#):
>
> to Simon Danisch who gave me a boost in understanding of Bonito’s websocket stack

That knowledge needs to be published somewhere. The existing docs on WebSockets in Genie.jl leaves a lot of details out.

- The main source of confusion for me was how the docs used the word “channel” in two different but related ways.
  - A channel is a bidirectional medium through which WebSocket messages travel.
  - There’s also a server-side `channel(route, handler)` method that doesn’t create a channel. It creates a route handler for WebSocket messages.

- The naming of channel route handlers has some rules that are not mentioned.
  - The first segment of the route has to be a channel name.
  - That’s why the built-in `/ ____/subscribe` and `/____ /unsubscribe` channel routes are named that way.
  - ` ____ ` is the name of the channel they operate on.

> **[Web sockets - Genie](https://learn.genieframework.com/framework/genie.jl/docs/websockets/)**
>
> Implement browser-server communication with web sockets.

---

<div class="post-metadata">

**Author:** ![hhaensel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hhaensel/32/1207_2.png) [@hhaensel](https://discourse.julialang.org/u/hhaensel)\
**Post date:** [December 12, 2024, 6:29am UTC](https://discourse.julialang.org/t/ann-stipplemakie-jl-easy-integration-of-makie-plots-into-genieframework/123632/3 "2024-12-12T06:29:31Z")

</div>

A new version is out with a Julia proxy. So StippleMakie can live on a single port without any external software.
