diff --git a/src/VSCodeExtension/.vscodeignore b/src/VSCodeExtension/.vscodeignore
index 5231325bff..ffb0eb5ec9 100644
--- a/src/VSCodeExtension/.vscodeignore
+++ b/src/VSCodeExtension/.vscodeignore
@@ -3,10 +3,10 @@
 out/test/**
 out/**/*.map
 src/**
-.gitignore
+**/.gitignore
 tsconfig.json
 vsc-extension-quickstart.md
 tslint.json
 Build-Dependencies.ps1
 BUILDING.md
-*.v.template
+**/*.v.template
diff --git a/src/VSCodeExtension/package.json.v.template b/src/VSCodeExtension/package.json.v.template
index 57cc891af0..ddcd4518ab 100644
--- a/src/VSCodeExtension/package.json.v.template
+++ b/src/VSCodeExtension/package.json.v.template
@@ -36,7 +36,7 @@
         "commands": [
             {
                 "command": "quantum.installTemplates",
-                "title": "Q#: Install project templates"
+                "title": "Q#: Install command line project templates"
             },
 
             {
@@ -114,6 +114,9 @@
         "vscode-extension-telemetry": "0.0.18",
         "vscode-languageclient": "5.1.0",
         "which": "1.3.1",
+        "yeoman-environment": "^2.10.3",
+        "yeoman-generator": "^2.0.1",
+        "yosay": "^2.0.1",
         "@types/fs-extra": "^8.0.0"
     },
     "devDependencies": {
@@ -121,6 +124,11 @@
         "typescript": "^2.6.1",
         "tslint": "^5.8.0",
         "mocha": "^5.2.0",
+        "@types/yeoman-generator": "^3.1.4",
+        "@types/yosay": "^0.0.29",
+        "yeoman-test": "^1.7.0",
+        "yeoman-assert": "^3.1.0",
+        "@types/yeoman-environment": "^2.3.3",
         "@types/node": "^9.6.5",
         "@types/mocha": "^5.2.0",
         "@types/which": "1.3.1",
diff --git a/src/VSCodeExtension/src/commands.ts b/src/VSCodeExtension/src/commands.ts
index 37c6778afb..f45b11f6a2 100644
--- a/src/VSCodeExtension/src/commands.ts
+++ b/src/VSCodeExtension/src/commands.ts
@@ -10,6 +10,9 @@ import { IPackageInfo } from './packageInfo';
 import * as semver from 'semver';
 import { promisify } from 'util';
 import { oc } from 'ts-optchain';
+import { QSharpGenerator } from './yeoman-generator';
+
+import * as yeoman from 'yeoman-environment';
 
 export function registerCommand(context: vscode.ExtensionContext, name: string, action: () => void) {
     context.subscriptions.push(
@@ -22,107 +25,17 @@ export function registerCommand(context: vscode.ExtensionContext, name: string,
     )
 }
 
-function createNewProjectAtUri(dotNetSdk: DotnetInfo, projectType: string, uri: vscode.Uri) {
-    let proc = cp.spawn(
-        dotNetSdk.path,
-        ["new", projectType, "-lang", "Q#", "-o", uri.fsPath]
-    );
-    
-    let errorMessage = "";
-    proc.stderr.on('data', data => {
-        errorMessage = errorMessage + data;
-    });
-
-    proc.on(
-        'exit', (code, signal) => {
-            if (code === 0) {
-                const openItem = "Open new project...";
-                vscode.window.showInformationMessage(
-                    `Successfully created new project at ${uri.fsPath}.`,
-                    openItem
-                ).then(
-                    (item) => {
-                        if (item === openItem) {
-                            vscode.commands.executeCommand(
-                                "vscode.openFolder",
-                                uri
-                            ).then(
-                                (value) => {},
-                                (value) => {
-                                    vscode.window.showErrorMessage("Could not open new project");
-                                }
-                            );
-                        }
-                    }
-                );
-            } else {
-                // Check if the problem was that the project templates are missing.
-                // If so, we can give a more helpful error message and offer the
-                // user to install templates.
-                if (errorMessage.includes("Q#") && errorMessage.includes("-lang")) {
-                    const installTemplatesItem = "Install project templates and retry";
-                    vscode.window.showErrorMessage(
-                        "Project creation failed. The Q# project templates may not be installed.",
-                        installTemplatesItem
-                    )
-                    .then(
-                        item => {
-                            if (item === installTemplatesItem) {
-                                vscode.commands.executeCommand(
-                                    "quantum.installTemplates"
-                                ).then(
-                                    () => createNewProjectAtUri(dotNetSdk, projectType, uri)
-                                );
-                            }
-                        }
-                    );
-                } else {
-                    vscode.window.showErrorMessage(
-                        `.NET Core SDK exited with code ${code} when creating a new project:\n${errorMessage}`
-                    );
-                }
-            }
+export function createNewProject(context: vscode.ExtensionContext) {    
+    let env = yeoman.createEnv();
+    env.options.extensionPath = context.extensionPath;
+    env.registerStub(QSharpGenerator, 'qsharp:app');
+    env.run('qsharp:app', (err: null | Error) => {
+        if (err) {
+            let errorMessage = err.name + ": " + err.message;
+            console.log(errorMessage);
+            vscode.window.showErrorMessage(errorMessage);
         }
-    );
-}
-
-export function createNewProject(dotNetSdk: DotnetInfo) {    
-    const projectTypes: {[key: string]: string} = {
-        "Standalone console application": "console",
-        "Quantum library": "classlib",
-        "Unit testing project": "xunit"
-    };
-    vscode.window.showQuickPick(
-        Object.keys(projectTypes)
-    ).then(
-        projectTypeSelection => {
-            if (projectTypeSelection === undefined) {
-                throw undefined;
-            }
-            let projectType = projectTypes[projectTypeSelection];
-            
-            vscode.window.showSaveDialog({
-                saveLabel: "Create Project"
-            }).then(
-                (uri) => {
-                    if (uri !== undefined) {
-                        if (uri.scheme !== "file") {
-                            vscode.window.showErrorMessage(
-                                "New projects must be saved to the filesystem."
-                            );
-                            throw new Error("URI scheme was not file.");
-                        }
-                        else {
-                            return uri;
-                        }
-                    } else {
-                        throw undefined;
-                    }
-                }
-            )
-            .then(uri => createNewProjectAtUri(dotNetSdk, projectType, uri));
-        }
-    );
+    });
 }
 
 export function installTemplates(dotNetSdk: DotnetInfo, packageInfo?: IPackageInfo) {
diff --git a/src/VSCodeExtension/src/extension.ts b/src/VSCodeExtension/src/extension.ts
index f887d417b1..7debb216c8 100644
--- a/src/VSCodeExtension/src/extension.ts
+++ b/src/VSCodeExtension/src/extension.ts
@@ -63,7 +63,7 @@ export async function activate(context: vscode.ExtensionContext) {
         context,
         "quantum.newProject",
         () => {
-            requireDotNetSdk(dotNetSdkVersion).then(createNewProject);
+            createNewProject(context);
         }
     );
 
diff --git a/src/VSCodeExtension/src/yeoman-generator.ts b/src/VSCodeExtension/src/yeoman-generator.ts
new file mode 100644
index 0000000000..189610a73c
--- /dev/null
+++ b/src/VSCodeExtension/src/yeoman-generator.ts
@@ -0,0 +1,123 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+import * as vscode from 'vscode';
+import * as fs from 'fs-extra';
+import * as path from 'path';
+import yo = require("yeoman-generator");
+import yosay = require("yosay");
+
+export class QSharpGenerator extends yo {
+
+    constructor(args : any, opts : any) {
+        super(args, opts);
+        console.log(
+            yosay("Welcome to the Q# generator!")
+        );
+
+        this.sourceRoot(path.join(this.options.extensionPath, "templates"));
+    }
+
+    prompting() {
+        let done = this.async();
+
+        // This dictionary maps the public description of the project type to the name
+        // of the folder with the corresponding template files.
+        const projectTypes: {[key: string]: string} = {
+            "Standalone console application": "application",
+            "Quantum library": "library",
+            "Unit testing project": "unittest"
+        };
+
+        vscode.window.showQuickPick(
+            Object.keys(projectTypes)
+        ).then(
+            projectTypeSelection => {
+                if (projectTypeSelection === undefined) {
+                    throw undefined;
+                }
+                
+                vscode.window.showSaveDialog({
+                    saveLabel: "Create Project"
+                }).then(
+                    (uri) => {
+                        if (uri !== undefined) {
+                            if (uri.scheme !== "file") {
+                                vscode.window.showErrorMessage(
+                                    "New projects must be saved to the filesystem."
+                                );
+                                throw new Error("URI scheme was not file.");
+                            }
+                            else {
+                                return uri;
+                            }
+                        } else {
+                            throw undefined;
+                        }
+                    }
+                )
+                .then(uri => { 
+                    this.options.projectType = projectTypes[projectTypeSelection];
+                    this.options.outputUri = uri;
+                    done();
+                });
+            }
+        );
+    }
+
+    writing() {
+        console.log(
+            yosay("Creating Q# project.")
+        );
+
+        let sourceDir = path.join(this.templatePath(), this.options.projectType);
+        let targetDir = this.options.outputUri.fsPath;
+        fs.mkdir(targetDir);
+
+        // Namespace is the directory name itself.
+        let dirs = targetDir.split(path.sep);
+
+        // In case there is a trailing separator.
+        let namespaceName = dirs.pop() || dirs.pop();
+
+        fs.readdir(sourceDir, (err, files) => {
+            if (err){
+                throw err;
+            }
+            files.forEach( (filename) => {
+                let destinationName = filename;
+                let fileExtension = filename.split(".").pop();
+
+                if (fileExtension && fileExtension.toLowerCase() === "csproj") {
+                    destinationName = namespaceName + ".csproj";
+                }
+
+                this.fs.copyTpl(
+                    path.join(sourceDir, filename),
+                    path.join(targetDir, destinationName),
+                    {  name: namespaceName }
+                );
+            });
+        });
+
+        const openItem = "Open new project...";
+        vscode.window.showInformationMessage(
+            `Successfully created new project at ${targetDir}.`,
+            openItem
+        ).then(
+            (item) => {
+                if (item === openItem) {
+                    vscode.commands.executeCommand(
+                        "vscode.openFolder",
+                        this.options.outputUri
+                    ).then(
+                        (value) => { },
+                        (value) => {
+                            vscode.window.showErrorMessage("Could not open new project");
+                        }
+                    );
+                }
+            }
+        );
+    }
+}
diff --git a/src/VSCodeExtension/templates/application/.gitignore b/src/VSCodeExtension/templates/application/.gitignore
new file mode 100644
index 0000000000..2b04328876
--- /dev/null
+++ b/src/VSCodeExtension/templates/application/.gitignore
@@ -0,0 +1,2 @@
+# Generated or copied files
+*.csproj
diff --git a/src/VSCodeExtension/templates/application/Application.csproj.v.template b/src/VSCodeExtension/templates/application/Application.csproj.v.template
new file mode 100644
index 0000000000..2061e46bde
--- /dev/null
+++ b/src/VSCodeExtension/templates/application/Application.csproj.v.template
@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.Quantum.Sdk/#NUGET_VERSION#">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+  </PropertyGroup>
+
+</Project>
diff --git a/src/VSCodeExtension/templates/application/Program.qs b/src/VSCodeExtension/templates/application/Program.qs
new file mode 100644
index 0000000000..969e2dcce0
--- /dev/null
+++ b/src/VSCodeExtension/templates/application/Program.qs
@@ -0,0 +1,10 @@
+﻿namespace <%= name %> {
+    open Microsoft.Quantum.Canon;
+    open Microsoft.Quantum.Intrinsic;
+    
+
+    @EntryPoint()
+    operation SayHello() : Unit {
+        Message("Hello quantum world!");
+    }
+}
diff --git a/src/VSCodeExtension/templates/library/.gitignore b/src/VSCodeExtension/templates/library/.gitignore
new file mode 100644
index 0000000000..2b04328876
--- /dev/null
+++ b/src/VSCodeExtension/templates/library/.gitignore
@@ -0,0 +1,2 @@
+# Generated or copied files
+*.csproj
diff --git a/src/VSCodeExtension/templates/library/Library.csproj.v.template b/src/VSCodeExtension/templates/library/Library.csproj.v.template
new file mode 100644
index 0000000000..b5159e47ee
--- /dev/null
+++ b/src/VSCodeExtension/templates/library/Library.csproj.v.template
@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.Quantum.Sdk/#NUGET_VERSION#">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.1</TargetFramework>
+  </PropertyGroup>
+
+</Project>
diff --git a/src/VSCodeExtension/templates/library/Library.qs b/src/VSCodeExtension/templates/library/Library.qs
new file mode 100644
index 0000000000..54a38c7587
--- /dev/null
+++ b/src/VSCodeExtension/templates/library/Library.qs
@@ -0,0 +1,9 @@
+﻿namespace <%= name %> {
+    open Microsoft.Quantum.Canon;
+    open Microsoft.Quantum.Intrinsic;
+
+
+    operation SayHello() : Unit {
+        Message("Hello quantum world!");
+    }
+}
diff --git a/src/VSCodeExtension/templates/unittest/.gitignore b/src/VSCodeExtension/templates/unittest/.gitignore
new file mode 100644
index 0000000000..2b04328876
--- /dev/null
+++ b/src/VSCodeExtension/templates/unittest/.gitignore
@@ -0,0 +1,2 @@
+# Generated or copied files
+*.csproj
diff --git a/src/VSCodeExtension/templates/unittest/Test.csproj.v.template b/src/VSCodeExtension/templates/unittest/Test.csproj.v.template
new file mode 100644
index 0000000000..40bccfea26
--- /dev/null
+++ b/src/VSCodeExtension/templates/unittest/Test.csproj.v.template
@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.Quantum.Sdk/#NUGET_VERSION#">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <IsPackable>false</IsPackable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.Quantum.Xunit" Version="#NUGET_VERSION#" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
+    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
+    <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
+  </ItemGroup>
+
+</Project>
diff --git a/src/VSCodeExtension/templates/unittest/Tests.qs b/src/VSCodeExtension/templates/unittest/Tests.qs
new file mode 100644
index 0000000000..901bb6b366
--- /dev/null
+++ b/src/VSCodeExtension/templates/unittest/Tests.qs
@@ -0,0 +1,16 @@
+﻿namespace <%= name %> {
+    open Microsoft.Quantum.Canon;
+    open Microsoft.Quantum.Diagnostics;
+    open Microsoft.Quantum.Intrinsic;
+
+
+    @Test("QuantumSimulator")
+    operation AllocateQubit() : Unit {
+        
+        using (q = Qubit()) {
+            Assert([PauliZ], [q], Zero, "Newly allocated qubit must be in |0> state.");
+        }
+        
+        Message("Test passed.");
+    }
+}
