diff --git a/src/main/kotlin/com/demonwav/mcdev/asset/PlatformAssets.kt b/src/main/kotlin/com/demonwav/mcdev/asset/PlatformAssets.kt
index 34b6ffc8c..870956197 100644
--- a/src/main/kotlin/com/demonwav/mcdev/asset/PlatformAssets.kt
+++ b/src/main/kotlin/com/demonwav/mcdev/asset/PlatformAssets.kt
@@ -47,4 +47,7 @@ object PlatformAssets : Assets() {
     val MCP_ICON_2X = loadIcon("/assets/icons/platform/MCP@2x.png")
     val MCP_ICON_DARK = loadIcon("/assets/icons/platform/MCP_dark.png")
     val MCP_ICON_2X_DARK = loadIcon("/assets/icons/platform/MCP@2x_dark.png")
+
+    val PLACEHOLDERAPI_ICON = loadIcon("/assets/icons/platform/PlaceholderAPI@2x.png")
+    val PLACEHOLDERAPI_ICON_2X = loadIcon("/assets/icons/platform/PlaceholderAPI@2x.png")
 }
diff --git a/src/main/kotlin/com/demonwav/mcdev/buildsystem/maven/MavenBuildSystem.kt b/src/main/kotlin/com/demonwav/mcdev/buildsystem/maven/MavenBuildSystem.kt
index 92b389f46..aed89ee80 100644
--- a/src/main/kotlin/com/demonwav/mcdev/buildsystem/maven/MavenBuildSystem.kt
+++ b/src/main/kotlin/com/demonwav/mcdev/buildsystem/maven/MavenBuildSystem.kt
@@ -56,7 +56,7 @@ class MavenBuildSystem(
             directories = createDirectories(rootDirectory)
 
             val text = when (configuration.type) {
-                PlatformType.BUKKIT, PlatformType.SPIGOT, PlatformType.PAPER ->
+                PlatformType.BUKKIT, PlatformType.SPIGOT, PlatformType.PAPER, PlatformType.PLACEHOLDERAPI ->
                     BukkitTemplate.applyPomTemplate(project)
                 PlatformType.BUNGEECORD, PlatformType.WATERFALL ->
                     BungeeCordTemplate.applyPomTemplate(project)
diff --git a/src/main/kotlin/com/demonwav/mcdev/creator/MinecraftModuleBuilder.kt b/src/main/kotlin/com/demonwav/mcdev/creator/MinecraftModuleBuilder.kt
index 6da3060aa..8788fce0c 100644
--- a/src/main/kotlin/com/demonwav/mcdev/creator/MinecraftModuleBuilder.kt
+++ b/src/main/kotlin/com/demonwav/mcdev/creator/MinecraftModuleBuilder.kt
@@ -104,7 +104,8 @@ class MinecraftModuleBuilder : JavaModuleBuilder() {
             SpongeProjectSettingsWizard(creator),
             ForgeProjectSettingsWizard(creator),
             LiteLoaderProjectSettingsWizard(creator),
-            BungeeCordProjectSettingsWizard(creator)
+            BungeeCordProjectSettingsWizard(creator),
+            PlaceholderApiProjectSettingsWizard(creator)
         )
     }
 
diff --git a/src/main/kotlin/com/demonwav/mcdev/creator/PlaceholderApiProjectSettingsWizard.form b/src/main/kotlin/com/demonwav/mcdev/creator/PlaceholderApiProjectSettingsWizard.form
new file mode 100644
index 000000000..e4314e82f
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/creator/PlaceholderApiProjectSettingsWizard.form
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.demonwav.mcdev.creator.PlaceholderApiProjectSettingsWizard">
+  <grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="545" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <grid id="a6cf1" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="10" vgap="10">
+        <margin top="5" left="10" bottom="10" right="10"/>
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none" title-justification="1" title-position="3"/>
+        <children>
+          <component id="778f7" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="Required Settings"/>
+            </properties>
+          </component>
+          <component id="d2a96" class="javax.swing.JSeparator">
+            <constraints>
+              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+                <maximum-size width="-1" height="5"/>
+              </grid>
+            </constraints>
+            <properties/>
+          </component>
+          <grid id="c1d37" layout-manager="GridLayoutManager" row-count="3" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="5" vgap="5">
+            <margin top="5" left="5" bottom="5" right="5"/>
+            <constraints>
+              <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="e7052" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="Expansion Name"/>
+                </properties>
+              </component>
+              <component id="5b8d8" class="javax.swing.JTextField" binding="expansionNameField">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                    <preferred-size width="150" height="-1"/>
+                  </grid>
+                </constraints>
+                <properties/>
+              </component>
+              <component id="5875e" class="javax.swing.JTextField" binding="expansionVersionField">
+                <constraints>
+                  <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                    <preferred-size width="150" height="-1"/>
+                  </grid>
+                </constraints>
+                <properties/>
+              </component>
+              <component id="75b6c" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="Class Name"/>
+                </properties>
+              </component>
+              <component id="c76d2" class="javax.swing.JTextField" binding="mainClassField">
+                <constraints>
+                  <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                    <preferred-size width="150" height="-1"/>
+                  </grid>
+                </constraints>
+                <properties>
+                  <editable value="true"/>
+                </properties>
+              </component>
+              <component id="d3cfe" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="Expansion Version"/>
+                </properties>
+              </component>
+              <grid id="ab82c" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints>
+                  <grid row="2" column="0" row-span="1" col-span="4" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children>
+                  <component id="c5948" class="javax.swing.JLabel">
+                    <constraints>
+                      <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false">
+                        <preferred-size width="-1" height="17"/>
+                      </grid>
+                    </constraints>
+                    <properties>
+                      <horizontalAlignment value="4"/>
+                      <horizontalTextPosition value="4"/>
+                      <text value=""/>
+                    </properties>
+                  </component>
+                  <hspacer id="65705">
+                    <constraints>
+                      <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                  </hspacer>
+                  <component id="2aeb8" class="javax.swing.JComboBox" binding="minecraftVersionBox">
+                    <constraints>
+                      <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <model/>
+                    </properties>
+                  </component>
+                  <component id="a8a36" class="javax.swing.JLabel">
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="4" fill="0" indent="0" use-parent-layout="false">
+                        <preferred-size width="-1" height="17"/>
+                      </grid>
+                    </constraints>
+                    <properties>
+                      <horizontalAlignment value="4"/>
+                      <horizontalTextPosition value="4"/>
+                      <text value="    Minecraft Version"/>
+                    </properties>
+                  </component>
+                </children>
+              </grid>
+              <component id="add4c" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="Author Name"/>
+                </properties>
+              </component>
+              <component id="11667" class="javax.swing.JTextField" binding="expansionAuthorField">
+                <constraints>
+                  <grid row="1" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                    <preferred-size width="150" height="-1"/>
+                  </grid>
+                </constraints>
+                <properties/>
+              </component>
+            </children>
+          </grid>
+          <component id="f1d01" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <icon value="assets/icons/platform/PlaceholderAPI@2x.png"/>
+              <text value="&lt;html&gt;&lt;font size=&quot;5&quot;&gt;PlaceholderAPI Settings&lt;/font&gt;&lt;/html&gt;"/>
+            </properties>
+          </component>
+        </children>
+      </grid>
+      <component id="503f2" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value="Optional Settings"/>
+        </properties>
+      </component>
+    </children>
+  </grid>
+</form>
diff --git a/src/main/kotlin/com/demonwav/mcdev/creator/PlaceholderApiProjectSettingsWizard.kt b/src/main/kotlin/com/demonwav/mcdev/creator/PlaceholderApiProjectSettingsWizard.kt
new file mode 100644
index 000000000..e17a45e3b
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/creator/PlaceholderApiProjectSettingsWizard.kt
@@ -0,0 +1,91 @@
+/*
+ * Minecraft Dev for IntelliJ
+ *
+ * https://minecraftdev.org
+ *
+ * Copyright (c) 2020 minecraft-dev
+ *
+ * MIT License
+ */
+
+@file:Suppress("Duplicates")
+
+package com.demonwav.mcdev.creator
+
+import com.demonwav.mcdev.platform.ProjectConfiguration
+import com.demonwav.mcdev.platform.placeholderapi.PlaceholderApiProjectConfiguration
+import com.demonwav.mcdev.util.firstOfType
+import javax.swing.JComboBox
+import javax.swing.JComponent
+import javax.swing.JPanel
+import javax.swing.JTextField
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.swing.Swing
+import kotlinx.coroutines.withContext
+import org.apache.commons.lang.WordUtils
+
+class PlaceholderApiProjectSettingsWizard(private val creator: MinecraftProjectCreator) : MinecraftModuleWizardStep() {
+    private lateinit var panel: JPanel
+    private lateinit var expansionNameField: JTextField
+    private lateinit var expansionVersionField: JTextField
+    private lateinit var mainClassField: JTextField
+    private lateinit var expansionAuthorField: JTextField
+    private lateinit var minecraftVersionBox: JComboBox<String>
+
+    private var config: PlaceholderApiProjectConfiguration? = null
+
+    override fun getComponent(): JComponent {
+        return panel
+    }
+
+    override fun updateStep() {
+        config = creator.configs.firstOfType()
+        if (config == null) {
+            return
+        }
+
+        val buildSystem = creator.buildSystem ?: return
+
+        val name = WordUtils.capitalize(buildSystem.artifactId.replace('-', ' '))
+        expansionNameField.text = name
+        expansionVersionField.text = buildSystem.version
+
+        val conf = config ?: return
+
+        if (creator.configs.indexOf(conf) != 0) {
+            expansionNameField.isEditable = false
+            expansionVersionField.isEditable = false
+        }
+
+        mainClassField.text = buildSystem.groupId.replace("-", "").toLowerCase() + "." +
+            buildSystem.artifactId.replace("-", "").toLowerCase() + "." + name.replace(" ", "")
+
+        CoroutineScope(Dispatchers.Swing).launch {
+            try {
+                withContext(Dispatchers.IO) { getVersionSelector(conf.type) }.set(minecraftVersionBox)
+            } catch (e: Exception) {
+                e.printStackTrace()
+            }
+        }
+    }
+
+    override fun onStepLeaving() {
+        val conf = config ?: return
+        conf.base = ProjectConfiguration.BaseConfigs(
+            expansionNameField.text,
+            expansionVersionField.text,
+            mainClassField.text
+        )
+
+        conf.setAuthors(this.expansionAuthorField.text)
+        conf.mcVersion = minecraftVersionBox.selectedItem as? String ?: ""
+    }
+
+    override fun isStepVisible(): Boolean {
+        return creator.configs.any { it is PlaceholderApiProjectConfiguration }
+    }
+
+    override fun updateDataModel() {}
+}
diff --git a/src/main/kotlin/com/demonwav/mcdev/creator/ProjectChooserWizardStep.form b/src/main/kotlin/com/demonwav/mcdev/creator/ProjectChooserWizardStep.form
index a1d788154..8198d9d61 100644
--- a/src/main/kotlin/com/demonwav/mcdev/creator/ProjectChooserWizardStep.form
+++ b/src/main/kotlin/com/demonwav/mcdev/creator/ProjectChooserWizardStep.form
@@ -18,12 +18,12 @@
             <constraints border-constraint="North"/>
             <properties>
               <requestFocusEnabled value="false"/>
-              <text value="Choose plugin type:"/>
+              <text value="Choose project type:"/>
             </properties>
           </component>
         </children>
       </grid>
-      <grid id="c580e" binding="chooserPanel" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="5" vgap="5">
+      <grid id="c580e" binding="chooserPanel" layout-manager="GridLayoutManager" row-count="10" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="5" vgap="5">
         <margin top="2" left="10" bottom="10" right="10"/>
         <constraints border-constraint="Center"/>
         <properties/>
@@ -95,7 +95,7 @@
           </component>
           <component id="1a539" class="javax.swing.JCheckBox" binding="bukkitPluginCheckBox" default-binding="true">
             <constraints>
-              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <text value="Bukkit Plugin"/>
@@ -103,7 +103,7 @@
           </component>
           <component id="1a691" class="javax.swing.JCheckBox" binding="spigotPluginCheckBox" default-binding="true">
             <constraints>
-              <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <text value="Spigot Plugin"/>
@@ -111,7 +111,7 @@
           </component>
           <component id="24d89" class="javax.swing.JCheckBox" binding="paperPluginCheckBox">
             <constraints>
-              <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="2" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <text value="Paper Plugin"/>
@@ -119,7 +119,7 @@
           </component>
           <component id="657b2" class="javax.swing.JCheckBox" binding="spongePluginCheckBox">
             <constraints>
-              <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="3" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <text value="Sponge Plugin"/>
@@ -127,7 +127,7 @@
           </component>
           <component id="d9577" class="javax.swing.JCheckBox" binding="forgeModCheckBox">
             <constraints>
-              <grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="4" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <text value="Forge Mod"/>
@@ -135,7 +135,7 @@
           </component>
           <component id="51426" class="javax.swing.JCheckBox" binding="bungeeCordPluginCheckBox">
             <constraints>
-              <grid row="6" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="6" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <text value="BungeeCord Plugin"/>
@@ -152,7 +152,7 @@
           </component>
           <component id="5a8c1" class="javax.swing.JCheckBox" binding="liteLoaderModCheckBox" default-binding="true">
             <constraints>
-              <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="5" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <text value="LiteLoader Mod"/>
@@ -160,7 +160,7 @@
           </component>
           <vspacer id="d9ec2">
             <constraints>
-              <grid row="8" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+              <grid row="9" column="2" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
             </constraints>
           </vspacer>
           <component id="87b9d" class="javax.swing.JLabel">
@@ -176,12 +176,30 @@
           </component>
           <component id="55507" class="javax.swing.JCheckBox" binding="waterfallPluginCheckBox">
             <constraints>
-              <grid row="7" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+              <grid row="7" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
             </constraints>
             <properties>
               <text value="Waterfall Plugin"/>
             </properties>
           </component>
+          <component id="c0edf" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="8" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <icon value="assets/icons/platform/PlaceholderAPI@2x.png"/>
+              <iconTextGap value="0"/>
+              <text value=""/>
+            </properties>
+          </component>
+          <component id="cd548" class="javax.swing.JCheckBox" binding="papiExpansionCheckBox">
+            <constraints>
+              <grid row="8" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <text value="PlaceholderAPI Expansion"/>
+            </properties>
+          </component>
         </children>
       </grid>
       <grid id="c3a72" binding="infoPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
diff --git a/src/main/kotlin/com/demonwav/mcdev/creator/ProjectChooserWizardStep.kt b/src/main/kotlin/com/demonwav/mcdev/creator/ProjectChooserWizardStep.kt
index 865ace375..3fd6ac62f 100644
--- a/src/main/kotlin/com/demonwav/mcdev/creator/ProjectChooserWizardStep.kt
+++ b/src/main/kotlin/com/demonwav/mcdev/creator/ProjectChooserWizardStep.kt
@@ -16,6 +16,7 @@ import com.demonwav.mcdev.platform.bukkit.BukkitProjectConfiguration
 import com.demonwav.mcdev.platform.bungeecord.BungeeCordProjectConfiguration
 import com.demonwav.mcdev.platform.forge.ForgeProjectConfiguration
 import com.demonwav.mcdev.platform.liteloader.LiteLoaderProjectConfiguration
+import com.demonwav.mcdev.platform.placeholderapi.PlaceholderApiProjectConfiguration
 import com.demonwav.mcdev.platform.sponge.SpongeProjectConfiguration
 import com.intellij.ide.util.projectWizard.ModuleWizardStep
 import com.intellij.ui.IdeBorderFactory
@@ -44,6 +45,7 @@ class ProjectChooserWizardStep(private val creator: MinecraftProjectCreator) : M
     private lateinit var bungeeCordPluginCheckBox: JCheckBox
     private lateinit var waterfallPluginCheckBox: JCheckBox
     private lateinit var liteLoaderModCheckBox: JCheckBox
+    private lateinit var papiExpansionCheckBox: JCheckBox
 
     override fun getComponent(): JComponent {
         chooserPanel.border = IdeBorderFactory.createBorder()
@@ -86,6 +88,7 @@ class ProjectChooserWizardStep(private val creator: MinecraftProjectCreator) : M
         liteLoaderModCheckBox.addActionListener { fillInInfoPane() }
         bungeeCordPluginCheckBox.addActionListener { toggle(bungeeCordPluginCheckBox, waterfallPluginCheckBox) }
         waterfallPluginCheckBox.addActionListener { toggle(waterfallPluginCheckBox, bungeeCordPluginCheckBox) }
+        papiExpansionCheckBox.addActionListener { fillInInfoPane() }
 
         if (UIUtil.isUnderDarcula()) {
             spongeIcon.icon = PlatformAssets.SPONGE_ICON_2X_DARK
@@ -121,6 +124,7 @@ class ProjectChooserWizardStep(private val creator: MinecraftProjectCreator) : M
         sb.append(liteLoaderModCheckBox, liteLoaderInfo)
         sb.append(bungeeCordPluginCheckBox, bungeeCordInfo)
         sb.append(waterfallPluginCheckBox, waterfallInfo)
+        sb.append(papiExpansionCheckBox, papiInfo)
 
         sb.append("</font></html>")
 
@@ -161,6 +165,10 @@ class ProjectChooserWizardStep(private val creator: MinecraftProjectCreator) : M
         if (waterfallPluginCheckBox.isSelected) {
             creator.configs += BungeeCordProjectConfiguration(PlatformType.WATERFALL)
         }
+
+        if (papiExpansionCheckBox.isSelected) {
+            creator.configs += PlaceholderApiProjectConfiguration()
+        }
     }
 
     override fun validate(): Boolean {
@@ -171,7 +179,8 @@ class ProjectChooserWizardStep(private val creator: MinecraftProjectCreator) : M
             forgeModCheckBox.isSelected ||
             liteLoaderModCheckBox.isSelected ||
             bungeeCordPluginCheckBox.isSelected ||
-            waterfallPluginCheckBox.isSelected
+            waterfallPluginCheckBox.isSelected ||
+            papiExpansionCheckBox.isSelected
     }
 
     companion object {
@@ -199,5 +208,8 @@ class ProjectChooserWizardStep(private val creator: MinecraftProjectCreator) : M
         private const val liteLoaderInfo = "Create a standard " +
             "<a href=\"http://www.liteloader.com/\">LiteLoader</a> mod, for use " +
             "on LiteLoader clients."
+        private const val papiInfo = "Create a standard " +
+            "<a href=\"https://placeholderapi.com\">PlaceholderAPI</a> expansion, for use " +
+            "on servers running PlaceholderAPI."
     }
 }
diff --git a/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftFacetEditorTab.form b/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftFacetEditorTab.form
index 0b1d6cb80..67867ecf5 100644
--- a/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftFacetEditorTab.form
+++ b/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftFacetEditorTab.form
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.demonwav.mcdev.facet.MinecraftFacetEditorTab">
-  <grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="13" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="10" vgap="10">
+  <grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="14" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="10" vgap="10">
     <margin top="10" left="10" bottom="10" right="10"/>
     <constraints>
       <xy x="20" y="20" width="500" height="600"/>
@@ -23,7 +23,7 @@
       </hspacer>
       <vspacer id="a91b3">
         <constraints>
-          <grid row="12" column="1" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <grid row="13" column="1" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
         </constraints>
       </vspacer>
       <component id="67298" class="javax.swing.JLabel">
@@ -398,6 +398,41 @@
           <text value=""/>
         </properties>
       </component>
+      <component id="d792" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="12" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <icon value="assets/icons/platform/PlaceholderAPI@2x.png"/>
+          <text value=""/>
+        </properties>
+      </component>
+      <component id="3219e" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="12" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value="PlaceholderAPI"/>
+        </properties>
+      </component>
+      <component id="fb47d" class="javax.swing.JCheckBox" binding="placeholderApiEnabledCheckBox">
+        <constraints>
+          <grid row="12" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <enabled value="true"/>
+          <text value=""/>
+        </properties>
+      </component>
+      <component id="faa13" class="javax.swing.JCheckBox" binding="placeholderApiAutoCheckBox">
+        <constraints>
+          <grid row="12" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <selected value="false"/>
+          <text value=""/>
+        </properties>
+      </component>
     </children>
   </grid>
 </form>
diff --git a/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftFacetEditorTab.kt b/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftFacetEditorTab.kt
index 345bbb77f..00c84b78b 100644
--- a/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftFacetEditorTab.kt
+++ b/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftFacetEditorTab.kt
@@ -43,6 +43,8 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura
     private lateinit var bungeecordAutoCheckBox: JCheckBox
     private lateinit var waterfallEnabledCheckBox: JCheckBox
     private lateinit var waterfallAutoCheckBox: JCheckBox
+    private lateinit var placeholderApiEnabledCheckBox: JCheckBox
+    private lateinit var placeholderApiAutoCheckBox: JCheckBox
 
     private lateinit var spongeIcon: JLabel
     private lateinit var mcpIcon: JLabel
@@ -59,7 +61,8 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura
             mcpEnabledCheckBox,
             mixinEnabledCheckBox,
             bungeecordEnabledCheckBox,
-            waterfallEnabledCheckBox
+            waterfallEnabledCheckBox,
+            placeholderApiEnabledCheckBox
         )
     }
 
