Introduction
jDeploy allows Java developers to deploy desktop applications as native bundles on Macintosh, Windows, and Linux. Unlike other deployment solutions, jDeploy doesn’t require any third party tools (other than OpenJDK), and can build native installers for Mac, Windows, and Linux on any platform. For example, you can build a native Windows installer on Linux or Mac, and vice versa. Applications deployed using jDeploy can also receive updates automatically as they become available, so you can be assured that your users will always be working with the latest version of your application.
Note
|
Apps distributed with jDeploy can also be installed as command-line apps using npm . See Command-line Distribution for more information about that.
|
GUI
jDeploy provides a graphical user interface that makes it easy to configure your app’s deployment settings such as icons, splash screens, file associations, etc… After you’re satisfied with the settings, press "Publish", and it will publish your app so that users can download the latest version.

Download Page
When you publish your application using jDeploy, your users will instantly be able to download your app at https://www.jdeploy.com/~YOUR-APP-NAME

The download page includes links for Windows, Mac, and Linux. At time of writing, Linux includes two different download types: .deb, and .bin, but more may be added as there is demand.
Note
|
You can also use the Github Action to add your installers as artifacts on your app’s release page. |
The Installer
The installer that is downloaded from the download page will prompt the user to select relevant installation options, such as whether to add a link in the Dock (Mac only), or the Start Menu (Windows Only), and whether to enable auto-update (default "On").

After selecting the desired options, the user can press the Install button, which will trigger the installation of your app. This will only take a second, and, when complete, the user will be prompted with a dialog as follows:

In this example, clicking on the "Open SwingSet2", will open the app as shown below:

Mac Codesigning and Notarization
When you deploy your app with jDeploy, you don’t need to sign or notarize it as you normally would when deploying a Mac application. jDeploy handles all of this so you don’t need to worry about it. You don’t require any Apple developer certificates; nor do you require an Apple developer account. Mac users running the latest versions of MacOS will be able to download and install your app, by simply downloading it from the jDeploy download page, and running the installer.
If, however, you do have an Apple Developer account, and want to sign and notarize your app, you can do this as well, via a convenient Github action.
Java Versions
jDeploy currently uses Azul’s OpenJDK REST API to download an appropriate JRE, or JDK on demand. You can specify which version of Java your app requires in your jDeploy config file. You can also specify whether your app requires a full JDK, or JavaFX. Deploying JavaFX apps with jDeploy is actually quite painless - as you don’t need to bundle the JavaFX jars or modules with your distribution.
All versions of Java should work. If a new version comes out that isn’t yet in the "drop-down" list of the GUI, you can just enter the version manually in the package.json file.
GitHub Action
You can automate your deployments using the jDeploy Github action. Publish your app as a GitHub release, or using npm’s repository.
Publish to npm and/or GitHub
jDeploy supports hosting your releases on both GitHub (as release artifacts) or npm. When you publish a new version, your app will automatically detect this the next time it is launched, so that you can be sure that your users are always working with your latest version.
Important
|
Publishing the app to npm requires an NPM account. This takes a few seconds to set up. You can simply type npm adduser and follow the prompts. full instructions on the NPM site. If you already have an account but haven’t logged in on the current machine you would use npm login to login and store the credentials locally.
|
Git Branch Synchronization
The jDeploy GitHub action will allow you to publish native apps that stay in-sync with changes in a particular branch of your repository. When you commit changes to that branch, the app will automatically receive the update the next time it is launched. This all happens through the magic of Github actions.
Getting Started
Installation
Download and install the jDeploy desktop application for your platform. macOS, Windows, and Linux are supported.

Main Menu
The jDeploy main menu, shown below, provides 3 main options:
-
Open Project - Use this if you have already set up your application with jDeploy.
-
Import Project - Use this if you have an jar file that you would like to deploy.
-
Create New Project - Use this if you would like to create a new project from scratch.

Import Project: Convert your existing jar file to a native application
If you already have a jar file (or a project that produces an executable jar file), you should use the "Import Project" option in the main menu to configure jDeploy to deploy your jar file as a native application.

Either enter the path to your project’s directory in the provided text field, or press "Select…" to select it from a file chooser dialog.
Tip
|
Generally, it is best to select the directory of your project, which is the one containing your pom.xml file, or your build.gradle file.
|
If you intend to use GitHub actions to automatically deploy your application in response to commit and tag events, then you can check the "Generate GitHub Workflow" checkbox. This will generate a basic workflow in the .github/workflows
directory.
Once you have selected your project directory, press "Import"
Note
|
Creating a jdeploy project will generate a file named package.json in your project’s directory. This file will be used to store the configuration for deploying your application.
|
This should open the project editor dialog, as shown below:

This dialog allows you to configure your desktop application. You can configure such things as: . App icon . Installer splash screen . Java version . File and URL associations . Display name . Publish targets
See [project-editor] for more information about the fields and options available in the project editor.
jDeploy does its best to find your app’s main jar file. You should see the path (relative to project root) in the JAR File field. If this is incorrect, or empty, the first thing you’ll want to do is to correct this. Press the "Select…" button to select the correct jar file.
Tip
|
Make sure that you have built your project so that there is a jar file to find! |
The name and title fields will also be populated with default values, based on the name of your Jar file. Inspect these and change as desired. The critical fields, for publishing your application, are the Name, Version, Title, and Author fields.
The Name field should be your globally unique project name. If you are publishing to npm, for example, this will be the name of your npm package.
The Title field is the human-readable title of your application. This is what will be displayed in the application menu, and in the installer.
Note
|
Importing a project will create a package.json file in your project’s directory. This file will be used to store the configuration for deploying your application. You’ll also notice a .jdeploy directory, which is used to store metadata used by the jDeploy desktop application. Additionally, if you selected the "Generate GitHub Workflow" option, you’ll see a .github/workflows directory with a workflow file named jdeploy.yml that will be used to deploy your application to GitHub releases.
|
Publishing your application
Currently (as of jDeploy 5.0.0), jDeploy supports publishing to the following platforms:
-
GitHub Releases
-
npm
To publish your application, you’ll need to configure the Publish Targets section of the project editor dialog. By default, you’ll find that npm
is selected as a publish target. If you don’t want to publish to npm, you can uncheck this option.
Generating an npm token
For the purposes of this "Getting started" tutorial, we are going to publish to npm. To do this, you’ll need to have an npm account, and you’ll need to generate a token that you can use to authenticate with npm. You can generate a token by visiting the following URL:
Replace your-username
with your npm username.
Click on the "Generate Token" button, to create a new token. You can either choose a granular access token or a class token. Either will work, as long as it has publish permissions.
Copy this token into a safe place. You’ll need it in the next step.
Publishing to npm
Now, back in the jDeploy project editor for your application, press the "Publish" button in the lower right of the dialog.
Important
|
Before publishing, you should save any changes you’ve made to the configuration by selecting "File" > "Save" from the menu, or simply pressing Ctrl+S (or Cmd+S on macOS).
|

You will be prompted to confirm that you want to publish your application, as shown below:

Click "Yes" to proceed.
Next, you’ll be asked to select the npm account you wish to use to publish your application. If you haven’t already configured an npm account, you can do so by pressing the "Add Account" button.

Since this is our first time using jDeploy, you’ll need to add an account.

The account name field name be any identifier you choose. It doesn’t need to match your npm username. It is just for you to identify the account.
The Token field is where you’ll paste the token that you generated in the previous step.
Note
|
The token will be stored in your system’s keychain, so you won’t need to enter it again in the future. |
Press "Save", to return to the account selection dialog. Then press "Continue" to proceed with publishing your application.

