# \[ANN\] Magic.jl — A Simple, Data-Centric Web App Framework for Julia

**URL:** https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855
**Category:** Package Announcements
**Tags:** package, web, webapps
**Created:** [January 3, 2026, 5:42pm UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855 "2026-01-03T17:42:19Z")
**Posts on this page:** 12
**Page:** 2

<div class="post-metadata">

### Author: ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)
#### Post date: [January 11, 2026, 12:12am UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/21 "2026-01-11T00:12:30Z")

</div>

Nice work!

The question everyone is probably asking: why another Genie.jl?

Could you please compare the features of the two frameworks?

---

<div class="post-metadata">

### Author: ![nidoro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nidoro/32/220222_2.png) [@nidoro](https://discourse.julialang.org/u/nidoro)
#### Post date: [January 11, 2026, 2:48am UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/22 "2026-01-11T02:48:32Z")

</div>

Thanks for the question!

# How does Lit.jl compare to Genie.jl?

They are very different, and most of their differences arise from their different execution models.

## Genie

**Genie** adopts a reactive component model, similar to React’s component model.

- **Traditional request/response architecture** : Genie works with traditional request/response architecture, where the developer implements the response for each endpoint request.
- **Declarative UI** : The UI is implemented in a declarative way, almost as if writing HTML (and sometimes _literally_ writing HTML) but with Julia constructs.
- **Reactive model** : Simple UI updates happen automatically through reactive variable binding, but custom logic in response to user interactions is implemented exclusively via callbacks.

These characteristics makes Genie very flexible, giving the developer a lot of control on how things look and behave, which makes Genie suitable for developing any kind of web app really. But they also make implementing simple interactivity that goes beyond UI updates less straightforward, especially because of the hard separation between the UI placement and the UI behavior (which resembles the separation between HTML and Javascript).

## Lit

**Lit** adopts a top-to-bottom rerun model, like Streamlit.

- **Script rerun model** : The entire app script runs from top to bottom on every user interaction, making the execution flow intuitive and easy to reason about.
- **Imperative UI** : You build the UI using simple imperative Julia code - just call functions like `button()` and `text()` in the order you want them to appear.
- **Implicit reactivity** : State management and UI updates happen automatically through the rerun mechanism - no need to define reactive variables or wire up callbacks (although that’s also possible).