@@ -74,7 +77,8 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura
             mcpAutoCheckBox,
             mixinAutoCheckBox,
             bungeecordAutoCheckBox,
-            waterfallAutoCheckBox
+            waterfallAutoCheckBox,
+            placeholderApiAutoCheckBox
         )
     }
 
@@ -137,6 +141,8 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura
         bungeecordEnabledCheckBox.addActionListener { unique(bungeecordEnabledCheckBox, waterfallEnabledCheckBox) }
         waterfallEnabledCheckBox.addActionListener { unique(waterfallEnabledCheckBox, bungeecordEnabledCheckBox) }
 
+        placeholderApiEnabledCheckBox.addActionListener { also(placeholderApiEnabledCheckBox) }
+
         return panel
     }
 
@@ -256,6 +262,7 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura
         private const val MIXIN = MCP + 1
         private const val BUNGEECORD = MIXIN + 1
         private const val WATERFALL = BUNGEECORD + 1
+        private const val PLACEHOLDERAPI = WATERFALL + 1
 
         private val platformTypes = arrayOf(
             PlatformType.BUKKIT,
@@ -267,10 +274,14 @@ class MinecraftFacetEditorTab(private val configuration: MinecraftFacetConfigura
             PlatformType.MCP,
             PlatformType.MIXIN,
             PlatformType.BUNGEECORD,
-            PlatformType.WATERFALL
+            PlatformType.WATERFALL,
+            PlatformType.PLACEHOLDERAPI
         )
 
         private val indexes =
-            intArrayOf(BUKKIT, SPIGOT, PAPER, SPONGE, FORGE, LITELOADER, MCP, MIXIN, BUNGEECORD, WATERFALL)
+            intArrayOf(
+                BUKKIT, SPIGOT, PAPER, SPONGE, FORGE, LITELOADER, MCP, MIXIN, BUNGEECORD, WATERFALL,
+                PLACEHOLDERAPI
+            )
     }
 }
