-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
When deploying a Genie app behind an nginx reverse proxy with a subpath (e.g., /projects/genie_apps/), setting ENV["BASEPATH"] before loading GenieFramework does not properly configure asset URLs. Assets are requested without the base path prefix, resulting in 404 errors.
According to the official documentation, setting ENV["BASEPATH"] should automatically configure all asset paths. However, this fails silently due to a macro scoping bug in @genietools.
Environment
- GenieFramework: v3.0.1
- Stipple: v0.31.40
- Julia: 1.12.0
- Deployment: nginx reverse proxy with path stripping
Nginx Configuration
location /projects/myapp/ {
proxy_pass http://127.0.0.1:5071/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}Expected Behavior
App code (following documentation):
module App
ENV["BASEPATH"] = "/projects/myapp"
using GenieFramework
@genietools
@app begin
@in N = 0
@out msg = ""
@onchange N begin
msg = "N = $N"
end
end
function ui()
[
cell([
p("Enter a number")
textfield("N", :N)
])
cell([
bignumber("The value of N is", :N)
])
]
end
@page("/", ui)
endExpected result: Asset URLs in generated HTML should include the base path:
<link href="/projects/myapp/stipple.jl/v0.31.40/assets/css/stipplecore.css" rel="stylesheet" />Actual Behavior
Actual result: Asset URLs are generated without the base path:
<link href="/stipple.jl/v0.31.40/assets/css/stipplecore.css" rel="stylesheet" />This causes 404 errors for all assets (CSS, JS) and WebSocket connection failures.
Root Cause
When loading the app, the following error appears (caught silently by try/catch):
Loading app┌ Error: 2025-11-26 19:27:16 UndefVarError(:PLUGINS_WITH_ASSETS, 0x000000000000977e, Main.App)
└ @ Main.App ~/.julia/packages/GenieFramework/sLFpM/src/GenieFramework.jl:73
The bug is in /src/GenieFramework.jl at lines 69 and 79:
# Line 69 - inside `__genietools()` function
Genie.Assets.assets_config!([Genie, PLUGINS_WITH_ASSETS..., GenieAutoReload], host = ENV["BASEPATH"])# Line 79 - inside __genietools() function
Genie.Assets.assets_config!([Genie, PLUGINS_WITH_ASSETS...], host = Genie.config.cdn_url)The PLUGINS_WITH_ASSETS constant is defined in the GenieFramework module (line 23), but when the @genietools macro expands, the __genietools() function is defined in the user's module (e.g., Main.App). When this function tries to reference PLUGINS_WITH_ASSETS, it looks for it in Main.App where it doesn't exist, causing an UndefVarError. Compare to line 118 which works correctly:
for plugin in GenieFramework.PLUGINS_WITH_ASSETS # ← Fully qualified!The Fix
Change lines 69 and 79 to use the fully qualified module name: Line 69:
# Before (broken):
Genie.Assets.assets_config!([Genie, PLUGINS_WITH_ASSETS..., GenieAutoReload], host = ENV["BASEPATH"])
# After (fixed):
Genie.Assets.assets_config!([Genie, GenieFramework.PLUGINS_WITH_ASSETS..., GenieAutoReload], host = ENV["BASEPATH"])
Line 79:
# Before (broken):
Genie.Assets.assets_config!([Genie, PLUGINS_WITH_ASSETS...], host = Genie.config.cdn_url)
# After (fixed):
Genie.Assets.assets_config!([Genie, GenieFramework.PLUGINS_WITH_ASSETS...], host = Genie.config.cdn_url)Workaround (until fixed)
Users must manually configure all asset configs after @genietools:
module App
ENV["BASEPATH"] = "/projects/myapp"
using GenieFramework
@genietools
# Manual workaround - should not be necessary!
Genie.config.base_path = ENV["BASEPATH"]
Stipple.assets_config.host = ENV["BASEPATH"]
StippleUI.assets_config.host = ENV["BASEPATH"]
StipplePlotly.assets_config.host = ENV["BASEPATH"]
Genie.Assets.assets_config.host = ENV["BASEPATH"]
StipplePivotTable.assets_config.host = ENV["BASEPATH"]
StippleTable.assets_config.host = ENV["BASEPATH"]
StippleTabs.assets_config.host = ENV["BASEPATH"]
GenieAutoReload.assets_config.host = ENV["BASEPATH"]
Genie.config.websockets_base_path = ENV["BASEPATH"]
# Rest of app...Related Issues
Testing
I've verified the fix works by editing the local GenieFramework installation and can confirm that with the fully qualified module names, ENV["BASEPATH"] works as documented without requiring manual configuration.