I'm failing at "deploy"ing my first web-app with Dash.jl on JuliaHub

I have made a local package that takes data and sonifies it (sonification is when you map data to sound as opposed to visualization where you map it to visuals/graphs.) I now want to make some of its functionality accessible through a UI. I want people to be able to upload data (csv file), specify a handful of parameters, generate a sound file (an .ogg or maybe a .wav), play it, and download the file. I’ve settled on a web app so there’s no installation involved. I’m still learning software development and have zero knowledge of networking and all the frontend-backend stuff (what’s a port anyway?). I tried my hand at Genie, got frustrated with the GenieBuilder VSCode plugin. Tried Oxygen, but then that required more understanding of networking and http than I currently have and it seemed more suited for creating APIs (which I might consider in the future). I was able to make most progress with Dash.jl. They have decent julia-specific documentation with examples, though some of it is still lacking (like how to do user authentication). I’ve set up the UI skeleton that successfully does what I want on my local machine, though I’m just generating some random 1-second long sound for now and will plug in my actual sonification package later. I am running into issues with setting up the app on JuliaHub— issues that don’t occur on my machine.

  • When I run it on the JuliaHub IDE, the app seemingly runs fine. But the sound file it produces is empty (zero seconds long).

  • When I “Deploy” the app rather than running it using the JuliaHub IDE, I get an error that it “Failed to bundle project”.

If you have any advice on any of the specific topics above, I would be grateful.

If you have any pointers on how to get started with web apps and networking I would appreciate that too. Areas where I expect to be out of my depth:

  • figuring out how multiple users can create/download their own sound files. Right now I have the files saved in a hardcoded path that looks something like “assets/sounds/sound.ogg”. Does that mean each user will be overwriting each other’s output? Or will they each be served their own independent folders/paths? Is generating a unique filename using tempname() the solution? Will all the files that people make pile up and take up space?
  • How do I implement user authentication so that only people with a password can access the app?
  • How do I track usage per user so I know how much computing resources each person is using?

Hey, this sounds like a cool project! A few quick pointers:

run it on the JuliaHub IDE

How are you running this? Are you launching it such that you get a popup notification in VS Code that “your web server is active, click to open”? If so, Dash requires one additional configuration because VS code launches the app at a subpath like /proxy/8080/. The general structure you need to interactively work with the dash app on JuliaHub’s VS code is:

port = 8080
Dash.dash(requests_pathname_prefix="/proxy/$port/")
# ...
Dash.run_server(app, "0.0.0.0", port)

When I “Deploy” the app

How are you trying to deploy it? Are you adding it as a Custom Application?


With regards to multi-user and authentication, this can be a tricky aspect. Yes, if you’re saving directly to a hardcoded path, the users will overwrite eachothers files. Some simple authentication controls can be enabled by launching it as an application, but more robust integration with SSO and such are paid tiers of JuliaHub.

I have a global variable that determines whether I’m running the app on JuliaHub (got this idea from a JuliaHub webinar video):

JULIAHUB = haskey(ENV, "JULIAHUB_USEREMAIL")

I then do:

app =
    if JULIAHUB
        dash(; assets_folder = "../assets", serve_locally = true, external_stylesheets=["./pico.min.css"], requests_pathname_prefix="/proxy/$PORT/")
    else
        dash(; assets_folder = "../assets", serve_locally = true, external_stylesheets=["./pico.min.css"])
    end

and

run_app(host = HOST, port = PORT) =
    if JULIAHUB
        run_server(app, Sockets.localhost, port, debug = DEV_MODE)
    else
        run_server(app, host, port; debug = DEV_MODE)
    end

Yes, I run bin/main.jl in VSCode and it gives me the popup. That page looks fine. It’s just that the sound file generated is totally empty. And that’s not the behavior locally.

I did not go the custom applicaiton route. I used the create dash project feature to get the file/folder structure and edited it.

1 Like

Ah, great. Then I suspect it’s with how you’re saving your temp files — that hardcoded path is likely using a slightly different current working directory than how your environment is configured in VS Code. It can be useful to use abspath or @__DIR__ to get an absolute path that will resolve the same in all situations.

I don’t think it’s the file path, though I had some trouble getting that right at first. I just manually deleted the file, launched the app, and re-created it. I navigate to the folder where I expected the file and it was there. I downloaded it manually and played it, and it is the 1-second sound I expect.

I have the following dash html element in my layout to show the file and controls. I wonder if it has to do with the browser understanding the MIME type. It does show me the play button and volume control and everything. But I don’t understand why it would happen only on JuliaHub.

html_audio(
    src = path_to_sound_file,
    controls = true,
    style = Dict("width" => "100%", "height" => "60px",),
)

I’m also creating/saving the audio file and returning the html_audio(...) in the same callback. I wonder if the order is not being enforced.