diff --git a/_templates/add-interface/StandardPlugin/implements.ejs.t b/_templates/add-interface/StandardPlugin/implements.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..7e42f254b362037a7f3e49de06948b419263f8f3
--- /dev/null
+++ b/_templates/add-interface/StandardPlugin/implements.ejs.t
@@ -0,0 +1,7 @@
+---
+inject: true
+to: <%= pluginclassname %>
+skip_if: StandardPlugin,
+after: \/\* Plugin Interfaces \*\/
+---
+    StandardPlugin,
\ No newline at end of file
diff --git a/_templates/add-interface/StandardPlugin/methods.ejs.t b/_templates/add-interface/StandardPlugin/methods.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..7a81c88d4046fb5d76c973e7c3c217422930cdac
--- /dev/null
+++ b/_templates/add-interface/StandardPlugin/methods.ejs.t
@@ -0,0 +1,78 @@
+---
+inject: true
+to: <%= pluginclassname %>
+skip_if: getInfoTemplate|getIconNavigation|getTabNavigation|getMetadata
+after: \/\* Interface Methods \*\/
+---
+    /**
+     * Return a template (an instance of the Flexi_Template class)
+     * to be rendered on the course summary page. Return NULL to
+     * render nothing for this plugin.
+     *
+     * The template will automatically get a standard layout, which
+     * can be configured via attributes set on the template:
+     *
+     *  title        title to display, defaults to plugin name
+     *  icon_url     icon for this plugin (if any)
+     *  admin_url    admin link for this plugin (if any)
+     *  admin_title  title for admin link (default: Administration)
+     *
+     * @return object   template object to render or NULL
+     */
+    function getInfoTemplate($course_id)
+    {
+        return null;
+    }
+
+    /**
+     * Return a navigation object representing this plugin in the
+     * course overview table or return NULL if you want to display
+     * no icon for this plugin (or course). The navigation object's
+     * title will not be shown, only the image (and its associated
+     * attributes like 'title') and the URL are actually used.
+     *
+     * By convention, new or changed plugin content is indicated
+     * by a different icon and a corresponding tooltip.
+     *
+     * @param  string   $course_id   course or institute range id
+     * @param  int      $last_visit  time of user's last visit
+     * @param  string   $user_id     the user to get the navigation for
+     *
+     * @return object   navigation item to render or NULL
+     */
+    function getIconNavigation($course_id, $last_visit, $user_id)
+    {
+        return null;
+    }
+
+    /**
+     * Return a navigation object representing this plugin in the
+     * course overview table or return NULL if you want to display
+     * no icon for this plugin (or course). The navigation object's
+     * title will not be shown, only the image (and its associated
+     * attributes like 'title') and the URL are actually used.
+     *
+     * By convention, new or changed plugin content is indicated
+     * by a different icon and a corresponding tooltip.
+     *
+     * @param  string   $course_id   course or institute range id
+     *
+     * @return array    navigation item to render or NULL
+     */
+    function getTabNavigation($course_id)
+    {
+        return null;
+    }
+
+
+    /**
+     * Provides metadata like a descriptional text for this module that
+     * is shown on the course "+" page to inform users about what the
+     * module acutally does. Additionally, a URL can be specified.
+     *
+     * @return array    metadata containg description and/or url
+     */
+    function getMetadata()
+    {
+        return [];
+    }
diff --git a/_templates/add-interface/StandardPlugin/prompt.js b/_templates/add-interface/StandardPlugin/prompt.js
new file mode 100644
index 0000000000000000000000000000000000000000..b803c5e0461109d7bd46dc1dc2ea0fd32dd6955b
--- /dev/null
+++ b/_templates/add-interface/StandardPlugin/prompt.js
@@ -0,0 +1,39 @@
+const fs = require("fs");
+const path = require("path");
+
+module.exports = [
+  {
+    type: "list",
+    name: "pluginclassname",
+    message: "Welche Plugin-Klasse?",
+    choices: function() {
+      const pluginDirectory = path.join(__dirname, "../../..");
+      const manifestFilename = pluginDirectory + "/plugin.manifest";
+
+      const manifest = fs.readFileSync(manifestFilename, "utf-8");
+      const result = manifest.match(/^pluginclassname=.*/gm);
+
+      if (!result) {
+        return null;
+      }
+
+      const x = result.reduce((memo, item) => {
+        const pluginClassname = item.substr("pluginclassname=".length);
+        console.log(pluginClassname);
+        const oldStyle = pluginClassname + ".class.php";
+        const newStyle = pluginClassname + ".php";
+        if (fs.existsSync(path.join(pluginDirectory, oldStyle))) {
+          memo.push(oldStyle);
+        } else if (fs.existsSync(path.join(pluginDirectory, newStyle))) {
+          memo.push(newStyle);
+        }
+
+        return memo;
+      }, []);
+
+      console.log(x);
+
+      return x;
+    }
+  }
+];
diff --git a/_templates/generator/help/index.ejs.t b/_templates/generator/help/index.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..90a29aff2d87b267f1c6941415cf719fa5a65944
--- /dev/null
+++ b/_templates/generator/help/index.ejs.t
@@ -0,0 +1,5 @@
+---
+message: |
+  hygen {bold generator new} --name [NAME] --action [ACTION]
+  hygen {bold generator with-prompt} --name [NAME] --action [ACTION]
+---
\ No newline at end of file
diff --git a/_templates/generator/new/hello.ejs.t b/_templates/generator/new/hello.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..5680d963905d6ef77c7f387da44dcc495aaf4649
--- /dev/null
+++ b/_templates/generator/new/hello.ejs.t
@@ -0,0 +1,18 @@
+---
+to: _templates/<%= name %>/<%= action || 'new' %>/hello.ejs.t
+---
+---
+to: app/hello.js
+---
+const hello = ```
+Hello!
+This is your first hygen template.
+
+Learn what it can do here:
+
+https://github.com/jondot/hygen
+```
+
+console.log(hello)
+
+
diff --git a/_templates/generator/with-prompt/hello.ejs.t b/_templates/generator/with-prompt/hello.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..ba6abc562d090a8c263f82ac3896a53fa568aed5
--- /dev/null
+++ b/_templates/generator/with-prompt/hello.ejs.t
@@ -0,0 +1,18 @@
+---
+to: _templates/<%= name %>/<%= action || 'new' %>/hello.ejs.t
+---
+---
+to: app/hello.js
+---
+const hello = ```
+Hello!
+This is your first prompt based hygen template.
+
+Learn what it can do here:
+
+https://github.com/jondot/hygen
+```
+
+console.log(hello)
+
+
diff --git a/_templates/generator/with-prompt/prompt.ejs.t b/_templates/generator/with-prompt/prompt.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..d5984a5f44eaf3ce2e2a6831d83fb53e2cbd2739
--- /dev/null
+++ b/_templates/generator/with-prompt/prompt.ejs.t
@@ -0,0 +1,16 @@
+---
+to: _templates/<%= name %>/<%= action || 'new' %>/prompt.js
+---
+
+// see types of prompts:
+// https://github.com/SBoudrias/Inquirer.js#prompt-types
+//
+// and for examples for prompts:
+// https://github.com/SBoudrias/Inquirer.js/tree/master/examples
+module.exports = [
+  {
+    type: 'input',
+    name: 'message',
+    message: "What's your message?"
+  }
+]
diff --git a/_templates/plugin/add/hello.ejs.t b/_templates/plugin/add/hello.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..86c0af382717ca2b5963317a553a050d8e77cb77
--- /dev/null
+++ b/_templates/plugin/add/hello.ejs.t
@@ -0,0 +1,21 @@
+---
+to: <%= pluginclassname %>.php
+---
+<?php
+
+/**
+ * Stud.IP plugin.
+ */
+class <%= pluginclassname %> extends StudIPPlugin implements
+    /* Plugin Interfaces */
+    <%= plugininterfaces.join(",\n    ") %>
+{
+    public function __construct()
+    {
+        parent::__construct();
+
+        require_once 'vendor/autoload.php';
+    }
+
+    /* Interface Methods */
+}
diff --git a/_templates/plugin/add/prompt.js b/_templates/plugin/add/prompt.js
new file mode 100644
index 0000000000000000000000000000000000000000..c3743644c84ba0ced66af41fc76cb467ae078d30
--- /dev/null
+++ b/_templates/plugin/add/prompt.js
@@ -0,0 +1,30 @@
+const fs = require("fs");
+const path = require("path");
+
+module.exports = [
+  {
+    type: "input",
+    name: "pluginclassname",
+    message: "Wie soll die Plugin-Klasse heißen?",
+    validate: function(input) {
+      if (input.match(/^[A-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/)) {
+        return true;
+      }
+
+      return "Ungültiger Klassenname";
+    }
+  },
+  {
+    type: "checkbox",
+    name: "plugininterfaces",
+    message: "Welche Plugin-Interface?",
+    choices: ["StandardPlugin", "SystemPlugin"],
+    validate: function(input) {
+      if (input.length) {
+        return true;
+      }
+
+      return "Mindestens ein Plugin-Interface muss gewählt sein.";
+    }
+  }
+];
diff --git a/_templates/plugin/add/standard.ejs.t b/_templates/plugin/add/standard.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..e44853767fe38812354b997566f76cf721ca14f6
--- /dev/null
+++ b/_templates/plugin/add/standard.ejs.t
@@ -0,0 +1,65 @@
+---
+inject: true
+to: <%= pluginclassname %>.php
+skip_if: getInfoTemplate
+after: \/\* Interface Methods \*\/
+---
+    /**
+     * Return a template (an instance of the Flexi_Template class)
+     * to be rendered on the course summary page. Return NULL to
+     * render nothing for this plugin.
+     *
+     * The template will automatically get a standard layout, which
+     * can be configured via attributes set on the template:
+     *
+     *  title        title to display, defaults to plugin name
+     *  icon_url     icon for this plugin (if any)
+     *  admin_url    admin link for this plugin (if any)
+     *  admin_title  title for admin link (default: Administration)
+     *
+     * @return object   template object to render or NULL
+     */
+    function getInfoTemplate($course_id)
+    {
+        return null;
+    }
+
+    /**
+     * Return a navigation object representing this plugin in the
+     * course overview table or return NULL if you want to display
+     * no icon for this plugin (or course). The navigation object's
+     * title will not be shown, only the image (and its associated
+     * attributes like 'title') and the URL are actually used.
+     *
+     * By convention, new or changed plugin content is indicated
+     * by a different icon and a corresponding tooltip.
+     *
+     * @param string $course_id  course or institute range id
+     * @param int    $last_visit time of user's last visit
+     * @param string $user_id    the user to get the navigation for
+     *
+     * @return object navigation item to render or NULL
+     */
+    public function getIconNavigation($course_id, $last_visit, $user_id)
+    {
+        return null;
+    }
+
+    /**
+     * Return a navigation object representing this plugin in the
+     * course overview table or return NULL if you want to display
+     * no icon for this plugin (or course). The navigation object's
+     * title will not be shown, only the image (and its associated
+     * attributes like 'title') and the URL are actually used.
+     *
+     * By convention, new or changed plugin content is indicated
+     * by a different icon and a corresponding tooltip.
+     *
+     * @param string $course_id course or institute range id
+     *
+     * @return array navigation item to render or NULL
+     */
+    public function getTabNavigation($course_id)
+    {
+        return null;
+    }
diff --git a/_templates/plugin/add/system.ejs.t b/_templates/plugin/add/system.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..275f96d3e48316d3c34e2f8a7ad7f117d819bf76
--- /dev/null
+++ b/_templates/plugin/add/system.ejs.t
@@ -0,0 +1,6 @@
+---
+inject: true
+to: <%= pluginclassname %>.php
+xskip_if: SystemPlugin,
+after: \/\* Interface Methods \*\/
+---
diff --git a/_templates/plugin/trails/prompt.js b/_templates/plugin/trails/prompt.js
new file mode 100644
index 0000000000000000000000000000000000000000..28ca77be39f4d0ff906df08ecdce07bffdd5a7c1
--- /dev/null
+++ b/_templates/plugin/trails/prompt.js
@@ -0,0 +1,34 @@
+const fs = require("fs");
+const path = require("path");
+
+module.exports = [
+  {
+    type: "list",
+    name: "pluginclassname",
+    message: "Welche Plugin-Klasse?",
+    choices: function() {
+      const pluginDirectory = path.join(__dirname, "../../..");
+      const manifestFilename = pluginDirectory + "/plugin.manifest";
+
+      const manifest = fs.readFileSync(manifestFilename, "utf-8");
+      const result = manifest.match(/^pluginclassname=.*/gm);
+
+      if (!result) {
+        return null;
+      }
+
+      return result.reduce((memo, item) => {
+        const pluginClassname = item.substr("pluginclassname=".length);
+        const oldStyle = pluginClassname + ".class.php";
+        const newStyle = pluginClassname + ".php";
+        if (fs.existsSync(path.join(pluginDirectory, oldStyle))) {
+          memo.push(oldStyle);
+        } else if (fs.existsSync(path.join(pluginDirectory, newStyle))) {
+          memo.push(newStyle);
+        }
+
+        return memo;
+      }, []);
+    }
+  }
+];
diff --git a/ExamplePlugin.php b/_templates/plugin/trails/trails.ejs.t
similarity index 73%
rename from ExamplePlugin.php
rename to _templates/plugin/trails/trails.ejs.t
index 8eea4f4ecaefd2edacfbab846ca155f25c63a368..17dc276ce36c0358f356811d232d08fe6ad4cf05 100644
--- a/ExamplePlugin.php
+++ b/_templates/plugin/trails/trails.ejs.t
@@ -1,19 +1,9 @@
-<?php
-
-/**
- * Example Stud.IP plugin.
- */
-class ExamplePlugin extends StudIPPlugin implements
-    /* Plugin Interfaces */
-    SystemPlugin
-{
-    public function __construct()
-    {
-        parent::__construct();
-
-        require_once 'vendor/autoload.php';
-    }
-
+---
+inject: true
+to: <%= pluginclassname %>
+skip_if: perform
+before: \/\* Interface Methods \*\/
+---
     /**
      * This method dispatches all actions.
      *
@@ -39,6 +29,3 @@ class ExamplePlugin extends StudIPPlugin implements
             }
         }
     }
-
-    /* Interface Methods */
-}
diff --git a/_templates/plugin/trails/trailsController.ejs.t b/_templates/plugin/trails/trailsController.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..3647b2756efca94d66ddbcf0d7bd4e495200ec61
--- /dev/null
+++ b/_templates/plugin/trails/trailsController.ejs.t
@@ -0,0 +1,15 @@
+---
+to: controllers/index.php
+---
+<?php
+
+class IndexController extends \StudipController
+{
+    public function before_filter(&$action, &$args)
+    {
+    }
+
+    protected function index_url()
+    {
+    }
+}
diff --git a/_templates/plugin/trails/trailsView.ejs.t b/_templates/plugin/trails/trailsView.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..f7559d18e0b46625618e27a88ab02b028f4e9c90
--- /dev/null
+++ b/_templates/plugin/trails/trailsView.ejs.t
@@ -0,0 +1,5 @@
+---
+to: views/index/index.php
+---
+<h1>Hallo, Welt!</h1>
+<p>Find me in {pluginDirectory}/views/index/index.php</p>
diff --git a/_templates/trails/action/hello.ejs.t b/_templates/trails/action/hello.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..095a04ee93cad49210ca510b826b4ade77e0235e
--- /dev/null
+++ b/_templates/trails/action/hello.ejs.t
@@ -0,0 +1,15 @@
+---
+to: app/hello.js
+---
+const hello = ```
+Hello!
+This is your first hygen template.
+
+Learn what it can do here:
+
+https://github.com/jondot/hygen
+```
+
+console.log(hello)
+
+
diff --git a/_templates/trails/controller/hello.ejs.t b/_templates/trails/controller/hello.ejs.t
new file mode 100644
index 0000000000000000000000000000000000000000..095a04ee93cad49210ca510b826b4ade77e0235e
--- /dev/null
+++ b/_templates/trails/controller/hello.ejs.t
@@ -0,0 +1,15 @@
+---
+to: app/hello.js
+---
+const hello = ```
+Hello!
+This is your first hygen template.
+
+Learn what it can do here:
+
+https://github.com/jondot/hygen
+```
+
+console.log(hello)
+
+