IntelliJ Platform Plugin SDK Help

New Project Wizard API

The New Project wizard items can be grouped into two main types:

Language Project Generators

Language project generators allow for creating general-purpose projects without specific frameworks (they can be added to the project by users later). Examples:

  • a Kotlin project

  • a Python project

These items are displayed at the top in the left sidebar of the New Project dialog.

Language project generators implement LanguageGeneratorNewProjectWizard and are registered in com.intellij.newProjectWizard.languageGenerator extension point.

The generator implementation must provide:

  • name and icon used in UI

  • ordinal that is used to sort the generator in the generator list

  • isEnabled(WizardContext) that allows controlling displaying the item depending on the current context

  • createStep(NewProjectWizardStep) that creates the tree of steps that users go through during the project creation. Note the provided parent step, which exposes the wizard context, data holder, and other shared properties. See Wizard Steps for details.

Examples:

Framework Project Generators

Framework project wizards allow for creating projects related to a specific technology, for example:

  • a Spring Boot project

  • a project generated from a Maven Archetype

  • a React project

These items are displayed under language generator items in the left sidebar of the New Project dialog.

Framework project wizards implement GeneratorNewProjectWizard and are registered in com.intellij.newProjectWizard.generator extension point.

The interface exposes:

  • unique id

  • name and icon used in UI

  • ordinal that is used to sort the generator in the generator list

  • isEnabled() that allows controlling displaying the item depending on the current IDE context

  • createStep(WizardContext) that creates the tree of steps that users go through during the project creation. See Wizard Steps for details.

Example: MavenArchetypeNewProjectWizard creating Maven projects from a selected archetype

Wizard Steps

Every project wizard consists of one or more steps that users go through during project creation. Each step contains UI elements for data necessary to create a project. All the steps are displayed on a single screen in the project wizard dialog, which displays the Create button that creates the project.

A project wizard step implements NewProjectWizardStep. The most important methods are:

  • setupUI() — defines the UI components for the step. Step UI is built with Kotlin UI DSL Version 2

  • setupProject() — applies the parameters provided in UI to the generated project

See the example implementations in the intellij-community repository.

Steps build a tree structure (read the rest of this section for details), as some steps can be displayed depending on previously selected options. setupUI() and setupProject() of steps building the tree are applied in the order from root to leaf. Note that setupProject() won't be called for hidden steps.

For convenience, the platform provides AbstractNewProjectWizardStep, which is a base step class that takes a parent step and delegates common property accessors to the parent. It allows sharing the root step's properties by all descendant steps.

Chaining Steps

As mentioned before, all steps are rendered on a single screen. Merging multiple steps into a chain displayed as a single screen step is achieved with NewProjectWizardChainStep. Its companion object exposes a helper method NewProjectWizardChainStep.nextStep(), which allows chaining steps in fluent form, for example:

override fun createStep(context: WizardContext): NewProjectWizardStep { return RootNewProjectWizardStep(context) .nextStep(::FirstProjectWizardStep) .nextStep(::SecondProjectWizardStep) .nextStep(::ThirdProjectWizardStep) }

All the steps above will be created inside a single NewProjectWizardChainStep and will be displayed (except the root step, which exists to hold shared data) in a single dialog page:

New ProjectFirst Step Input 1First Step Input 2valueSecond Step InputSelectionThird Step InputCancelCreate

Root Step

The root project wizard step initializes a data holder and other properties shared with all descendant steps in the wizard.

In the case of language project generators, the LanguageGeneratorNewProjectWizard.createStep(NewProjectWizardStep) receives a parent step, and there is no need to initialize these values and create a root step.

In the case of framework project generators, the root step can be created with RootNewProjectWizardStep, which initializes shared properties.

Common Steps

Almost every project requires providing the project name and the location where it should be created. Also, projects are often shared in a Git repository. The IntelliJ Platform provides:

Note that language project generators already include these steps out of the box, and there is no need to create them in the wizard implementation.

Asset Steps