Depending on your npm account settings, you might be prompted to enter a one-time password (OTP) to authenticate. If so, you’ll see a dialog like the one shown below:

If you have set up your npm account for 2-factor authentication, then you can simply enter the code from your authenticator app. If you haven’t set up 2-factor authentication, then you have two options:
-
Set up 2-factor authentication for your npm account.
-
Adjust your account settings to allow publishing without 2-factor authentication.
See the npm documentation for more information on how to set up 2-factor authentication for your npm account.
Once you have entered the OTP, or if you don’t need to enter one, the publishing process will continue.
If all goes well, you should see a dialog like the one shown below:

You can click on "View Download Page" to download your application. The URL for this download page will remain constant for all future releases of your application, so you can link to it from your website, or share it with your users.

Note
|
The download page is hosted on jdeploy.com, and provides downloads for your app’s installer, however, it doesn’t actually host your app. The installer that users download from this page will download your app from npm’s repository at install time. |
Installing your application
To install your application, simply download the installer for your platform from the download page, and run it. The installer will guide you through the installation process.
E.g. On windows, it will download the installer as an exe file. You can run this directly from your browser’s downloads:

On macOS, it will download a .tar.gz file with an .app file inside. You can extract this file and run the .app file to install your application.
Tip
|
jDeploy also supports DMG file distribution for macOS, but this requires some configuration, as well as set up for code signing. This is not covered in this "Getting Started" tutorial. |
Linux provides 3 different options for installation:
-
.deb package
-
.bin installer
-
Command-line installation snippet that you can run in your terminal.
Choose the option that is most appropriate for your system.
The vanilla installer UI is shown below. We’ll cover later, how you can customize this to match your app’s branding.

On Windows it provides options to add to the Start menu, as well as adding a desktop shortcut. On macOS it will provide an option to add to the Dock instead of the start menu.
Users can select the auto-update settings that they prefer. Recommended to leave it "On" so that the application will automatically download updates for your application when they are available.
Click the "Install" button to proceed with the installation.
This will prompt you with a confirmation dialog as shown below:

Click "Yes" to proceed with the installation.
Tip
|
By default this says that the application’s home page is at npmjs.com. If you published to GitHub releases, it would, instead, show the URL to your GitHub repository. Later we’ll learn how to change this to point to your own website. |
Important
|
This confirmation step is important to prevent malware, and provide the user with a change to verify that the software is from a trusted source. The jDeploy installer is signed using the jDeploy’s code signing certificate, so it should be trusted by most systems so that you don’t need to jump through the hoops of code-signing yourself. So the installer is considered trusted, but the user must still confirm that they trust the software that the installer is installing. |
Once you have confirmed, the installation will proceed.
If all goes well, you should see a dialog like the one shown below:

Click "Open <Your application name>" to launch your application.

Notice, that the application should also be available via the start menu.

Publishing to GitHub Releases
If you would like to publish your application to GitHub releases, instead of, or in addition to, npm, you can do so by configuring the Publish Settings tab of the project editor dialog.

Select the "Publish releases to GitHub" checkbox to enable this option. You should also provide the URL to the GitHub repository where you would like to publish your releases.
Important
|
This GitHub repository needs to be public so that the jDeploy installer is able to download updates from it. You may use a different repository than where your application sources are stored, if you want to keep your sources private. This repository need just be used to publish releases. |
Generating a GitHub Personal Access Token
To publish to GitHub releases, you’ll need to generate a personal access token. See the GitHub documentation for details on creating your token. You can use a classic token or a fine-grained token, as long as it has permission to publish releases.
Publishing to GitHub
Once you have configured your GitHub repository and generated your personal access token, you can press the "Publish" button in the project editor dialog to publish your application.
In the project editor, click on the "Publish" button in the lower right of the dialog.

This will prompt you to confirm that you want to publish your application.

Click "Yes" to proceed.
Next, you’ll be asked to select the GitHub account you wish to use to publish your application. If you haven’t already configured a GitHub account, you can do so by pressing the "Add Account" button.

If this is your first time publishing, you’ll need to add an account, by pressing "Add a new account". This will open a dialog where you can enter your GitHub username and personal access token.

You can enter anything you like into the "Account Name" field. This is just for you to identify the account. The "Token" field is where you’ll paste the personal access token that you generated in the previous step.
Press "Save" to save the account, and then press "Continue" to proceed with publishing your application.
While publishing, you’ll see a progress dialog like the one shown below:

If all goes well, you should see a dialog like the one shown below:

You can click on "View Download Page" to view the download page for your application. This page will provide a link to download the installer for your application.
Create New Project
If you are starting from scratch, you can use the "Create New Project" option in the main menu to create a new project based on a selection of templates. Some of the templates available include:
-
swing - A Swing application
-
javafx - A JavaFX application
-
codenameone - A Codename One application
-
fxgl- An FXGL application
All templates currently use Maven as the build system.

Most of the "Create New Project" dialog should be self-explanatory. You can select the template you want to use, and enter the name of your project. The "Group ID" and "Artifact ID" fields are used to generate the Maven coordinates for your project.
You can select either GitHub or npm as a publish target. If you select GitHub, you’ll need to provide the URL to your GitHub repository. If you select npm, you’ll need to specify the name of your npm package. These options can be configured also later in the project editor.
Press "Create Project" to create your new project. Upon completion, the project editor dialog open, allowing you to configure your application, further.
Tip
|
You can open the project’s directory in Finder/File explorer by selecting "File" > "Open Project Directory" from the menu. ![]() |
You can open the project in your preferred IDE.
Deploy as a Web App (CheerpJ)
jDeploy includes support for deploying Java Swing/AWT-based applications as progressive web apps. From the CheerpJ website:
CheerpJ is a WebAssembly-based Java Virtual Machine for the browser. It has extensive compatibility with Java 8 and provides a full runtime environment1 for running Java applications, applets, libraries, and Java Web Start / JNLP applications in the browser without plugins.
This is currently experimental. Limitations include:
-
Only Swing/AWT UIs are supported currently. No JavaFX.
-
Some 3rd-party java libraries may not be supported. You can try to build and find out.
Important
|
Please read the CheerpJ licensing options before deploying your application, to ensure that you are fully compliant. |
To preview your app running as a web app, you can press the "Web Preview" button in the project editor dialog. This will build your application as a web app, then open a dialog for you to preview it in your browser, as shown below:

You can open the web preview in your browser by pressing the "Open in Browser" button.
The following screenshot shows the SwingSet2 demo running as a web app in the browser:

Command-line Usage
If you eschew GUIs and prefer to work on the command-line, the following instructions are for you.
In terminal, navigate to a directory containing an executable .jar file that you would like to publish.
$ jdeploy init
This will generate a package.json file with settings to allow you to publish the app to npm.
The package.json file
After this command completes, you should open the package.json in your text editor to adjust the settings to your requirements. The following is the package.json file for the SwingSet2 app.
{
"bin": {"swingset2": "jdeploy-bundle/jdeploy.js"},
"author": "Oracle",
"description": "The Swing Sampler demo, packaged by jDeploy",
"main": "index.js",
"preferGlobal": true,
"repository": "https://github.com/shannah/swingset2",
"version": "1.0.5",
"jdeploy": {
"jar": "target/swingset2-1.0-SNAPSHOT.jar",
"javaVersion" : "11",
"title" : "SwingSet2",
"javafx" : false,
"jdk" : false
},
"dependencies": {"shelljs": "^0.8.4", "njre": "^0.2.0"},
"license": "GPLv2+Classpath Exception",
"name": "jdeploy-demo-swingset2",
"files": ["jdeploy-bundle"],
"scripts": {"test": "echo \"Error: no test specified\" && exit 1"}
}
The package.json specification can be found here. The jdeploy object includes additional properties that you can use to customize how your native desktop bundle. It includes the following keys:
- jar
-
The path (relative to the package.json file) to your executable jar file. It the
jdeploy init
command worked correctly, it should already point to the correct jar file. If it found the wrong file, or the name of the file changes later, you may need to adjust this value.Type: String
- javaVersion
-
The Java runtime version required to run your app. At time of writing the default is "11". You can also use "8", or "17" here. In theory any version that Azul's API supports can be used here.
ImportantThis value should not include only the major version. E.g. "11", NOT "11.0". Also, this value should be a string, not an int. I.e. "javaVersion" : "11"
, NOT"javaVersion" : 11
.Type: String
- title
-
Your app’s title. This is the human-readable name of your app. It will be used on the download page, and also as the app’s file name when downloaded.
Type: String
- jdk
-
Whether the app requires a full JDK to run. If true, then the app will be run with a JDK - not just the JRE. Unless your app actually needs a JDK (i.e. access to javac, etc…), you should keep this
false
as the JDK is substantially larger than the JRE.Type: boolean
- javafx
-
Whether your app requires JavaFX. If true, then the app will run with a JRE/JDK that includes JavaFX.
Type: boolean
Icons and Splash Images
There are three specially-named images that, if placed in the same directory as your package.json, will be used by jDeploy. They are:
- icon.png
-
An icon for your app. If you don’t include this file, it will use a generic jDeploy icon for your app.
Recommended specifications: 512x512 pixels, with transparency.
NoteIf you are using JavaFX you should also add your icon to your app’s Stage using stage.getIcons().add(…)
as there is a bug in Ubuntu that will cause the app’s icon to appear blank in the taskbar otherwise. - splash.png/splash.jpg/splash.gif
-
A splash image to be displayed while your app is loading.
NotejDeploy uses the -splash:splash.gif
CLI argument at runtime to add the splash screen. This apparently causes some issues with JavaFX. Currently, the recommendation for adding splash screens to JavaFX apps is to use a Preloader. Example here. - installsplash.png
-
A splash/info screen to be displayed in the installer for your app.
Publish App to NPM
Tip
|
This section describes how to publish to npm, but you can alternatively publish to Github releases using the jDeploy github action. |
Important
|
In order to publish your app with jDeploy, you need to have an npm account. For instructions on creating your free npm account see this tutorial. |
You must be logged into your npm account in the command-line in order for the jdeploy publish
command to work. If you already have an npm account you can login with the npm login
command. See this tutorial for more details.
Once you have logged into your npm account and configured your package.json file to your liking, you can publish your app to npm with the following command:
$ jdeploy publish
If it completes successfully, you’ll be able to download your app bundles at https://www.jdeploy.com/~YOUR-APP-NAME where YOUR-APP-NAME
is the name specified in the name property of your package.json file.
Publishing New Versions
If you make changes to your app, and want to publish a new version, you can increment the version property of your package.json file, and run jdeploy publish
again.
File Associations
jDeploy allows you to associate your application with file mimetypes and extensions. For example, you can associate your application with .txt files so that it is listed as one of the options when users right click on a .txt file and select "Open with". Additionally, your application will respond when text files are dropped onto your app icon.
You can add file associations in the "Filetypes" tab of the GUI. Alternatively see File Associations In package.json for a description of how to add the associations directly in the package.json file.

To add a new document type, press the button. To remove a document type, press the
button in the corresponding row.
Each file type row includes the following fields:
- Extension
-
The file extension. E.g. txt, html, mp4. Do not include the "dot".
- Mimetype
-
The corresponding mimetype of the extension. You should provide both the extension and mimetype in each row, as some operating systems rely more heavily on one than the other.
- Editor
-
Check this box if your app can edit files of this type. Leave it unchecked if it can only view files of this type.
- Custom
-
Check this box if this is a custom mimetype. This is used on Linux as an indicator that the installer needs to register the mimetype in the system’s mimetype database.
File Associations In package.json
Such file associations can registered by adding the documentTypes property to the jdeploy object. E.g.
...
"jdeploy" : {
...
"documentTypes" : [
{
"extension" : "txt",
"mimetype" : "text/plain",
"editor" : true
}, {
"extension" : "html",
"mimetype" : "text/html"
}, {
"extension" : "jdtext",
"mimetype" : "application/x-jdeploy-demo-texteditor-jdtext"
}, ....
],
}
...
The documentTypes array may contain zero of more object entries, with the following properties:
- extension
-
The extension of the file type. E.g. txt, html, etc…
- mimetype
-
The mimetype of the file type. E.g. text/plain, text/html, etc…
- editor
-
Boolean indicating whether the application can edit the file type. If omitted or
false
, the application will be regarded as a "viewer" for this file type. - custom
-
Boolean indicating whether this is a custom file type for your app. This is currently only used for .deb installers so that it knows whether it needs to register the mimetype with the system. Default is
false
Accessing Files In Java
When a user launches your app by opening an associated file type (e.g. by dragging the file on your app icon, or selecting your app in the "Open with" menu), you will likely want to know which file triggered the launch. On Windows and Linux, these file paths are passed as arguments in your main()
method. E.g.
public static void main(String[] args) {
if (args.length > 0) {
System.out.println("Received "+args.length+" file arguments");
for (int i=0; i<arg.length; i++) {
System.out.println("File: "+args[i]);
}
}
}
On Macintosh, you need to use the java.awt.Desktop class to be notified when the user opens a file with your app.
FileHandler
interface with the Desktop
class to be notified when users open files with your app on Mac OS.import java.awt.*;
import java.awt.desktop.OpenFilesHandler;
import java.awt.desktop.OpenFilesEvent;
public class HelloApplication {
static {
try {
Desktop.getDesktop().setOpenFileHandler(new FileHandler());
} catch (Exception ex){}
}
...
public static class FileHandler implements OpenFilesHandler {
@Override
public void openFiles(OpenFilesEvent e) {
System.out.println("Received open files event "+e.toString());
}
}
...
}
URL Schemes
jDeploy allows you to register your application to open URLs with specific schemes so that, when a user clicks on a link with that URL scheme, your application will be launched.
You can add URL schemes in the URLs tab of the GUI. To add url schemes directly in the package.json file, see URL Schemes in package.json.
For example, you if you specify the "myapp" URL scheme, then you could add a link on your website as follows:
<a href="myapp:some-data">Open My App</a>
When users who have your app installed click on this link, they will be prompted to launch your app. When you app launches, you’ll be able to detect the specific URL that was clicked, so that you can respond appropriately.
The URLs tab is shown here:

In the above example, the app would be associated with URLs like "jdtext:xxxxxx".
Adding Multiple URL Schemes
To add multiple URL schemes, you can simply add multiple values separated by commas in the text field.
e.g.
"myapp,podcast,feed"
In this case the app would respond to URLs like "myapp:…", "podcast:…", and "feed:…"
Standard URL Schemes
You can associate your app with both custom schemes, and standard schemes. For a list of standard URL schemes that you might want your app to be ableto handle, see this wikipedia entry.
URL Schemes in package.json
Do this by adding a urlSchemes property of the jdeploy object with an array of string schemes.
E.g.:
"jdeploy" : {
...
"urlSchemes" : ["jdtext"]
...
}
With the above configuration in the package.json file, your app would be launched when the user clicks links like "jdtext:…." in a webpage.
E.g.
...
<p>Testing the custom jdtext url scheme. <a href="jdtext:hello">CLick here</a></p>
...
Accessing URLs In Java
When a user launches your app by clicking on a link, you will likely want to know the URL that triggered the launch. On Windows and Linux, these URLs paths are passed as arguments in your main()
method. E.g.
public static void main(String[] args) {
if (args.length > 0) {
System.out.println("Received "+args.length+" URL arguments");
for (int i=0; i<arg.length; i++) {
System.out.println("URL: "+args[i]);
}
}
}
On Macintosh, you need to use the java.awt.Desktop class to be notified when the user opens a URL with your app.
URIHandler
interface with the Desktop
class to be notified when users open URLs with your app on Mac OS.import java.awt.Desktop;
import java.awt.desktop.OpenURIEvent;
import java.awt.desktop.OpenURIHandler;
public class HelloApplication {
static {
try {
Desktop.getDesktop().setOpenURIHandler(new URIHandler());
} catch (Exception ex){}
}
...
public static class URIHandler implements OpenURIHandler {
@Override
public void openURI(OpenURIEvent e) {
System.out.println("Received open uri event "+e.toString());
}
}
...
}
Homepage Verification
When users install your app, they will be prompted with a warning dialog to remind them to only install software from trusted sources. They are encouraged to review the app’s homepage to ensure that they trust the developer before proceeding with the installation. The dialog will look something like:

By default it will report the software’s verified homepage to be the npmjs.org package page for your app. If you want this to report your actual website or GitHub repository, you’ll need to enter your your website URL into the "Homepage" field the "Details" tab, and then verify ownership.

To verify ownership of this page, you’ll need to copy and past your app’s SHA256 hash code into your website. You can begin this process by pressing the "Verify" button beside the Homepage text field. It will display a dialog like the following:

Click on the SHA256 hash code in this dialog to have it copied to the clipboard. Then paste it somewhere in your webpage. This can be hidden inside a meta tag, or just placed into the text of the page. As long as the jDeploy installer can make an HTTP request to your homepage and find the code amongst the page content.
Important
|
The sha256 hash code is generated based on the package name and the homepage URL, so if you change the homepage URL, the hash will change, and you’ll have to re-verify. |
Once you have added the code to your homepage, press the "Verify" button so that jDeploy can check it. If everything looks good, you’ll see a success dialog like the following:

Important
|
This verification step is just a sanity check to ensure that you’ve pasted the code correctly. It doesn’t store this verification anywhere, and the jDeploy installer will perform its own check at install time whenever a user installs your app. This means that you shouldn’t remove the code after verification. You should leave it there permanently - or at least as long as you want your installers to be able to verify to your homepage. |
Command-line Distribution
Apps distributed using jDeploy can also be installed in the command-line using npm. When distributing in this way, you’ll want to pay attention to the bin and name properties of your package.json file.
- name
-
This is the name of our project as it will be listed in the NPM registry. This name must be unique. If you try to publish a project with a name that is already registered by someone else, it will fail. This name will be used by users who want to install your app. E.g. If "name"= "hello-world", then people would install my app by typing "npm install hello-world -g" at the command prompt.
- bin
-
This specifies the name of the command that will be installed to activate your app. It actually maps an alias to the "jdeploy-bundle/jdeploy.js" script, which is thin bootstrap shell script for your java app. The entry will look like
"bin" : {"hello-world" : "jdeploy-bundle/jdeploy.js"}
. If you want to change your app’s command name to "my-hello-world", then you would just change "hello-world" to "my-hello-world".
You don’t need to do anything special to allow your app to be installed via the command-line. If you have published it using the jdeploy publish
command, then, assuming your package name is "hello-world", users will be able to install your app by typing:
$ npm install hello-world -g
Some things to note:
-
On Mac and Linux you’ll need to use
sudo
as it adds a symlink to /usr/local/bin which requires sudo permissions. On Windows it will work without sudo as long as you are using an Administrator account. -
If you omit the
-g
it will install the app locally (i.e. for use inside the current working directory). When installed in this way, you need to use thenpx
command to run your app, and it will only work when run inside the install directory.
They can then launch your app with:
$ hello-world
or, if they installed it locally, they would instead run it with:
$ npx hello-world
See Getting Started with jDeploy for Command-line apps for step-by-step instructions in deploying your command-line app.
Runtime Arguments
jDeploy allows you to configure JVM options, system properties, and program arguments for your application in the Runtime Args tab of the GUI, or the args property of the jdeploy object in the package.json file.
When working in the GUI, you should enter the arguments one per line in the provided text area. jDeploy supports a small set of placeholder variables that you can include in your arguments, that will be replaced at runtime. It also supports a minimal syntax for making platform-specific arguments, which are used on some platforms and not others.

