# Add Stipple,jl reactive elements to existed Genie.jl app with controllers

**URL:** <https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726>\
**Category:** Web Stack\
**Created:** [July 14, 2025, 9:59pm UTC](https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726 "2025-07-14T21:59:21Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![PharmCat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pharmcat/32/6953_2.png) [@PharmCat](https://discourse.julialang.org/u/PharmCat)\
**Post date:** [July 14, 2025, 9:59pm UTC](https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726/1 "2025-07-14T21:59:21Z")

</div>

So I made Genie.jl app as it described in movie example. With controllers, route.jl, ets…

Is it possible to use Stipple.jl functionality in existed project?

I have no `app.jl` in Genie.jl project… Where I should use all of these elements?

```julia
using GenieFramework # < inside controller?
using Statistics
@genietools # < inside controller?

@app begin # < inside controller?
    @in N = 0
    @out m = 0.0
    @out name = "John"
    @onchange N begin
        m = mean(rand(N))
    end
end

# Define the UI for each page
index() = [h1("Welcome {{name}}!"), a(href="/form")]
function formui() # < call this function from routes.jl 
    cell([
        textfield("How many numbers?", :N),
        p("The average of {{N}} random numbers is {{m}}"),
    ])
end

@route("/", index) # < remove this ?
@page("/form", formui) # < remove this ?

```

Can i just add?:

```julia
using MyGenieApp.OnesController
route("/trials", OnesController.formui)

```

---

<div class="post-metadata">

**Author:** ![PharmCat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pharmcat/32/6953_2.png) [@PharmCat](https://discourse.julialang.org/u/PharmCat)\
**Post date:** [July 18, 2025, 1:55pm UTC](https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726/2 "2025-07-18T13:55:02Z")

</div>

After some tries…

and

```julia
import Pkg; Pkg.add("StipplePivotTable")

```

got…

```julia
Failed to precompile StipplePivotTable [adab0226-ee3c-44de-8f2f-393b1bf1e936] to C:\Users\...\.julia\compiled\v1.8\StipplePivotTable\jl_A02.tmp.
ERROR: LoadError: UndefVarError: @kwdef not defined

```

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [July 21, 2025, 2:49pm UTC](https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726/3 "2025-07-21T14:49:44Z")

</div>

Are you using pre-1.9 Julia? [What does @kwdef do? - #4 by j-fu](https://discourse.julialang.org/t/what-does-kwdef-do/51973/4) says that `@kwdef` was exported from Base in version 1.9.

---

<div class="post-metadata">

**Author:** ![PharmCat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pharmcat/32/6953_2.png) [@PharmCat](https://discourse.julialang.org/u/PharmCat)\
**Post date:** [July 21, 2025, 8:42pm UTC](https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726/4 "2025-07-21T20:42:33Z")

</div>

So, yes. This was a problem with `@kwdef`, julia version 1.9 solve it.

But as i correctly understand I cant use something like `@route("/", index)` in route.jl for simple [Genie.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/Genie) mvc project.  
Seems I should manually make page with java scripts for asynchronous work.

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [July 21, 2025, 9:15pm UTC](https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726/5 "2025-07-21T21:15:46Z")

</div>

> [@PharmCat](#):
>
> @route(“/”, index)

I’ve never used Genie or Stipple, but the docs here say to define routes with the @page macro: [Introduction - Genie](https://learn.genieframework.com/framework/stipple.jl/docs#declaring-a-route)

Some other posts here suggest contacting the developers at [Genie Community](https://discord.gg/9zyZbD6J7H)

I hope that helps

---

<div class="post-metadata">

**Author:** ![PharmCat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pharmcat/32/6953_2.png) [@PharmCat](https://discourse.julialang.org/u/PharmCat)\
**Post date:** [July 27, 2025, 11:49am UTC](https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726/6 "2025-07-27T11:49:31Z")

</div>

Hi! Seems `@page` work only for `GenieFramework.jl` and not for `Genie.jl` , my task to add reactive model to existed Genie project, but I have no answer on discord yet…  
Is Genie project alive?

---

<div class="post-metadata">

**Author:** ![andreeco](https://avatars.discourse-cdn.com/v4/letter/a/d26b3c/32.png) [@andreeco](https://discourse.julialang.org/u/andreeco)\
**Post date:** [July 27, 2025, 12:42pm UTC](https://discourse.julialang.org/t/add-stipple-jl-reactive-elements-to-existed-genie-jl-app-with-controllers/130726/7 "2025-07-27T12:42:14Z")

</div>

I have a working solution, but the layout doesn’t yet match the rest of the app. This is how it currently looks (with slight modifications). Note that I use some packages not (yet?) public, which you should ignore for the moment. (Also internationalization hasn’t been implemented yet for the Stipple example in the app—it would typically involve something like @t(“panels!heading”), and so on.)

The app’s code (a little different) comes from the default setup created by my private AuthPlugin with `AuthPlugin.install`. Some important parts you will find below.

app/resources/panels/PanelsController.jl

```julia
module PanelsController
using Genie, Stipple, Stipple.ReactiveTools, StippleUI, AuthPlugin, I18nPlugin

@app PanelModel begin
    @in N = 0
    @out msg = ""
    @onchange N begin
        msg = "N = $N"
    end
end

function panels()
    @authenticated!
    locale = params(:locale, "en")
    model = @init PanelModel
    view = include(path"app/resources/panels/views/panels.jl")
    layout = filepath("app/layouts/authapp_stipple.jl.html")
     html!(view;
    layout = layout,
    context = @ __MODULE__ ,
    model = model,
    locale = locale
  )
end
end

```

app/resources/panels/views/panels.jl

```julia-auto
  [
        cell([
                p("Enter a number")
                textfield("N", :N )
            ])
        cell([
                bignumber("The value of N is", :N)
            ])
    ]

```

app/resources/layouts/authapp.jl.html

```julia-auto
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="/css/authpluginstyle.css">
    <title>Online Shop</title>
</head>

<body>

    <nav>
        <div class="container">
            <div class="logo">
                     <a href="$(linkto(:main,locale=locale))">$(@t("layout!site_name"))</a>
            </div>
            <label for="menu-toggle" class="menu-icon">&#9776;</label>
            <input type="checkbox" id="menu-toggle">
            <ul class="menu">
                <li><a href="$(linkto(:main,locale=locale))">$(@t("layout!home"))</a></li>
                <% if Main.UserApp.authenticated() %>
                    <li><a href="$(linkto(:panel,locale=locale))">$(@t("layout!panel"))</a></li>
                    <% end %>
                        <% if Main.UserApp.authenticated() %>
                            <li><a href="$(linkto(:account_index,locale=locale))">$(@t("layout!my_account"))</a></li>
                            <% else %>
                                <li><a href="$(linkto(:show_login,locale=locale))">$(@t("layout!login"))</a></li>
                                <% end %>
                                    <% if Main.UserApp.has_role(Main.UserApp.current_user(), "admin" ) %>
                                        <li><a href="$(linkto(:admin_index,locale=locale))">$(@t("layout!admin"))</a>
                                        </li>
                                        <% end %>

                                            <li class="lang-picker">
                                                <select id="langSelectMenu" onchange="window.location=this.value">
                                                    <% for_each(available_locales(I18N)) do lang %>
                                                        $(
                                                        option(
                                                        uppercase(lang),
                                                        value = switch_locale_link(lang),
                                                        selected = (lang == locale)
                                                        )
                                                        )
                                                        <% end %>
                                                </select>
                                            </li>
            </ul>
        </div>
    </nav>
    <% @yield %>
</body>

<footer>
    <div class="container">
        <p>$(@t("layout!footer_text"))</p>
        <p>$(@t("layout!footer_copyright"))</p>
        <p class="legal-links">
            <a href="$(linkto(:get_imprint,locale=locale))">$(@t("layout!imprint"))</a>&nbsp;|&nbsp;
            <a href="$(linkto(:get_privacy,locale=locale))">$(@t("layout!privacy"))</a>
        </p>
    </div>
</footer>

</html>

```

app/resources/layouts/authapp\_stipple.jl.html

```julia-auto
<!DOCTYPE html>
<html lang="en">
  <head>
     <% Stipple.sesstoken() %>
    <meta charset="utf-8" />
       <link rel="stylesheet" href="/css/authpluginstyle.css">
    <title>$(@t("layout!site_name"))</title>
  </head>
  <body>

  <nav>
        <div class="container">
            <div class="logo">
                <a href="$(linkto(:main,locale=locale))">$(@t("layout!site_name"))</a>
            </div>
            <label for="menu-toggle" class="menu-icon">&#9776;</label>
             <input type="checkbox" id="menu-toggle">
             <ul class="menu">
                <li><a href="$(linkto(:main,locale=locale))">$(@t("layout!home"))</a></li>
   <% if Main.UserApp.authenticated() %>
   <li><a href="$(linkto(:panel,locale=locale))">$(@t("layout!panel"))</a></li>
   <% end %>
   <% if Main.UserApp.authenticated() %>
    <li><a href="$(linkto(:account_index,locale=locale))">$(@t("layout!my_account"))</a></li>
   <% else %>
    <li><a href="$(linkto(:show_login,locale=locale))">$(@t("layout!login"))</a></li>
   <% end %>
   <% if Main.UserApp.has_role(Main.UserApp.current_user(), "admin") %>
      <li><a href="$(linkto(:admin_index,locale=locale))">$(@t("layout!admin"))</a></li>
    <% end %>

<li class="lang-picker">
  <select id="langSelectMenu" onchange="window.location=this.value">
      <% for_each(available_locales(I18N)) do lang %>
        $(
          option(
            uppercase(lang),
            value = switch_locale_link(lang),
            selected = (lang == locale)
          )
        )
      <% end %>
    </select>
  </li>
            </ul>
        </div>
    </nav>
 <% Stipple.page(model, partial = true, v__cloak = true, [Stipple.Genie.Renderer.Html.@yield], Stipple.@if(:isready)) %>
  </body>

 <footer>
  <div class="container">
    <p>$(@t("layout!footer_text"))</p>
    <p>$(@t("layout!footer_copyright"))</p>
    <p class="legal-links">
      <a href="$(linkto(:get_imprint,locale=locale))">$(@t("layout!imprint"))</a>&nbsp;|&nbsp;
      <a href="$(linkto(:get_privacy,locale=locale))">$(@t("layout!privacy"))</a>
    </p>
  </div>
</footer>
</html>

```

routes.jl / or plugins/authplugin.jl

```julia
...
using ..Main.UserApp.PanelsController
route("/$(patternize(I18N))/panels",PanelsController.panels, named = :panel)

```

This is a the structure of the app (a little modified).

```julia-auto
├── app
│ ├── helpers
│ │ └── ValidationHelper.jl
│ ├── layouts
│ │ ├── app.jl.html
│ │ ├── authapp.jl.html
│ │ └── authapp_stipple.jl.html
│ └── resources
│ ├── accounts
│ │ ├── AccountsController.jl
│ │ └── views
│ │ └── account_index.jl.html
│ ├── admins
│ │ ├── AdminsController.jl
│ │ └── views
│ │ └── index.jl.html
│ ├── legals
│ │ ├── LegalsController.jl
│ │ └── views
│ │ ├── imprint.jl.html
│ │ └── privacy.jl.html
│ ├── mains
│ │ ├── MainsController.jl
│ │ └── views
│ │ └── index.jl.html
│ └── panels
│ ├── PanelsController.jl
│ └── views
│ └── panels.jl
├── bin
│ ├── repl
│ ├── repl.bat
│ ├── runtask
│ ├── runtask.bat
│ ├── server
│ └── server.bat
├── THISAPP.code-workspace
├── bootstrap.jl
├── build
│ └── GenieViews
├── config
│ ├── env
│ │ ├── dev.jl
│ │ ├── global.jl
│ │ ├── prod.jl
│ │ └── test.jl
│ ├── initializers
│ │ ├── authplugin_init.jl
│ │ ├── autoload.jl
│ │ ├── channel_authorizer.jl
│ │ ├── converters.jl
│ │ ├── i18nplugin.jl
│ │ ├── inflector.jl
│ │ ├── logging.jl
│ │ └── searchlight.jl
│ └── secrets.jl
├── db
│ ├── connection.yml
│ ├── dev.sqlite3
│ ├── migrations
│ └── seeds
├── locales
│ └── en
│ ├── accounts.toml
│ ├── admins.toml
│ ├── layout.toml
│ ├── legals.toml
│ └── mains.toml
├── log
│ ├── prod-2025-07-23.log
│ ├── prod-2025-07-24.log
│ ├── prod-2025-07-25.log
│ ├── prod-2025-07-26.log
│ ├── prod-2025-07-27.log
│ └── test-2025-07-18.log
├── Manifest.toml
├── plugins
│ └── authplugin.jl
├── Project.toml
├── public
│ ├── css
│ │ ├── authpluginstyle.css
│ │ ├── genie
│ │ │ ├── prism.css
│ │ │ └── style.css
│ │ └── old?authpluginstyle.css
│ ├── error-404.html
│ ├── error-500.html
│ ├── error-xxx.html
│ ├── favicon.ico
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ ├── img
│ │ └── genie
│ │ ├── community.png
│ │ ├── contribute-2.png
│ │ ├── docs.png
│ │ ├── genie.png
│ │ └── genie-sad.png
│ ├── js
│ │ └── genie
│ │ ├── ansi_up.js
│ │ ├── ansi_up.js.map
│ │ ├── jquery.min.js
│ │ ├── jquery.min.map
│ │ ├── prism.js
│ │ └── static.js
│ ├── robots.txt
│ └── welcome.html
├── routes.jl
├── src
│ └── THISAPP.jl
├── test
│ ├── Manifest.toml
│ ├── Project.toml
│ └── runtests.jl 

```

 ![Screenshot From 2025-07-27 14-37-05](https://global.discourse-cdn.com/julialang/original/3X/4/d/4d2df12de92fe7ee50b5269fc3e8fa559abdca8f.png)  
 ![Screenshot From 2025-07-27 14-37-19](https://global.discourse-cdn.com/julialang/original/3X/1/2/12965180fb65583139baea5abb2558729b2d4261.png)  
 ![Screenshot From 2025-07-27 14-38-46](https://global.discourse-cdn.com/julialang/original/3X/3/b/3b5400f8653919db1d83fcb928152f708f5c2ee3.png)