It is often required to populate a created project with initial assets like:

  • directory structure, for example, src/main/java, src/main/resources, src/test/java, src/test/resources in a Gradle Java project

  • a build-tool-specific .gitignore file ignoring build and other directories and files

  • sample code

This can be achieved by creating a step extending AssetsNewProjectWizardStep. It allows for adding directories, static assets, assets generated from Freemarker templates, and granting them proper file permissions.

See example implementations in the intellij-community repository.

Steps Forking the Wizard Flow

Sometimes, a wizard requires displaying different options depending on the user's selection. For example, depending on the selected build tool, different fields specific to the selected build tool are displayed.

Such a behavior can be implemented with AbstractNewProjectWizardMultiStep.

AbstractNewProjectWizardMultiStep internally handles steps forking the wizard flow. It is responsible for:

  • setting up the switcher

  • setting up the selected step's UI

  • applying the selected step's options to the created project

Forking steps are provided with an extension point implementing NewProjectWizardMultiStepFactory. Besides the parent step, AbstractNewProjectWizardMultiStep's constructor receives the name of the extension point implementing NewProjectWizardMultiStepFactory and uses registered extensions to create steps.

The Adding Support for Custom Build Systems in Language Project Wizards section lists example implementations of AbstractNewProjectWizardMultiStep.

Adding Support for Custom Build Systems in Language Project Wizards

Some language project generators contain the Build system field that allows for choosing a build system used by a project. This is achieved by implementing AbstractNewProjectWizardMultiStep described above. Example implementations are:

It is possible to add support for custom build systems by implementing extensions specific to these languages. The table below shows the supported languages with corresponding interfaces and extension points:

Sharing Data Between Steps