The above arguments would be saved in the package.json file as follows:
{
...
"jdeploy": {
...
"args": [
"-Dmyapp.foo=bar",
"-Xmx2G",
"-D[mac]application.support.dir={{ user.home }}/Library/Application Support",
"-D[mac]resources.dir={{ app.path }}/Contents/Resources",
"gui"
],
...
JVM Options
JVM options are options that configure how the JVM works. They are always marked with the "-X" prefix. Some examples of commonly-used JVM options include:
- -XmsXXX
-
Sets the minimum and initial size of the heap. E.g.
-Xms2G
. See the Java documentation for more information. - -XmxXXX
-
Sets the maximum sizeof the heap. E.g.
-Xmx4g
. See the Java documentation for more information.
System Properties
You can set system properties using the -D
prefix. E.g. -Dmyapp.setting=foobar
Program Arguments
Arguments that are not prefixed with -X
or -D
are treated as program arguments. They will be passed to your program, and you can receive them in your main(String[] args)
method.
Placeholder Variables
jDeploy supports a handful of placeholder variables that can be embedded in your run arguments, and will be replaced with the appropriate value at runtime. Placeholder variables are marked with {{ varname }}
. The available variables are as follows:
- {{ user.home }}
-
The path to the user’s home directory.
- {{ exe.path }}
-
The path to the executable.
- {{ app.path }}
-
The path to the .app bundle (when run on Mac). Otherwise it will be the same as
{{ exe.path }}
.
Platform-Specific Arguments
In some cases you may want a setting to only be applied on a specific platform. For example some JVM options may be mac specific. jDeploy provides a minimal syntax for marking an argument as platform-specific. For system properties, you would add a condition after the -D
prefix, so instead of -Dfoo=bar
, you would have -D[CONDITION]foo=bar
where CONDITION
is one or more platform names ("mac-x64", "mac-arm64", "linux", "win") delimited by pipes. Some examples:
-D[mac]foo=bar
-
Same as
-Dfoo=bar
, but only on Mac. -D[win]foo=bar
-
Same as
-Dfoo=bar
, but only on Windows. -D[win|linux]foo=bar
-
Same as
-Dfoo=bar
, but only on Windows and Linux.
A similar syntax is used for platform-specific JVM options: -X[CONDITION]value
, where CONDITION
is one or more platform names ("mac-x64", "mac-arm64", "linux", "win") delimited by pipes. Some examples:
-X[mac]ms2G
-
Same as
-Xms2G
, but only on Mac. -X[mac|linux]mx4G
-
Same as
-Xmx4G
, but only on Mac and Linux.
Finally, for program arguments (i.e. arguments that are passed to your main(args)
method), you can mark them as platform-specific by adding a -[CONDITION]
prefix. E.g. -[mac]anArgOnlyAddedOnMac
. Some more examples:
-[mac]foo
-
Same as
foo
, but only on Mac. -[linux|win]foo
-
Same as
foo
, but only on Linux and Windows.
Publishing as Web App (CheerpJ)
jDeploy includes experimental support for deploying Java Swing/AWT-based applications as progressive web apps. From the CheerpJ website:
CheerpJ is a WebAssembly-based Java Virtual Machine for the browser. It has extensive compatibility with Java 8 and provides a full runtime environment1 for running Java applications, applets, libraries, and Java Web Start / JNLP applications in the browser without plugins.
This is currently experimental. Limitations include:
-
Only Swing/AWT UIs are supported currently. No JavaFX.
-
Some 3rd-party java libraries may not be supported. You can try to build and find out.
Important
|
Please read the CheerpJ licensing options before deploying your application, to ensure that you are fully compliant. |
To enable CheerpJ support, you should add a "cheerpj" property to the "jdeploy" object in the package.json file. E.g.:
"jdeploy": {
...
"cheerpj": {
"githubPages": {
"branchPath": "{{ branch }}",
"tagPath": "app",
"branch": "gh-pages",
"enabled": true
},
"enabled": true
},
},
...
The above configuration will be used by the github action to publish a web application via github pages.
The following properties, pertaining to Cheerpj, are available.
jdeploy.cheerpj
-
Boolean value indicating whether the github action should attempt to build the app as a web app using CheerpJ.
jdeploy.cheerpj.githubPages
-
Object with configuration properties for GitHub pages.
jdeploy.cheerpj.githubPages.enabled
-
Whether to publish to GitHub pages. Boolean.
jdeploy.cheerpj.githubPages.branch
-
The branch to use for publishing to GitHub pages. This should match the branch that is configured for GitHub pages on GitHub.
jdeploy.cheerpj.githubPages.branchPath
-
The path within the pages site where the app should be published for "branch" commits. You can use the
{{ branch }}
placeholder to include the name of the branch. It will be replaced by the name of the branch on which the commit occurred. jdeploy.cheerpj.githubPages.tagPath
-
The path within the pages site where the app should be published for "tag" releases. You can use the
{{ tag }}
placeholder to include the name of the tag in the path. It will be replaced by the name of the tag. jdeploy.cheerpj.githubPages.path
-
Optional. If you want branch commits and tag commits to be published to the same path, then you can use this to set them both in one place.
Tip
|
The jDeploy IntelliJ Plugin includes a GUI form for configuring CheerpJ in the jDeploy Settings dialog. |

Building Bundles Locally
Important
|
When building your bundles locally, you still need to ensure that you run jdeploy publish to publish your app on npm, as the launcher relies on your published package for the automatic updates feature.
|
The easiest way to distribute your app is to just share the link to its download page at https://www.jdeploy.com/~your-app-name, however, you can optionally just generate your bundles locally as part of the jdeploy package
step (which is included when you run jdeploy publish
).
There are two flavors of packages that you can create:
- bundles
-
The .exe, .app, etc.. bundles that launch your app directly.
- installers
-
The installers that you can distribute to your users which install your .exe/.app, etc… bundles.
If you want to distribute your app to users, the installers provide a better experience since they include options to, for example, add your app to the programs menu (Windows/Linux) or the Dock (Mac).
You can generate bundles via the bundles property of the jdeploy object in your package.json file. E.g.
{
...
"jdeploy" : {
...
"bundles": ["mac-x64", "mac-arm64", "win", "linux"],
}
}
With this setting the jdeploy package
command (and jdeploy publish
) will generate your app bundles in the jdeploy/bundles
directory. If you only wanted to generate a "mac" bundle for Intel macs, you would do:
"bundles" : ["mac-x64"]
To generate installers, you can add the "installers" property. E.g.
"installers" : ["mac-x64", "mac-arm64", "win", "linux"]
This would result in installer bundles being generated in the jdeploy/installers
directory.
Note
|
The installers generated in this way may differ slightly from the installers available on your download page. This is because the download page uses a different mechanism for generating the packages. Additionally, the download page may provide some installer types that aren’t available locally. |
Publishing on GitHub
Important
|
You must publish your releases to a public repository, or your app installer won’t be able to download updates. If your repository is private, you can use the target_repository parameter for the GitHub action to publish your installers to a different repository that is public.
|
As of jDeploy 4.0, you can deploy your application on GitHub packages instead of npm. When deploying bundles in this way, you do not require an npm account. Some of the features of this deployment style include:
-
GitHub actions integration to automate deployments on push/release/tag.
-
Publish app artifacts in the GitHub release itself.
-
Branch-App Synchronization: Distribute app bundles that are automatically synchronized with a specific branch of your repo.
-
Multiple Streams: Distributed multiple versions of your app (e.g. "dev", "stage", "production") that are synchronized to different branches of your repository.
-
Still includes support for jDeploy Download page. In addition to publishing apps as artifacts of GitHub releases, your bundles will still be available at jdeploy.com on your download page.
Publishing Releases with GitHub Actions
Tip
|
The jDeploy IntelliJ Plugin provides a project wizard that includes project templates for Codename One, Swing, and JavaFX, which are plug-and-play, including full support for publishing releases using GitHub actions. |
To publish your packages on GitHub, you’ll need to add the following to your workflow.
- name: Publish with jDeploy
uses: shannah/jdeploy@master
with:
github_token: '${{ github.token }}'
This should be placed in a step after you have built your app already (e.g. using maven, gradle, ant, etc…).
If this action is used in a workflow on a merge or push, then it will publish artifacts on a release named after the branch that the workflow is running on.
E.g. If this workflow runs on the "master" branch, then it will publish your app bundles as artifacts on a tag named "master".
If this action is used in a workflow on a release or tag action, then it will add the app bundles as artifacts directly on the release/tag in GitHub.
Tip
|
You can add a working workflow to your app using the jDeploy GUI, by selecting "File" > "Add Github Workflow" ![]() |
Your App Download Page
The URL convention for the jDeploy download page for apps hosted on GitHub is:
https://www.jdeploy.com/gh/YOUR_GITHUB_ACCOUNT/YOUR_REPO_NAME
E.g. The SwingSet app whose repository is located at https://github.com/shannah/swingset2
, will have download page at https://www.jdeploy.com/gh/shannah/swingset2
.
To access the download page for a specific branch you can append the branch name to the URL. E.g. The download for the "Swing Set 2 (master)" app, which is synchronized with the "master" branch, the URL would be:
https://www.jdeploy.com/gh/shannah/swingset2/master
Distributing Mac App as a DMG image
By default, MacOS apps are distributed as an installer, which is signed and notarized by jDeploy, so you don’t need to sign it with your own Apple developer certificate. However, if you would prefer to sign the app with your own certificate, you can distribute it as a DMG instead of an installer, you can do this via the jDeploy DMG GitHub action.
The IntelliJ plugin project templates include a DMG job in the GitHub workflow by default, but you do need to define a configuration variable and some secrets in your repository.
For full instructions, see the README.
Publishing Releases for Private Repositories
Your release artifacts must be published to a public repository in order for the jDeploy installer to be able to download updates for your app. If your repository is private, you can publish your releases in a different repository which is public.
Step One: Create a Public Repository for your Releases
For example, consider a scenario where your app is in the private repository yourname/yourapp
. Then you could create a new public repository at yourname/yourapp-releases
.
Important
|
Make sure you make at least one commit to this repo before publishing releases to it, or GitHub won’t allow you to add a release. E.g. Add a readme file to the repo. |
Step Two: Create a Personal Access Token
In order to publish releases to a different repository, you’ll need to create a personal access token that has permission to create releases in the other repository.
Once you’ve created the personal access token, you’ll need to add it as a secret in your repository.
Step Three: Specify the target_repository
in your workflow
Finally, you’ll need to modify the invocation of the jdeploy GitHub action to use the target_repository
parameter, and change the github_token
parameter to use your personal access token instead of the default github_token.
- name: Publish with jDeploy
uses: shannah/jdeploy@master
with:
github_token: '${{ secrets.YOUR_PERSONAL_ACCESS_TOKEN }}'
target_repository: 'yourname/yourapp-releases'
The next time your run the workflow, it should publish the releases to the yourapp-releases
repository instead of the yourapp
repository.
File | Description |
---|---|
icon.png |
The icon for your app |
installsplash.png |
The splash screen to display in the installer. |
package-info.json |
A JSON file including all of the package information about your app. |
The "jdeploy" tag
This action will add (and update) a tag named "jdeploy" to your repo, with a file named "package-info.json". This tag must not be deleted. The package-info.json file is used by both the jDeploy launcher and installer obtain details about your app, so that it knows what versions are available.
The jDeploy JavaFX Starter Project Template
If you’re starting out with a new JavaFX project, then the jdeploy-javafx-starter may be what you’re looking for. It provides you with a bare-bones JavaFX maven project, based on the official openjfx javafx-archetype-simple archtype, but it comes loaded with a GitHub workflow to auto-generate native installers for all branches and releases.
Getting started is as simple as pressing "Use this template", and you’ll be all set.
See https://github.com/shannah/jdeploy-javafx-starter for details.
Appendix: package.json Reference
jDeploy uses the package.json file to store all of its configuration details for a project. When you run jdeploy init
it will create a default package.json file in the current working directory with default settings.
Note
|
For full documentation on the package.json file and its standard properties, see the npm package.json documentation. |
Most of the jDeploy-related settings are located inside the "jdeploy" object. E.g.
{
...
"jdeploy" : {
"jar" : "dist/my-app.jar"
...
}
}
However, there are a few properties at the "root" level that will affect how jDeploy deploys your application.
Main Root-Level Properties
The following standard properties are important to jDeploy.
Property | Description | Required | Default |
---|---|---|---|
name |
The name used to install your app from NPM. This must be unique in the NPM registry. E.g. If your "name" is |
Yes |
|
bin |
An map containing the binaries for your application. This must contain at least one entry whose key is the name of your app as it will be called on the command-line, and value is "jdeploy-bundle/jdeploy.js" |
Yes |
|
dependencies |
Must include a dependency on the "shelljs" library. |
Yes |
For other root-level properties see npm package.json documentation
Basic jDeploy Object Properties
The following properties should be placed inside the "jdeploy" object of the package.json, and are almost always used.
Property | Description | Type | Required | Default |
---|---|---|---|---|
buildCommand |
Optioknal build command that can be used to build the project before packaging. This is typically used for JavaFX projects that are built using Maven or Gradle. E.g. |
Array<String> |
No |
None |
javaVersion |
The Major java version to use for your app’s runtime. E.g. "8", "11", "17", "21", etc.. |
String |
No |
"17" |
jdk |
Whether the app requires the full JDK to run. |
boolean |
No |
|
javafx |
Whether the app requires JavaFX to run. |
boolean |
No |
|
javafxVersion |
Optional JavaFX version to use. If you don’t specify this, then it will just use whatever version comes with the ZuluFX Java distribution. |
String |
No |
None |
jar |
Relative path to the executable jar file that contains your app. You should supply either "war" or "jar", but not both. This value may be the path to a file, or a glob pattern (e.g. using |
String |
No |
|
title |
The human-readable title of your app. This is used in the download page, and in the app and installer names. |
String |
No |
A modified version of the package name. |
war |
Relative path to a war file, or web-app directory that contains your web app. You should supply either "war" or "jar", but not both. This value may be the path to a file, or a glob pattern (e.g. using |
String |
No |
Advanced jDeploy Object Properties
The following properties may be placed in the "jdeploy" object of the package.json file.
Property | Description | Type | Required | Default |
---|---|---|---|---|
args |
List of runtime arguments. See Runtime Arguments. |
Array<String> |
No |
None |
bundles |
List of the platforms to build bundles for when you run |
Array |
No |
None |
files |
List of copy rules for copying files into the the deployed application bundle. By default, for executable jar deployments, it will copy the jar file and all files listed in the jar’s class path (from its manifest file); and for war deployments, it will just copy what is inside the war file. If you need additional files to be deployed (e.g. native libs or resources), then you should specify them in this list. See Copy Rules. |
Array |
No |
|
documentTypes |
Array of file association objects. See File Associations. |
Array |
No |
|
urlSchemes |
Array of URL schemes to associate with your app. See URL Schemes. |
Array |
No |
|
installers |
List of the platforms to build installers for when you run |
Array |
No |
None |
jdeployVersion |
Optionally specify the version of jDeploy that should be used for building bundles and installers. |
String |
No |
None |
port |
For war deployments, this specifies the port that the Jetty wrapper should bind to. This can be overridden at runtime using the |
int |
No |
0 |
antFile |
Set the ant build file to use for the |
String |
No |
build.xml |
preCopyTarget |
You can optionally specify ANT to run a target before copying files to the |
String |
No |
|
postCopyTarget |
Optional ANT target to be run after files have been copied to the |
String |
No |
|
preCopyScript |
Optional script to be executed before copying files to the |
String |
No |
|
postCopyScript |
Optional script to be executed after copying files to the |
String |
No |
Copy Rules
The "jDeploy/files" array includes zero or more copy rules. Each copy rule is an object that may contain the following properties:
Property | Description | Type | Required | Default |
---|---|---|---|---|
dir |
The relative path to the directory from which files are to be copied. |
String |
Yes |
|
includes |
Specifies files to be included in the copy. Either an array of glob patterns, or a comma-delimited string of glob patterns. The glob pattern uses PathMatcher globs. E.g. "*/.dll". |
String or Array |
No |
All files in dir |
excludes |
Specifies files to be excluded from the copy. Either an array of glob patterns, or a comma-delimited string of glob patterns. The glob pattern uses PathMatcher globs. |
String or Array |
No |
None |
Example Copy Rules*
{
...
"jdeploy" : {
"files" : [
{"dir" : "dist", "includes": "lib/*.dll,lib/*.so,lib/*.dylib"}
]
}
...
}
This would copy all of the dll, so, and dylib files from "dist/lib" into the jdeploy-bundle directory for deployment.
Automatic jar/war file Resolution
The "jDeploy/jar" and "jDeploy/war" properties specify the location of the jar or war file that constitutes the application. jdeploy init
will scan the current directory for eligible jar, war, and web app directories and set the shallowest candidate in the "jDeploy/jar" or "jDeploy/war" directive of the package.json. If you delete this value, or you omit it from the package.json, jdeploy install
and jdeploy publish
will perform the same search for an appropriate candidate.
Examples
{
"bin": {"hellojdeploy": "jdeploy-bundle/jdeploy.js"}, // (1)
"preferGlobal": true, (2)
"version": "1.0.1",
"jdeploy": {"jar": "dist/HelloJDeploy.jar"}, (3)
"dependencies": {"shelljs": "^0.8.4"},
"license": "ISC",
"name": "hello-jdeploy", (4)
"files": ["jdeploy-bundle"] (5)
}
-
Once installed, the binary name of our app will be "hellojdeploy". I.e. we would start the app by typing "hellojdeploy" at the command prompt.
-
Indicates that NPM should prefer to install the app globally. If people forget to include the "-g" flag when they try to install the app, they will get a warning.
-
The executable Jar file that we are deploying is located at "dist/HelloJDeploy.jar".
-
The command to install the app would be
npm install -g jdeploy-bundle
The above package.json deploys an app such that it would be installed with
npm install -g hello-jdeploy
And it would be installed as "hellojdeploy", so that it could be run on the command line:
hellojdeploy
Appendix: Building Executable Jar File
Tip
|
The jdeploy-javafx-starter template comes preloaded with everything necessary to distribute your app as native installer. If you’re starting fresh, we recommend you start with that template. The following section describes how to modify existing maven projects to produce an executable Jar file. |
jDeploy essentially converts an executable Jar file into native bundles for Mac, Windows, and Linux. An Executable Jar file is essentially just a Jar file that can be run via java -jar TheJar.jar
. The distinguishing feature of an executable jar file (vs a regular jar file) is that it includes directives in its manifest that specify the "Main" class to run, and a "Class-Path" (i.e. a list of dependencies). Most IDEs and build tools have built-in support for generating executable Jar files. In some cases, however, you may need to explicitly enable this.
Executable Jar Files in Maven
The two most common strategies to produce executable jars in Maven are using either a combination of the maven-dependency-plugin and the maven-jar-plugin, or using the maven-assembly-plugin. The latter approach (maven-assembly-plugin) can generate a single "fat" jar with all of your dependencies. The former approach (maven-dependency-plugin and maven-jar-plugin) places your dependencies in a "libs" directory.
Tip
|
An alternate approach is to add the spring-boot-starter module as a parent in your pom.xml file. It will include all the configuration necessary to build your app as an executable "uber" jar. |
Using the maven-dependency-plugin and maven-jar-plugin
In Maven, for example, you will need to use the the maven-dependency-plugin and maven-jar-plugin plugins to package up all the dependencies, and add the appropriate manifest entries to make the jar executable. The following snippet can be added to the <build>/<plugins>
section of your pom.xml file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.example.YourMainClass
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
You will need to change the <mainClass>com.example.YourMainClass</mainClass>
entry to point to the main class of your app.
Using the maven-assembly-plugin
The maven-assembly-plugin is an alternate way to produce an executable jar. It will generate a "fat" jar with all dependencies.
Note
|
With jDeploy there is no benefit to "fat" jar because your app will be bundled as a native bundle anyways. |
The following snippet can be added to the <build>/<plugins>
section of your pom.xml file.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>build-publisher</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.example.YourMainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${project.artifactId}</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
You will need to change the <mainClass>com.example.YourMainClass</mainClass>
entry to point to the main class of your app.
Using the Spring Boot Starter
An alternate approach for generating executable jars in your app is to reference the spring-boot starter pom as the parent of your module. This will cause your project to inherit all of the nice build features that Spring boot has to offer.
The idea of using the spring boot starter may seem strange at first, since Spring is a framework for building web applications, but it was build to be modular, so it is possible to use its build tools without actually adding any dependencies to your application.
Add the following to your pom.xml file in order to use Spring boot to generate your jar:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.YourMainClass</mainClass>
</configuration>
</plugin>
</plugins>
</build>
Appendix: The jdeploy-javafx-archetype
The jdeploy-javafx-starter Github template, which provides you with a JavaFX app project and native installers out of the box, is essentially the same as the jdeploy-javafx-archetype maven archetype.
If you like to use Maven archetypes to generate your new project, you may prefer to use the archetype directly.
See https://github.com/shannah/jdeploy-javafx-starter-archetype for more information.
I generally prefer the former approach because sometimes bundling everything into a fat jar can break things. Also, when using jDeploy, there is no benefit to a fat jar, since your app is deployed as a native bundle anyways.
Appendix: Windows Installation Layout
The jDeploy application installer creates a slightly different file structure for the installed application on each platform.
Additionally, the layout will depend on which version of Java your application specifies in the javaVersion
property of the package.json file.
Finally, the layout for apps deployed via npm will differ slightly from apps that are deployed via GitHub releases.
Windows Installation Layout for Apps Deployed via npm
Given an application with package name "myapp" and title "My App", the following file structure will be created on Windows:
If the app uses Java 8:
Location | Description |
---|---|
%HOMEPATH%/.jdeploy/apps/myapp |
This is the root directory for the application. It contains the following subdirectories: |
%HOMEPATH%/.jdeploy/apps/myapp/bin/My App.exe |
The executable file for the application. This is the file that will be run when the user clicks on the app icon. |
%HOMEPATH%/.jdeploy/apps/myapp/jre |
The Java runtime environment that is bundled with the app. |
%HOMEPATH%/.jdeploy/uninstallers/myapp/myapp-uninstall.exe |
The uninstaller for the app. This installer will be run when you uninstall the application via Add/Remove Programs. IMPORTANT: You should not run the installer directly. Always run it via Add/Remove Programs. |
%HOMEPATH%/.jdeploy/packages/myapp |
This diectory contains all of your actual Java application files. This is where your jar file, war file, or web app directory will be installed. |
%HOMEPATH%/.jdeploy/log/myapp/myapp.lastrun.log |
The log file for the last run of the application. If you write to StdOut or StdErr in your application, this is where the output will be captured. |
If the app uses Java 11 or higher:
Location | Description |
---|---|
%HOMEPATH%/.jdeploy/apps/myapp |
This is the root directory for the application. It contains the following subdirectories: |
%HOMEPATH%/.jdeploy/apps/myapp/My App.exe |
The executable file for the application. This is the file that will be run when the user clicks on the app icon. |
%HOMEPATH%/.jdeploy/uninstallers/myapp/myapp-uninstall.exe |
The uninstaller for the app. This installer will be run when you uninstall the application via Add/Remove Programs. IMPORTANT: You should not run the installer directly. Always run it via Add/Remove Programs. |
%HOMEPATH%/.jdeploy/packages/myapp |
This diectory contains all of your actual Java application files. This is where your jar file, war file, or web app directory will be installed. |
%HOMEPATH%/.jdeploy/log/myapp/myapp.lastrun.log |
The log file for the last run of the application. If you write to StdOut or StdErr in your application, this is where the output will be captured. |
Windows Installation Layout for Apps Deployed via GitHub Releases
The layout for apps deployed via GitHub releases is slightly different. The main difference is that the app is installed in a directory that is named after the hash of the app’s package name and version. This is to ensure that multiple versions of the same app can be installed side-by-side.
Each app has a unique hash prefix that is derived from the package name and version of the app. This hash prefix is used to create a unique directory for the app.
In addition, the package is installed in the %HOMEPATH%/.jdeploy/gh-packages
directory, rather than the %HOMEPATH%/.jdeploy/packages
directory.
If the app uses Java 8:
Location | Description |
---|---|
%HOMEPATH%/.jdeploy/apps/<APP_HASH_PREFIX>.myapp |
This is the root directory for the application. It contains the following subdirectories: |
%HOMEPATH%/.jdeploy/apps/<APP_HASH_PREFIX>.myapp/bin/My App.exe |
The executable file for the application. This is the file that will be run when the user clicks on the app icon. |
%HOMEPATH%/.jdeploy/apps/<APP_HASH_PREFIX>.myapp/jre |
The Java runtime environment that is bundled with the app. |
%HOMEPATH%/.jdeploy/uninstallers/<APP_HASH_PREFIX>.myapp.<BRANCH_NAME>/myapp-uninstall.exe |
The uninstaller for the app. This installer will be run when you uninstall the application via Add/Remove Programs. IMPORTANT: You should not run the installer directly. Always run it via Add/Remove Programs. |
%HOMEPATH%/.jdeploy/gh-packages/<APP_HASH_PREFIX>.myapp |
This diectory contains all of your actual Java application files. This is where your jar file, war file, or web app directory will be installed. |
%HOMEPATH%/.jdeploy/log/github.com/<GITHUB_USER>/<GITHUB_REPO>/myapp/myapp.lastrun.log |
The log file for the last run of the application. If you write to StdOut or StdErr in your application, this is where the output will be captured. |
If the app uses Java 11 or higher:
Location | Description |
---|---|
%HOMEPATH%/.jdeploy/apps/<APP_HASH_PREFIX>.myapp |
This is the root directory for the application. It contains the following subdirectories: |
%HOMEPATH%/.jdeploy/apps/<APP_HASH_PREFIX>.myapp/My App.exe |
The executable file for the application. This is the file that will be run when the user clicks on the app icon. |
%HOMEPATH%/.jdeploy/uninstallers/<APP_HASH_PREFIX>.myapp/myapp-uninstall.exe |
The uninstaller for the app. This installer will be run when you uninstall the application via Add/Remove Programs. IMPORTANT: You should not run the installer directly. Always run it via Add/Remove Programs. |
%HOMEPATH%/.jdeploy/gh-packages/<APP_HASH_PREFIX>.myapp |
This diectory contains all of your actual Java application files. This is where your jar file, war file, or web app directory will be installed. |
%HOMEPATH%/.jdeploy/log/github.com/<GITHUB_USER>/<GITHUB_REPO>/myapp/myapp.lastrun.log |
The log file for the last run of the application. If you write to StdOut or StdErr in your application, this is where the output will be captured. |
Appendix: Command-Line Usage
While the GUI is recommended for most users, jDeploy can also be used entirely from the command line. This section covers installation and usage of jDeploy as a command-line tool.
Installing jDeploy CLI
jDeploy can be installed globally using npm:
npm install -g jdeploy
Note
|
On macOS and Linux, you may need to use sudo for global installation.
|
To verify the installation:
jdeploy --version
Basic Commands
Initializing a Project
To initialize a new jDeploy project in your existing Java application directory:
cd /path/to/your/java/app
jdeploy init
This creates a package.json
file with default jDeploy configuration. The command will:
-
Scan for executable JAR files in your project
-
Create initial configuration based on your project structure
-
Set up default publishing settings
Publishing Your Application
To publish your application:
# First time only: Log in to npm
npm login
# Publish the application
jdeploy publish
The publish command:
-
Builds your application bundles
-
Creates installers for all supported platforms
-
Publishes to npm or GitHub (based on configuration)
-
Updates your download page on jdeploy.com
Building Packages Locally
To build packages without publishing:
jdeploy package
This creates bundles and installers in the jdeploy/bundles
and jdeploy/installers
directories respectively.
Advanced Commands
Cleaning Build Files
To clean all generated files:
jdeploy clean
Running in Debug Mode
For detailed logging during any command:
jdeploy --debug <command>
For example:
jdeploy --debug publish
Command-Line Options
Option | Description |
---|---|
--version |
Display version information |
--debug |
Enable debug logging |
--help |
Show help information |
--skip-build |
Skip building the application (publish/package) |
--skip-installers |
Skip creating installers (publish/package) |
Environment Variables
jDeploy respects the following environment variables:
Variable | Description |
---|---|
JDEPLOY_PORT |
Override the default port for web applications |
JAVA_HOME |
Specify the Java installation to use |
NPM_TOKEN |
Authentication token for npm publishing |
Example Workflow
A typical command-line workflow might look like this:
# Initialize the project
cd my-java-app
jdeploy init
# Edit package.json to configure your app
# Build your Java application (e.g., mvn package)
# Test package building locally
jdeploy package
# When ready, publish
npm login
jdeploy publish
Appendix: Project Templates
When creating a new project in jDeploy, you can choose from several pre-configured project templates that provide a solid foundation for your application. These templates come with jDeploy integration and GitHub workflows already set up.

Built-in Templates
The following templates are available by default:
Swing Template
A basic Java Swing application template that includes:
-
Maven project structure
-
Basic Swing application window
-
jDeploy configuration for native bundles
-
GitHub workflow for automated releases
JavaFX Template
A JavaFX application template based on the official javafx-archetype-simple
archetype, featuring:
-
Modern JavaFX application structure
-
FXML support for UI design
-
CSS styling capabilities
-
GitHub workflow for native installers
-
Auto-update configuration
Spring Boot + Swing Template
A template combining Spring Boot with Swing, offering:
-
Spring Boot’s dependency management
-
Swing UI integration
-
Built-in executable JAR support
-
jDeploy publishing configuration
Template Variables
Project templates use placeholder variables that are automatically replaced when creating a new project. The available placeholders are:
Variable | Description |
---|---|
{{ appName }} |
The name of your application used for package naming |
{{ appTitle }} |
The human-readable title of your application |
{{ groupId }} |
The Maven group ID for your project |
{{ artifactId }} |
The Maven artifact ID for your project |
{{ mainClass }} |
The fully qualified name of your application’s main class |
{{ mainClassName }} |
Alternative reference to the main class name |
{{ packageName }} |
The Java package name for your project |
{{ packagePath }} |
The package name converted to a directory path (e.g., com.example becomes com/example) |
{{ javaVersion }} |
The Java version to be used in the project |
{{ githubRepository }} |
The GitHub repository where the project will be hosted |
{{ githubReleasesRepository }} |
The GitHub repository where releases will be published |
{{ releasesUrl }} |
The URL where releases will be available |
Contributing Templates
You can contribute your own project templates to the jDeploy community by submitting them to the jdeploy-project-templates repository.
Template Structure
A typical project template includes:
template/
├── src/ # Source code directory
├── .github/workflows/ # GitHub Actions workflows
├── pom.xml # Maven configuration
├── package.json # jDeploy configuration
└── README.md # Template documentation
Using Templates
To use a project template:
-
In the jDeploy GUI, select "Create New Project"
-
Choose a template from the dropdown list
-
Fill in the required information:
-
Project name
-
Application title
-
Group ID
-
Artifact ID
-
Main class name
-
Package name
-
GitHub repository (if using GitHub integration)
-
-
Click "Create Project"
The template system will:
-
Create a new directory for your project
-
Replace all template placeholders with your values
-
Initialize a Git repository (if requested)
-
Set up the GitHub workflow (if enabled)
Best Practices
When creating templates:
-
Use the standard placeholder variables consistently
-
Include comprehensive documentation
-
Add example code that demonstrates best practices
-
Include GitHub workflows for automated builds and releases
-
Configure appropriate jDeploy settings for the template type
-
Test the template with different placeholder values to ensure proper substitution