Simple and Cross-Platform DesktopApp Demo built on Phoenix with native menus, notifications, and full English/Spanish translation
-
desktop (elixir-desktop):
Desktopis a library that can encapsulate or wrap aPhoenix web applicationand render it in awxWindow.wxWindow, in turn, is part of theErlangwxlibrary, which is a binding ofwxWidgets(originally written inC++) for Erlang, allowing the building of local-first apps forWindows,macOS,Linux,iOS, andAndroidusingPhoenix LiveViewandElixir. -
Menu bar: Similar to native applications.
-
Notifications: Both native, as well as in the form of toasts (
flash messages), provided by the Phoenix framework, orpop-upsobtained through theJavaScriptlibrarySweetAlert2. -
Ability to select the app's language: Enabled in the menu bar allows complete translation of the application using the Elixir
Gettextlibrary. -
Data persistence in a SQLite3 database: This database stores the
Todosand the application language selected by the user. The application performsCRUDoperations on this database. SQLite databases are ideal for the organized storage of desktop application data. -
Ability to create/restore data backups: The database files are compressed into a
zip fileto/from the path chosen by the user. -
Using native dialogs: The
desktoplibrary does not provide a direct way to usenative dialogs, but by usingwxDirDialogandwxFileDialogfrom the Erlangwxlibrary, we can call them to select the folder where the data backups are stored or the backup file, respectively.
-
-
Prerequisites: Obviously, you'll need to install
ElixirandErlang/OTP(because you'll need to use its virtual machine). I recommend doing this throughasdf. This will allow you to have multiple versions of Elixir installed and easily switch between them per project or set a global version for the system. Likewise,asdfwill also allow you to installNodeJS(and, similarly, manage its different versions), which is required to install theTailwind CSSanddaisyUIJavaScript packages.I strongly recommend you to follow the recommendations made here to create a more complete Erlang/OTP installation that will allow you to use the Erlang binding for
wxWidgets, something essential to create the desktop application with theDesktoplibrary, as well as prepare your system as indicated here.As of this writing, the latest version of the Phoenix framework (v1.8.1) has an issue with the autocompletion of
Tailwind CSSutility classes inVScode(and other editors), as well as with the integration with itsdaisyUIplugin. The workaround requires manual installation of Tailwind CSS and daisyUI vianpm, although CSS compilation is still done by Phoenix via thetailwind/esbuildbinaries. This is the solution I have adopted in this application.The previous version of the
Desktoplibrary would throw errors when trying to create menu structures fromXML. This was due to the change made inPhoenix/Phoenix LiveView. The current version ofDesktophas fixed this problem, but requiresPhoenix >= 1.8to run correctly. If you intend to create aDesktopapplication and you still have Phoenix code generators from previous versions installed on your system, you will need to upgrade by first uninstalling (mix archive.uninstall phx_new) and then installing again (mix archive.install hex phx_new), which will install the Phoenix generators binaries inyour_home_folder/.asdf/installs/elixir/1.18.4/.mix/archives/, if you installed Elixir-Erlang/OTP usingasdf. -
Usage: Once you've completed the above requirements, you're ready to begin. Clone the repository and navigate to the project root to run the following command in the terminal:
$ mix installerThe above command is a
mix task(analias) that I created to simplify the installer generation. It downloads the Elixir dependencies, downloads and installs the JavaScript dependencies vianpm/NodeJS(Tailwind CSS,daisyUI, andSweetAlert2. For the need to install Tailwind CSS/daisyUI, see one of the previous notes), generates the assets that Phoenix needs for production, and finally, creates the application installer appropriate for your OS/version. This step may take more or less time to execute depending on your machine.The installer is created in the
_build/prod/folder with the name and version determined in themix.exsfile (_build/prod/Todolist_WebUI_Desktopapp-0.1.0-linux-x86_64.run, e.g.).Now run it. If you don't pass a path, it will install the application in your home directory. However, I recommend passing the path where applications are usually installed on your system:
$ ./_build/prod/Todolist_WebUI_Desktopapp-0.1.0-linux-x86_64.run $HOME/.local/bin # e.g. on LinuxThis command will unzip the folder containing the application to the given path. This creates a
self-containedfolder containing everything needed to run the application on any system without having to install any dependencies: the application binaries, theBEAM VMandruntime, all the necessarygraphics librariesand dependencies for your OS, and theassetsused by any Phoenix application. It also generates a launcher (*.desktopfile in Linux) that will make the application appear in your start menu. Likewise, (on Linux) another launcher will be created in$HOME/.config/autostart/that will launch the application when you log in to your system (but you can remove it if you don't want this behavior).Also, when the application starts for the first time, the
SQLite3database files will be created (in the appropriate path depending on your OS) and the connection to the database will be established. This is the standard behavior of a Phoenix application with anSQLite3database; however, this application is configured to also perform themigrationsthat create the necessary tables within the database upon startup, which is more suitable for a desktop application.
-
-
If you've installed all the requirements outlined in the previous steps and want to modify the application, to improve your development experience you can install 3 excellent extensions if you work with VScode:
ElixirLS,phoenixframeworkandTailwind CSS IntelliSense, and follow the instructions to correctly configure your work environment. Also, keep in mind what we said in the second note of thePrerequisitessection because in the new version of Phoenix (>= 1.8) in VScode and other code editors, the autocomplete function of the TailwindCSS/daisyUI utility classes does not work and you will have to make the modifications indicated in that note.Having made these considerations, clone the repository and from the terminal enter the project root:
$ git clone https://github.com/emarifer/elixir_desktop_webui_todoapp.git $ cd elixir_desktop_webui_todoappNow you can download the Elixir and JavaScript dependencies (Tailwind CSS/daisyUI), create the database, and perform migrations, all with a single command:
$ mix setupAnd now you can start the application in development mode with:
$ mix phx.serverYou can also do it using Elixir's interactive shell if you prefer to run something in IEx:
$ iex -S mixIf you want to access the user interface
dev tools, just like you would when developing a web application, you can do so with this trick: copy the address similar tohttp://localhost:4000?k=IOIQTAREYWKCO3MMP3RBSXS62RIFYVS5RRLH7HYKTM7RGBWVDMKQthat appears in the terminal and paste it into your browser's address bar. Now you can open thedev toolsin your browser!Hacky Trick: If you want to access the
dev toolswhen starting the application inproduction/release, you can do the following: navigate to the folder where you already have the application installed using the terminal, select the shell scriptTodolist_WebUI_Desktopapp; if you run it, the application will start without being linked to the current console process, but if you pass it thestartargument (as when running anyElixir Release), then it will be linked:$ ./Todolist_WebUI_Desktopapp start # in $HOME/.local/bin/Todolist_WebUI_Desktopapp/, e.g. from LinuxSince the process is linked to the current console, you'll see all its
logs. Copy the address you see in them into your browser and open itsdev tools😉.If you're using
Linux-Ubuntu(or derivatives), it's quite possible that when you open the application window, it will be blank. This is a known issue that can be resolved by exporting the following environment variable for the current terminal session:$ export WEBKIT_DISABLE_COMPOSITING_MODE=1Every time you save changes to your code, the application window will reload.
- Official website: https://www.phoenixframework.org/
- Guides: https://hexdocs.pm/phoenix/overview.html
- Docs: https://hexdocs.pm/phoenix
- Elixir Guides: https://hexdocs.pm/elixir/introduction.html
- Forum: https://elixirforum.com/c/phoenix-forum
- Source: https://github.com/phoenixframework/phoenix
- Phoenix LiveView: https://hexdocs.pm/phoenix_live_view/welcome.html
- Ecto: https://hexdocs.pm/ecto/Ecto.html
- Ecto SQL: https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.html
- Desktop (elixir-desktop): https://hexdocs.pm/desktop/readme.html
- Deployment (elixir-desktop): https://github.com/elixir-desktop/deployment
- Gettext: https://hexdocs.pm/gettext/Gettext.html
- Phoenix PubSub: https://hexdocs.pm/phoenix_pubsub/Phoenix.PubSub.html#content
- wx the erlang binding of wxWidgets: https://www.erlang.org/doc/apps/wx/chapter.html