Project wizards with multiple steps may require sharing data between them. The recommended approach includes the following implementation steps:

  1. Create an interface exposing step's shared properties, for example, ExampleData:

    interface ExampleData { val value: String }
  2. Add a companion object with the data key and a helper NewProjectWizardStep.exampleData extension property.

    interface ExampleData { // ... companion object { val KEY: Key<ExampleData> = Key.create(ExampleData::class.java.name) @JvmStatic val NewProjectWizardStep.exampleData: ExampleData? get() = data.getUserData(KEY) } }
  3. Make the step implement the created interface and implement the data property and a graph property (see Property Graph for details):

    class ExampleStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent), ExampleData { private val valueProperty = propertyGraph.property(false) override var value: String by valueProperty // ... }

    The graph property is used for binding value with UI components. Consider exposing it via the data interface if it is possible that other steps may depend on it.

  4. During step instance initialization, store data in the data holder shared with all steps:

    class ExampleStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent), ExampleData { // ... init { data.putUserData(ExampleData.KEY, this) } }

    Shared data can be accessed in another step in the following way:

    class AnotherStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent) { override fun setupProject(project: Project) { // exampleData is available via this if (exampleData?.value == true) { doSomething() } // ... } // ... }

    Property Graph

    PropertyGraph creates an observable dependency graph that automatically propagates changes between related properties. It is created in the root step and shared between all descendant steps via AbstractNewProjectWizardStep.propertyGraph.

    PropertyGraph is widely used in wizard steps to create a responsive UI that dynamically updates depending on the user's actions. It allows for:

    • conditional visibility of fields based on other selections

    • dynamic validation of user inputs

    • automatic updates to dependent properties when primary properties change

    • and more

    Consider NewProjectWizardBaseStep. It implements two graph properties for the project name and path:

    override val nameProperty: GraphProperty<String> = propertyGraph.lazyProperty(::suggestName) override val pathProperty: GraphProperty<String> = propertyGraph.lazyProperty { suggestLocation().toCanonicalPath() }

    Both properties are lazily initialized with default values based on the current context.

    Data properties delegate to the graph properties:

    override var name: String by nameProperty override var path: String by pathProperty

    Any read or update of a data or graph property will update its counterpart.

    Dependencies between properties are defined during step instance initialization:

    init { nameProperty.dependsOn(pathProperty, ::suggestUniqueName) }

    It means that whenever pathProperty is changed, the nameProperty will be updated using the provided suggestUniqueName() function.

    Properties are also bound to the UI allowing for synchronizing them with the UI in both directions:

    textField() .bindText(nameProperty.trim()) ... textFieldWithBrowseButton(fileChooserDescriptor, context.project) .bindText(pathProperty.toUiPathProperty())

    In addition, there is another graph property created from path and name graph properties:

    val locationProperty = pathProperty.joinCanonicalPath(nameProperty)

    locationProperty will be updated whenever pathProperty or nameProperty is updated, and it will contain a path built of the path and name. The value of the property is bound to the comment component displayed under the location row:

    textFieldWithBrowseButton(fileChooserDescriptor, context.project) // ... .locationComment(context, locationProperty)

    PropertyGraph has many possibilities that are hard to describe in detail. It is recommended to experiment with existing project wizards and exploring their implementations.

    Persisting Default Settings

    It is convenient for users to remember commonly used settings, so they don't need to fill them again. Consider the checkbox initializing a Git repository in a created project. When the user selects it for the first time, and later they create another project, the checkbox will be automatically selected.

    This behavior can be implemented by binding graph properties to persistent storage via methods from BindUtil, for example:

    private val gitProperty = propertyGraph.property(false) .bindBooleanStorage(GIT_PROPERTY_NAME)

    Under the hood, properties are stored at the application level via PropertiesComponent under the GIT_PROPERTY_NAME key.

    Example Project Wizard Steps Structure

    The following diagram presents the steps flow of the Kotlin language project wizard implemented by KotlinNewProjectWizard.

    NewProjectWizardChainStepRootNewProjectWizardStepNewProjectWizardBaseStepGitNewProjectWizardStepNewProjectWizardLanguageStepKotlinNewProjectWizard.StepMavenKotlinNewProjectWizardMavenKotlinNewProjectWizard.StepMavenKotlinNewProjectWizard.AssetsStepGradleKotlinNewProjectWizardGradleKotlinNewProjectWizard.StepGradleKotlinNewProjectWizard.AssetsStepselect Mavencreatesselect Gradlecreates

    The following steps are always present in language project generators and are created by the platform under the hood:

    • RootNewProjectWizardStep — initializes shared properties like data holder and property graph

    • NewProjectWizardBaseStep — displays project name and location options

    • GitNewProjectWizardStep — allows for creating a Git repository for the new project

    • NewProjectWizardLanguageStep — invisible step holding information about the chosen language (this step is deprecated and is used only for technical reasons; it shouldn't be used by plugins)

    All steps are enclosed within NewProjectWizardChainStep, which renders them on a single screen.

    KotlinNewProjectWizard.Step is a multistep that forks the wizard flow into two paths depending on the user selection in the Build system switcher:

    1. Maven-specific, if the user selected Maven

    2. Gradle-specific, if the user selected Gradle

    It creates the actual steps by using registered step factory extensions (MavenKotlinNewProjectWizard and GradleKotlinNewProjectWizard).

    Depending on the selection, the platform executes setupUI() and setupProject() methods of enabled steps.

    FAQ

    How to determine whether the current context is a project or a module creation?

    Use WizardContext.isCreatingNewProject(). The wizard context is available in every step via NewProjectWizardStep.context.

    How to add a project wizard hint?

    Sometimes, a project wizard requires an explanation about the purpose of the wizard or links to an alternative item. To add a simple comment, use CommentNewProjectWizardStep, for example, EmptyProjectGeneratorNewProjectWizard.CommentStep

    To additionally render a clickable link to another wizard, use LinkNewProjectWizardStep, for example, MavenArchetypeNewProjectWizard.CommentStep.

    How to implement a project wizard for non-Java IDEs?

    To create project wizards for non-Java IDEs (for example, PyCharm), implement DirectoryProjectGenerator and register it in the com.intellij.directoryProjectGenerator extension point.

    22 May 2025