These characteristics make Lit more approachable for scientists and researchers who want to quickly turn Julia scripts into interactive web apps, without needing to learn web development concepts like callbacks, reactive programming, or the separation between UI and behavior. But since each UI event triggers a rerun of the script and a rebuild of the page layout, Lit’s execution model can also make interactions feel less responsive for expensive reruns (although it provides mechanisms like [fragments](https://lit.coisasdodavi.net/docs/build/docs/api-reference/application-logic/fragment-macro) that can help with that).

## Summary

- Genie trades simplicity for flexibility and control, which is the opposite tradeoff that Lit is trying to make.
- Their execution models are optimized for different scenarios. Genie is more suitable for traditional websites and web apps that need to provide multiple, maybe unrelated, complex functionalities that require a high degree of control. Lit is more suitable for highly specialized web apps that are focused on a single or a few tasks, and most user interactions are somewhat related to those tasks, so the script rerun model makes creating these kinds of apps really simple.

Hope that helps!

---

<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: [January 18, 2026, 12:02am UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/23 "2026-01-18T00:02:53Z")

</div>

I think Genie, as well, tries to be simple for simple tasks. (I am biased 😉) All callbacks on the client side are automatic and hidden from the user. The user has to define a button variable and write a callback on the backend, but that doesn’t look very different from the Lit-code, to be honest.

Add block: Latest developments are [precompilable apps via packaging](https://github.com/GenieFramework/StippleDemos/tree/master/AdvancedExamples/GenieTemplate) and startup times from shell to the functional webpage of 4s.  
Moreover, these days AI tools can easily write a Vue-based UI that can be directly hooked into Genie.

---

<div class="post-metadata">

### Author: ![nidoro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nidoro/32/220222_2.png) [@nidoro](https://discourse.julialang.org/u/nidoro)
#### Post date: [January 18, 2026, 2:57am UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/24 "2026-01-18T02:57:16Z")

</div>

Thanks for the balancing comment, because I’m also biased 😅

On another topic, I’ll soon change the name of the package so I can register it. I was wondering if I should “reannounce” the package with the new name, since I can’t edit neither the title nor the original post, or just comment here on the name change.

What do you guys think?

---

<div class="post-metadata">

### Author: ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)
#### Post date: [January 18, 2026, 4:19am UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/25 "2026-01-18T04:19:17Z")

</div>

> [@nidoro](#):
>
> I can’t edit neither the title

I (and other users with at least “Regular” status) can edit the title. So adding a comment to this thread is definitely an option

---

<div class="post-metadata">

### Author: ![nidoro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nidoro/32/220222_2.png) [@nidoro](https://discourse.julialang.org/u/nidoro)
#### Post date: [January 23, 2026, 2:10am UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/26 "2026-01-23T02:10:18Z")

</div>

![magic-logo-and-text](https://global.discourse-cdn.com/julialang/original/3X/3/3/334d1c45a811ada2a9d6cf87404141df52f8fa16.svg)

# 🚀 v0.4.2 - Package rename and registration: Magic.jl

- New: Package renamed from Lit.jl to Magic.jl
- New: Magic can be installed by running `pkg> add Magic`
- New: Introduced `lifetime` argument to  
[`gen_resource_path()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/application-logic/gen_resource_path-func).
- Bug-fixes: see [`CHANGELOG.md`](https://github.com/nidoro/Magic.jl/blob/ef57850a8b02b5a28e3ae2a016aa2e7ee666eefe/CHANGELOG.md) for details.

Can a Regular+ discourse member do a `Lit => Magic` search-and-replace in my first post, please? Thanks!

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [January 23, 2026, 6:21am UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/27 "2026-01-23T06:21:56Z")

</div>

Editing posts is not something a regular can do but I fixed the title. Can’t you edit your own posts? Or does that stop after some time has passed?

---

<div class="post-metadata">

### Author: ![nidoro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nidoro/32/220222_2.png) [@nidoro](https://discourse.julialang.org/u/nidoro)
#### Post date: [January 23, 2026, 10:10am UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/28 "2026-01-23T10:10:41Z")

</div>

Thanks! Yes, I can’t edit after a while.

---

<div class="post-metadata">

### Author: ![nidoro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nidoro/32/220222_2.png) [@nidoro](https://discourse.julialang.org/u/nidoro)
#### Post date: [January 31, 2026, 2:57pm UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/29 "2026-01-31T14:57:41Z")

</div>

# 🚀 v0.5.0: File Upload/Download

### New widgets [demo here](https://magic.coisasdodavi.net/image-filters).

#### Highlights

- New: Widget [`file_uploader()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/interface-elements/file_uploader-func).
- New: Widget [`download_button()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/interface-elements/download_button-func).

#### Notable

- New: Function [`make_serveable_copy()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/application-logic/make_serveable_copy-func).
- New: Function [`move_to_serveable_dir()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/application-logic/move_to_serveable_dir-func).

#### Other

- New: A `.gitignore` file is now automatically generated inside `.Magic` if  
it doesn’t exist.
- New: New [`start_app()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/application-logic/start_app-func) arguments `upload_max_size` and `upload_max_files`.
- Breaking: renamed `gen_resource_path` to [`gen_serveable_path`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/application-logic/gen_serveable_path-func).  
Additionally, this function now generates file names without extension when  
an empty string is passed to extension, which is now the default value of the  
argument.
- Change: if a non-serveable path is passed to [`image()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/interface-elements/image-func) and the path points  
to an existing file, a serveable copy is automatically created using  
`make_serveable_copy()`.
- Change: Dry-run errors do not kill the server anymore. Rather, the user can  
see the error when accessing the web app, and work on the fix while using the  
hot-reloading mechanism.
- Performance: The temporary module where the user script is evaluated is now  
session-persistent rather then recreated on every rerun.
- Deprecated: `@once` macro is deprecated, as it turns out it is not needed now  
that the app module is session-persistent.

---

<div class="post-metadata">

### Author: ![nidoro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nidoro/32/220222_2.png) [@nidoro](https://discourse.julialang.org/u/nidoro)
#### Post date: [February 8, 2026, 11:18pm UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/30 "2026-02-08T23:18:29Z")

</div>

# 🚀 v0.6.0: Number Input

![image](https://global.discourse-cdn.com/julialang/original/3X/a/b/ab533978f4b897632b87f6fce6e2bacb1aac52ee.png)  
New widget [demo here](https://magic.coisasdodavi.net/probability-density)

#### Highlights

- New widget [`number_input()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/interface-elements/number_input-func)

#### Other

- Breaking-change: Removed argument `inner_func` from [`set_page_layout()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/layout-elements/set_page_layout-func) and  
thus the ability to have a `do-end` block with this function. If you want a  
`do-end` block that does the same, implement it with [`main_area()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/layout-elements/main_area-func) instead,  
after calling `set_page_layout()`.
- Bug-fix: Fixes [`file_uploader()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/interface-elements/file_uploader-func) bug where selecting a file, clearing the  
selection and selecting the same file didn’t work.
- Bug-fix: Fixes [`file_uploader()`](https://magic.coisasdodavi.net/docs/build/docs/api-reference/interface-elements/file_uploader-func) bug where canceling the file dialog when a  
file was selected triggered a change callback, when it shouldn’t.
- Bug-fix: Dry-run logic was breaking trying to access session 0 after the  
`handle_client_left(Cint(0))` has been called.

---

<div class="post-metadata">

### Author: ![nidoro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nidoro/32/220222_2.png) [@nidoro](https://discourse.julialang.org/u/nidoro)
#### Post date: [February 14, 2026, 9:28pm UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/31 "2026-02-14T21:28:24Z")

</div>

# 🚀 v0.6.1: Sliders! ─•────

- New: [`slider()` demo](https://magic.coisasdodavi.net/curves).
- New: [`slider()` reference](https://magic.coisasdodavi.net/docs/build/docs/api-reference/interface-elements/slider-func).
- Bug-fixes: [see CHANGELOG](https://github.com/nidoro/Magic.jl/blob/main/CHANGELOG.md).

For bug report and requests, feel free to [open an issue](https://github.com/nidoro/Magic.jl/issues)!

---

<div class="post-metadata">

### Author: ![nidoro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nidoro/32/220222_2.png) [@nidoro](https://discourse.julialang.org/u/nidoro)
#### Post date: [August 12, 2026, 12:23pm UTC](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855/32 "2026-08-12T12:23:50Z")

</div>

Hello everyone! Tomorrow I’ll be at JuliaCon talking about ✨Magic! See you there!

 ![image](https://global.discourse-cdn.com/julialang/original/3X/7/9/79cd33e28ae1a0cb58b534d1b693c4d04ffa6883.jpeg)

[Previous page](https://discourse.julialang.org/t/ann-magic-jl-a-simple-data-centric-web-app-framework-for-julia/134855.md?page=1)
