# Multiple programs in one openrndr-js-template

**URL:** <https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718>\
**Category:** Tutorials\
**Created:** [December 9, 2024, 2:23pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718 "2024-12-09T14:23:45Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [December 9, 2024, 2:23pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/1 "2024-12-09T14:23:45Z")

</div>

In [openrndr-template](https://github.com/openrndr/openrndr-template) it’s very easy to have multiple programs in one project: we clone that repo, then have multiple Kotlin programs under under `src/main/kotlin/`. Each `main` method shows a green clickable triangle in IntelliJ Idea. Click it and the program runs.

But what about [openrndr-js-template](https://github.com/openrndr/openrndr-js-template/)? With the JS template there is no green triangle next to the main method. The way to run the program is to execute `./gradlew browserDevelopmentRun --continuous` or `./gradlew jsRun -t`, depending on the version you’re using. Once you execute that command, the build system keeps running and any time you save changes to your program, the web page displaying your OPENRNDR program reloads automatically in the web browser.

What if you would like to have several programs? The obvious approach is to clone the repo again for each new program you want to create. But that feels less convenient than having several programs in a folder.

## Easy switching of programs with Kotlin / JS

Here one approach I came up with: change `TemplateProgram.kt` to be just one line:

```kotlin
fun main() = p1

```

Then create your first program (p1.kt):

```kotlin
import org.openrndr.application
import org.openrndr.color.ColorRGBa

val p1 = application {
    program {
        extend {
            drawer.clear(ColorRGBa.PINK)
        }
    }
}

```

and your second program (p2.kt):

```kotlin
import org.openrndr.application
import org.openrndr.color.ColorRGBa

val p2 = application {
    program {
        extend {
            drawer.clear(ColorRGBa.GREEN)
        }
    }
}

```

Now, to decide which program runs, you only need to change the main method to choose between p1 and p2.

This way you could have as many programs as you want and quickly jump between them.

## Alternative solution

An approach proposed by user _ephemient_ in the Kotlin Slack:

> I’ve ended up creating separate Gradle subprojects, each depending on the common library. then `:foo:jsRun` `:bar:jsRun` etc. work as expected

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [December 10, 2024, 12:09pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/2 "2024-12-10T12:09:04Z")

</div>

## How to choose which JS program to run from HTML?

I would like to improve this so the user can choose which program runs from the HTML page. There could be a clickable menu or a dropdown, which would reload the page passing the name of the function to run to the Kotlin program.

I figured out I can pass information from HTML to the program like this: in the HTML I add a data attribute:

```html
<canvas id="openrndr-canvas" data-program="p2"></canvas>

```

In Kotlin I can read it like this:

```kotlin
val program = document.getElementById("openrndr-canvas")!!.getAttribute("data-program")!!

```

But I don’t know what to do with that string. I tried the following:

```kotlin
    println(program) // p2
    println(eval(program)) // null
    println(window[program]) // null
    println(p2) // kotlin.Unit

```

But I suspect the `eval` and `window` return `null` because `p1` and `p2` are not known in the JavaScript side of things. Using `@JsExport` didn’t help either.

I also don’t know if the dead code removal is actually getting rid of the `p1` and `p2` functions because they are not called.

If anyone has ideas I’m all ears 🙂

---

<div class="post-metadata">

**Author:** ![bluehut](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/bluehut/32/675_2.png) [@bluehut](https://openrndr.discourse.group/u/bluehut)\
**Post date:** [December 10, 2024, 6:34pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/3 "2024-12-10T18:34:41Z")

</div>

Hey @abe, here’s my attempt at that this morning. I expect there’s a better way of reloading the script in `index.html` than the way I’ve done it!

> <https://github.com/nfletton/openrndr-js-template/blob/demo/multiple-apps/src/commonMain/kotlin/TemplateProgram.kt>

> <https://github.com/nfletton/openrndr-js-template/blob/demo/multiple-apps/src/commonMain/resources/index.html>

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [December 10, 2024, 6:54pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/4 "2024-12-10T18:54:59Z")

</div>

Nice! 🙂 That’s definitely progress 📈

I have a few ideas to try now… Thank you!

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [December 11, 2024, 1:02pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/5 "2024-12-11T13:02:49Z")

</div>

This is what I came up with. I moved all the logic into the main method, which takes care of running whatever program you specify in a GET parameter in the URL, and also creates a clickable menu of programs you can run.

```kotlin
import kotlinx.browser.document
import kotlinx.browser.window
import org.w3c.dom.url.URLSearchParams

// Add your application functions here
val myApps = listOf(
    ::bouncyBubbles,
    ::justGreen,
)

fun main() {
    // Create a map where function names point to the actual functions
    val appMap = myApps.associateBy { it.toString().lines()[1].trim().dropLast(3) }

    // Take the GET argument from the URL specifying which program to run. If missing take the first.
    val currentProgram = URLSearchParams(window.location.search).get("program") ?: appMap.keys.first()

    // Launch the selected program
    appMap[currentProgram]!!.invoke()

    // Create a div with clickable links
    val div = document.createElement("div")
    div.innerHTML = appMap.keys.joinToString(" ") { programName ->
        if (programName != currentProgram)
            """<a href="?program=$programName">$programName</a>"""
        else
            """<span>$programName</span>"""
    }
    // Prepend the div at the top of the HTML
    document.body?.prepend(div)
}

```

The user needs to update the `myApps` list, and create functions as in @bluehut 's example (ideally one per file).

```kotlin
fun bouncyBubbles() = application { ... }
fun justGreen() = application { ... }

```

 ![2024-12-11_13-52](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/2673ce03a11068db3f59c0d498c22b34040c8bd7.png)

It’s also pretty close to live coding. When I save my changes to my OPENRNDR Kotlin programs the browser refreshes in ~2 seconds (on my 2014 laptop).

It refreshes twice though. ~~I wish I know why.~~ [Workaround:](https://slack-chats.kotlinlang.org/t/8053383/why-does-my-browser-auto-refreshes-twice-to-show-changes-mad) add `sourceMaps = false` inside `commonWebpackConfig` in `build.gradle.kts`. Then it refreshes just once 🎉 But source maps are gone, which may be useful for debugging.

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [December 12, 2024, 12:18pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/6 "2024-12-12T12:18:31Z")

</div>

Next, I’m adding those links as an overlay on top of the visuals (so one can use the full window for visuals), and a `source` button to view the syntax-highlighted source code of the running program 🙂

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [December 13, 2024, 1:00pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/7 "2024-12-13T13:00:08Z")

</div>

Latest iteration:

I will post the actual code online 🙂

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [December 13, 2024, 4:00pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/8 "2024-12-13T16:00:45Z")

</div>

And here the [live demo](https://openrndr.github.io/openrndr-js-template/?program=justGreen) that gets built automatically by a workflow on GitHub any time I commit changes 🙂 🎉

ps. I really wanted to have

```kotlin
val myApps = listOf(
    ::bouncyBubbles,
    ::justGreen,
    ::fabulousPink,
)

```

instead of

```kotlin
val myApps = mapOf(
    "bouncyBubbles" to ::bouncyBubbles,
    "justGreen" to ::justGreen,
    "fabulousPink" to ::fabulousPink,
)

```

because repeating words is a potential source of typos. I did have a working version looking like the first solution, but when doing a production release, the system renames variables and methods to one-character names, and the whole thing falls apart because function names are no longer found.

Even better would be not needing that list/map at all, so the user could create programs, and they would be somehow detected.

Maybe doable with Gradle, but auto-generating source code files sounds a bit too magical 🪄 , even to me XD. Another option would be to add tweak openrndr-js to enable multi-app usage…

Lets see 🙂

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [December 14, 2024, 3:26pm UTC](https://openrndr.discourse.group/t/multiple-programs-in-one-openrndr-js-template/718/9 "2024-12-14T15:26:12Z")

</div>

I couldn’t resist and wrote a Gradle task that generates that list of a apps 🙂

Since it only runs when request by the user, I think this should be ok.

Any time the user adds an app they should double click on the task to update the list. I’ll use it and see how it goes.