diff --git a/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftLibraryKinds.kt b/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftLibraryKinds.kt
index 0cda8e660..bf87b7eb2 100644
--- a/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftLibraryKinds.kt
+++ b/src/main/kotlin/com/demonwav/mcdev/facet/MinecraftLibraryKinds.kt
@@ -19,6 +19,7 @@ import com.demonwav.mcdev.platform.forge.framework.FORGE_LIBRARY_KIND
 import com.demonwav.mcdev.platform.liteloader.framework.LITELOADER_LIBRARY_KIND
 import com.demonwav.mcdev.platform.mcp.framework.MCP_LIBRARY_KIND
 import com.demonwav.mcdev.platform.mixin.framework.MIXIN_LIBRARY_KIND
+import com.demonwav.mcdev.platform.placeholderapi.framework.PLACEHOLDERAPI_LIBRARY_KIND
 import com.demonwav.mcdev.platform.sponge.framework.SPONGE_LIBRARY_KIND
 
 val MINECRAFT_LIBRARY_KINDS = setOf(
@@ -31,5 +32,6 @@ val MINECRAFT_LIBRARY_KINDS = setOf(
     MCP_LIBRARY_KIND,
     MIXIN_LIBRARY_KIND,
     BUNGEECORD_LIBRARY_KIND,
-    WATERFALL_LIBRARY_KIND
+    WATERFALL_LIBRARY_KIND,
+    PLACEHOLDERAPI_LIBRARY_KIND
 )
diff --git a/src/main/kotlin/com/demonwav/mcdev/platform/PlatformType.kt b/src/main/kotlin/com/demonwav/mcdev/platform/PlatformType.kt
index f9428cae8..d31425763 100644
--- a/src/main/kotlin/com/demonwav/mcdev/platform/PlatformType.kt
+++ b/src/main/kotlin/com/demonwav/mcdev/platform/PlatformType.kt
@@ -28,6 +28,8 @@ import com.demonwav.mcdev.platform.mcp.McpModuleType
 import com.demonwav.mcdev.platform.mcp.framework.MCP_LIBRARY_KIND
 import com.demonwav.mcdev.platform.mixin.MixinModuleType
 import com.demonwav.mcdev.platform.mixin.framework.MIXIN_LIBRARY_KIND
+import com.demonwav.mcdev.platform.placeholderapi.PlaceholderApiModuleType
+import com.demonwav.mcdev.platform.placeholderapi.framework.PLACEHOLDERAPI_LIBRARY_KIND
 import com.demonwav.mcdev.platform.sponge.SpongeModuleType
 import com.demonwav.mcdev.platform.sponge.framework.SPONGE_LIBRARY_KIND
 import com.intellij.openapi.roots.libraries.LibraryKind
@@ -48,7 +50,8 @@ enum class PlatformType(
     BUNGEECORD(BungeeCordModuleType, "BungeeCord", "bungeecord.json", arrayOf(WATERFALL)),
     LITELOADER(LiteLoaderModuleType, "LiteLoader"),
     MIXIN(MixinModuleType, "Mixin"),
-    MCP(McpModuleType, "MCP");
+    MCP(McpModuleType, "MCP"),
+    PLACEHOLDERAPI(PlaceholderApiModuleType, "PlaceholderAPI", "spigot.json");
 
     companion object {
         fun removeParents(types: MutableSet<PlatformType>) =
@@ -65,6 +68,7 @@ enum class PlatformType(
             MIXIN_LIBRARY_KIND -> MIXIN
             BUNGEECORD_LIBRARY_KIND -> BUNGEECORD
             WATERFALL_LIBRARY_KIND -> WATERFALL
+            PLACEHOLDERAPI_LIBRARY_KIND -> PLACEHOLDERAPI
             else -> null
         }
     }
diff --git a/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiModule.kt b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiModule.kt
new file mode 100644
index 000000000..aa38f3ad8
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiModule.kt
@@ -0,0 +1,22 @@
+/*
+ * Minecraft Dev for IntelliJ
+ *
+ * https://minecraftdev.org
+ *
+ * Copyright (c) 2020 minecraft-dev
+ *
+ * MIT License
+ */
+
+package com.demonwav.mcdev.platform.placeholderapi
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.AbstractModule
+import com.demonwav.mcdev.platform.PlatformType
+
+class PlaceholderApiModule internal constructor(facet: MinecraftFacet) : AbstractModule(facet) {
+    override val moduleType = PlaceholderApiModuleType
+    override val type = PlatformType.PLACEHOLDERAPI
+    override val icon = PlatformAssets.PLACEHOLDERAPI_ICON
+}
diff --git a/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiModuleType.kt b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiModuleType.kt
new file mode 100644
index 000000000..3568ae150
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiModuleType.kt
@@ -0,0 +1,31 @@
+/*
+ * Minecraft Dev for IntelliJ
+ *
+ * https://minecraftdev.org
+ *
+ * Copyright (c) 2020 minecraft-dev
+ *
+ * MIT License
+ */
+
+package com.demonwav.mcdev.platform.placeholderapi
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.AbstractModuleType
+import com.demonwav.mcdev.platform.PlatformType
+
+object PlaceholderApiModuleType : AbstractModuleType<PlaceholderApiModule>("", "") {
+    private const val ID = "PLACEHOLDERAPI_MODULE_TYPE"
+
+    val IGNORED_ANNOTATIONS = emptyList<String>()
+    val LISTENER_ANNOTATIONS = emptyList<String>()
+
+    override val platformType = PlatformType.PLACEHOLDERAPI
+    override val icon = PlatformAssets.PLACEHOLDERAPI_ICON
+    override val id = ID
+    override val ignoredAnnotations = IGNORED_ANNOTATIONS
+    override val listenerAnnotations = LISTENER_ANNOTATIONS
+
+    override fun generateModule(facet: MinecraftFacet) = PlaceholderApiModule(facet)
+}
diff --git a/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiProjectConfiguration.kt b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiProjectConfiguration.kt
new file mode 100644
index 000000000..a06705a74
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiProjectConfiguration.kt
@@ -0,0 +1,102 @@
+/*
+ * Minecraft Dev for IntelliJ
+ *
+ * https://minecraftdev.org
+ *
+ * Copyright (c) 2020 minecraft-dev
+ *
+ * MIT License
+ */
+
+@file:Suppress("Duplicates")
+package com.demonwav.mcdev.platform.placeholderapi
+
+import com.demonwav.mcdev.buildsystem.BuildDependency
+import com.demonwav.mcdev.buildsystem.BuildRepository
+import com.demonwav.mcdev.buildsystem.BuildSystem
+import com.demonwav.mcdev.platform.PlatformType
+import com.demonwav.mcdev.platform.ProjectConfiguration
+import com.demonwav.mcdev.util.runWriteTask
+import com.intellij.ide.util.EditorHelper
+import com.intellij.openapi.progress.ProgressIndicator
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiManager
+
+class PlaceholderApiProjectConfiguration : ProjectConfiguration() {
+
+    var mcVersion = ""
+
+    override var type: PlatformType = PlatformType.PLACEHOLDERAPI
+
+    override fun create(project: Project, buildSystem: BuildSystem, indicator: ProgressIndicator) {
+        if (project.isDisposed) {
+            return
+        }
+
+        val baseConfig = base ?: return
+        val dirs = buildSystem.directories ?: return
+
+        runWriteTask {
+            indicator.text = "Writing main class"
+
+            var file = dirs.sourceDirectory
+            val files = baseConfig.mainClass.split(".").toTypedArray()
+            val className = files.last()
+            val packageName = baseConfig.mainClass.substring(0, baseConfig.mainClass.length - className.length - 1)
+            file = getMainClassDirectory(files, file)
+
+            val mainClassFile = file.findOrCreateChildData(this, className + ".java")
+            PlaceholderApiTemplate.applyMainClassTemplate(
+                project,
+                mainClassFile,
+                packageName,
+                className,
+                baseConfig.pluginName,
+                baseConfig.pluginVersion,
+                baseConfig.authors
+            )
+
+            PsiManager.getInstance(project).findFile(mainClassFile)?.let { mainClassPsi ->
+                EditorHelper.openInEditor(mainClassPsi)
+            }
+        }
+    }
+
+    override fun setupDependencies(buildSystem: BuildSystem) {
+        addRepos(buildSystem.repositories)
+        buildSystem.dependencies.add(
+            BuildDependency(
+                "org.spigotmc",
+                "spigot-api",
+                "$mcVersion-R0.1-SNAPSHOT",
+                mavenScope = "provided",
+                gradleConfiguration = "compileOnly"
+            )
+        )
+        addSonatype(buildSystem.repositories)
+        buildSystem.dependencies.add(
+            BuildDependency(
+                "me.clip",
+                "placeholderapi",
+                "LATEST",
+                mavenScope = "provided",
+                gradleConfiguration = "compileOnly"
+            )
+        )
+    }
+
+    private fun addRepos(list: MutableList<BuildRepository>) {
+        list.add(
+            BuildRepository(
+                "spigotmc-repo",
+                "https://hub.spigotmc.org/nexus/content/repositories/snapshots/"
+            )
+        )
+        list.add(
+            BuildRepository(
+                "placeholderapi-repo",
+                "https://repo.extendedclip.com/content/repositories/placeholderapi/"
+            )
+        )
+    }
+}
diff --git a/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiTemplate.kt b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiTemplate.kt
new file mode 100644
index 000000000..e3eb9ca28
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/PlaceholderApiTemplate.kt
@@ -0,0 +1,54 @@
+/*
+ * Minecraft Dev for IntelliJ
+ *
+ * https://minecraftdev.org
+ *
+ * Copyright (c) 2020 minecraft-dev
+ *
+ * MIT License
+ */
+
+package com.demonwav.mcdev.platform.placeholderapi
+
+import com.demonwav.mcdev.platform.BaseTemplate
+import com.demonwav.mcdev.util.MinecraftFileTemplateGroupFactory
+import com.intellij.ide.fileTemplates.FileTemplateManager
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.VirtualFile
+import java.util.Properties
+
+object PlaceholderApiTemplate {
+
+    fun applyMainClassTemplate(
+        project: Project,
+        mainClassFile: VirtualFile,
+        packageName: String,
+        className: String,
+        expansionName: String,
+        expansionVersion: String,
+        author: MutableList<String>
+    ) {
+        val properties = Properties()
+
+        properties.setProperty("PACKAGE", packageName)
+        properties.setProperty("CLASS_NAME", className)
+        properties.setProperty("EXPANSION_NAME", expansionName)
+        properties.setProperty("EXPANSION_VERSION", expansionVersion)
+        properties.setProperty("EXPANSION_AUTHOR", author[0])
+
+        BaseTemplate.applyTemplate(
+            project,
+            mainClassFile,
+            MinecraftFileTemplateGroupFactory.PLACEHOLDERAPI_MAIN_CLASS_TEMPLATE,
+            properties
+        )
+    }
+
+    fun applyPomTemplate(project: Project): String {
+        val properties = Properties()
+
+        val manager = FileTemplateManager.getInstance(project)
+        val fileTemplate = manager.getJ2eeTemplate(MinecraftFileTemplateGroupFactory.PLACEHOLDERAPI_POM_TEMPLATE)
+        return fileTemplate.getText(properties)
+    }
+}
diff --git a/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/framework/PlaceholderApiLibraryKind.kt b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/framework/PlaceholderApiLibraryKind.kt
new file mode 100644
index 000000000..2d1772e0f
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/framework/PlaceholderApiLibraryKind.kt
@@ -0,0 +1,15 @@
+/*
+ * Minecraft Dev for IntelliJ
+ *
+ * https://minecraftdev.org
+ *
+ * Copyright (c) 2020 minecraft-dev
+ *
+ * MIT License
+ */
+
+package com.demonwav.mcdev.platform.placeholderapi.framework
+
+import com.intellij.openapi.roots.libraries.LibraryKind
+
+val PLACEHOLDERAPI_LIBRARY_KIND: LibraryKind = LibraryKind.create("placeholderapi-library")
diff --git a/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/framework/PlaceholderApiPresentationProvider.kt b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/framework/PlaceholderApiPresentationProvider.kt
new file mode 100644
index 000000000..edbdf3d85
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/framework/PlaceholderApiPresentationProvider.kt
@@ -0,0 +1,35 @@
+/*
+ * Minecraft Dev for IntelliJ
+ *
+ * https://minecraftdev.org
+ *
+ * Copyright (c) 2020 minecraft-dev
+ *
+ * MIT License
+ */
+
+package com.demonwav.mcdev.platform.placeholderapi.framework
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.demonwav.mcdev.platform.placeholderapi.util.PlaceholderApiConstants
+import com.demonwav.mcdev.util.localFile
+import com.intellij.framework.library.LibraryVersionProperties
+import com.intellij.openapi.roots.libraries.LibraryPresentationProvider
+import com.intellij.openapi.util.io.JarUtil
+import com.intellij.openapi.vfs.VirtualFile
+
+class PlaceholderApiPresentationProvider :
+    LibraryPresentationProvider<LibraryVersionProperties>(PLACEHOLDERAPI_LIBRARY_KIND) {
+    override fun getIcon(properties: LibraryVersionProperties?) = PlatformAssets.PLACEHOLDERAPI_ICON
+
+    override fun detect(classesRoots: MutableList<VirtualFile>): LibraryVersionProperties? {
+        for (classesRoot in classesRoots) {
+            val file = classesRoot.localFile
+
+            if (JarUtil.containsClass(file, PlaceholderApiConstants.EXPANSION_CLASS)) {
+                return LibraryVersionProperties()
+            }
+        }
+        return null
+    }
+}
diff --git a/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/util/PlaceholderApiConstants.kt b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/util/PlaceholderApiConstants.kt
new file mode 100644
index 000000000..bbdf9bdb3
--- /dev/null
+++ b/src/main/kotlin/com/demonwav/mcdev/platform/placeholderapi/util/PlaceholderApiConstants.kt
@@ -0,0 +1,15 @@
+/*
+ * Minecraft Dev for IntelliJ
+ *
+ * https://minecraftdev.org
+ *
+ * Copyright (c) 2020 minecraft-dev
+ *
+ * MIT License
+ */
+
+package com.demonwav.mcdev.platform.placeholderapi.util
+
+object PlaceholderApiConstants {
+    const val EXPANSION_CLASS = "me.clip.placeholderapi.expansion.PlaceholderExpansion"
+}
diff --git a/src/main/kotlin/com/demonwav/mcdev/util/MinecraftFileTemplateGroupFactory.kt b/src/main/kotlin/com/demonwav/mcdev/util/MinecraftFileTemplateGroupFactory.kt
index 83495b372..d54d1448d 100644
--- a/src/main/kotlin/com/demonwav/mcdev/util/MinecraftFileTemplateGroupFactory.kt
+++ b/src/main/kotlin/com/demonwav/mcdev/util/MinecraftFileTemplateGroupFactory.kt
@@ -62,6 +62,13 @@ class MinecraftFileTemplateGroupFactory : FileTemplateGroupDescriptorFactory {
 
         group.addTemplate(FileTemplateDescriptor(MIXIN_OVERWRITE_FALLBACK, PlatformAssets.MIXIN_ICON))
 
+        group.addTemplate(
+            FileTemplateDescriptor(
+                PLACEHOLDERAPI_MAIN_CLASS_TEMPLATE,
+                PlatformAssets.PLACEHOLDERAPI_ICON
+            )
+        )
+        group.addTemplate(FileTemplateDescriptor(PLACEHOLDERAPI_POM_TEMPLATE, PlatformAssets.PLACEHOLDERAPI_ICON))
         return group
     }
 
@@ -102,5 +109,8 @@ class MinecraftFileTemplateGroupFactory : FileTemplateGroupDescriptorFactory {
         const val LITELOADER_MAIN_CLASS_TEMPLATE = "liteloader_main_class.java"
 
         const val MIXIN_OVERWRITE_FALLBACK = "Mixin Overwrite Fallback.java"
+
+        const val PLACEHOLDERAPI_MAIN_CLASS_TEMPLATE = "placeholderapi_main_class.java"
+        const val PLACEHOLDERAPI_POM_TEMPLATE = "placeholderapi_pom_template.xml"
     }
 }
diff --git a/src/main/resources/assets/icons/platform/PlaceholderAPI@2x.png b/src/main/resources/assets/icons/platform/PlaceholderAPI@2x.png
new file mode 100644
index 000000000..e8f16bbf5
Binary files /dev/null and b/src/main/resources/assets/icons/platform/PlaceholderAPI@2x.png differ
diff --git a/src/main/resources/fileTemplates/j2ee/palceholderapi_main_class.java.html b/src/main/resources/fileTemplates/j2ee/palceholderapi_main_class.java.html
new file mode 100644
index 000000000..cf003be04
--- /dev/null
+++ b/src/main/resources/fileTemplates/j2ee/palceholderapi_main_class.java.html
@@ -0,0 +1,15 @@
+<!--
+    Minecraft Dev for IntelliJ
+
+    https://minecraftdev.org
+
+    Copyright (c) 2020 minecraft-dev
+
+    MIT License
+-->
+
+<html>
+<body>
+<p>This is a built-in file template used to create a new main class for PlaceholderAPI.</p>
+</body>
+</html>
diff --git a/src/main/resources/fileTemplates/j2ee/placeholderapi_main_class.java.ft b/src/main/resources/fileTemplates/j2ee/placeholderapi_main_class.java.ft
new file mode 100644
index 000000000..c8830e289
--- /dev/null
+++ b/src/main/resources/fileTemplates/j2ee/placeholderapi_main_class.java.ft
@@ -0,0 +1,94 @@
+package ${PACKAGE};
+
+import org.bukkit.entity.Player;
+import me.clip.placeholderapi.expansion.PlaceholderExpansion;
+
+/**
+ * This class will automatically register as a placeholder expansion
+ * when a jar including this class is added to the directory
+ * {@code /plugins/PlaceholderAPI/expansions} on your server.
+ * <br>
+ * <br>If you create such a class inside your own plugin, you have to
+ * register it manually in your plugins {@code onEnable()} by using
+ * {@code new YourExpansionClass().register();}
+ */
+public class ${CLASS_NAME} extends PlaceholderExpansion {
+
+    /**
+     * This method should always return true unless we
+     * have a dependency we need to make sure is on the server
+     * for our placeholders to work!
+     *
+     * @return always true since we do not have any dependencies.
+     */
+    @Override
+    public boolean canRegister(){
+        return true;
+    }
+
+    /**
+     * The name of the person who created this expansion should go here.
+     *
+     * @return The name of the author as a String.
+     */
+    @Override
+    public String getAuthor(){
+        return "${EXPANSION_AUTHOR}";
+    }
+
+    /**
+     * The placeholder identifier should go here.
+     * <br>This is what tells PlaceholderAPI to call our onRequest
+     * method to obtain a value if a placeholder starts with our
+     * identifier.
+     * <br>This must be unique and can not contain % or _
+     *
+     * @return The identifier in {@code %<identifier>_<value>%} as String.
+     */
+    @Override
+    public String getIdentifier(){
+        return "${EXPANSION_NAME}";
+    }
+
+    /**
+     * This is the version of this expansion.
+     * <br>You don't have to use numbers, since it is set as a String.
+     *
+     * @return The version as a String.
+     */
+    @Override
+    public String getVersion(){
+        return "${EXPANSION_VERSION}";
+    }
+
+    /**
+     * This is the method called when a placeholder with our identifier
+     * is found and needs a value.
+     * <br>We specify the value identifier in this method.
+     * <br>Since version 2.9.1 can you use OfflinePlayers in your requests.
+     *
+     * @param  player
+     *         A {@link org.bukkit.OfflinePlayer OfflinePlayer}.
+     * @param  identifier
+     *         A String containing the identifier/value.
+     *
+     * @return Possibly-null String of the requested identifier.
+     */
+    @Override
+    public String onPlaceholderRequest(Player player, String identifier){
+
+        // %example_placeholder1%
+        if(identifier.equals("placeholder1")){
+            return "placeholder1 works";
+        }
+
+        // %example_placeholder2%
+        if(identifier.equals("placeholder2")){
+            return "placeholder2 works";
+        }
+
+        // We return null if an invalid placeholder (f.e. %example_placeholder3%)
+        // was provided
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/fileTemplates/j2ee/placeholderapi_pom_template.xml.ft b/src/main/resources/fileTemplates/j2ee/placeholderapi_pom_template.xml.ft
new file mode 100644
index 000000000..36e5174f8
--- /dev/null
+++ b/src/main/resources/fileTemplates/j2ee/placeholderapi_pom_template.xml.ft
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId></groupId>
+  <artifactId></artifactId>
+  <version></version>
+  <packaging>jar</packaging>
+
+  <name></name>
+
+  <properties>
+    <java.version>1.8</java.version>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <build>
+    <defaultGoal>clean package</defaultGoal>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.7.0</version>
+        <configuration>
+          <source>${java.version}</source>
+          <target>${java.version}</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>3.1.0</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <createDependencyReducedPom>false</createDependencyReducedPom>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+  </build>
+
+  <repositories></repositories>
+
+  <dependencies></dependencies>
+</project>
diff --git a/src/main/resources/fileTemplates/j2ee/placeholderapi_pom_template.xml.html b/src/main/resources/fileTemplates/j2ee/placeholderapi_pom_template.xml.html
new file mode 100644
index 000000000..08bd5d649
--- /dev/null
+++ b/src/main/resources/fileTemplates/j2ee/placeholderapi_pom_template.xml.html
@@ -0,0 +1,15 @@
+<!--
+    Minecraft Dev for IntelliJ
+
+    https://minecraftdev.org
+
+    Copyright (c) 2020 minecraft-dev
+
+    MIT License
+-->
+
+<html>
+<body>
+<p>This is a built-in file template used to create a new pom.xml for PlaceholderAPI.</p>
+</body>
+</html>