diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..65932d2e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+# Matches multiple files with brace expansion notation
+# Set default charset
+[*.{js,ts,less}]
+charset = utf-8
+indent_style = space
+indent_size = 4
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..86bddc9f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.vs
+.idea
+node_modules
+npm-debug.log
+dist/
+*.crx
+*.pem
+build/
+package-lock.json
diff --git a/bitwarden-desktop.sln b/bitwarden-desktop.sln
new file mode 100644
index 00000000..91aec424
--- /dev/null
+++ b/bitwarden-desktop.sln
@@ -0,0 +1,38 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "bitwarden-desktop", ".", "{A4DE5293-DB47-41D1-8890-7C67B83F663C}"
+ ProjectSection(WebsiteProperties) = preProject
+ TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
+ Debug.AspNetCompiler.VirtualPath = "/localhost_4405"
+ Debug.AspNetCompiler.PhysicalPath = "."
+ Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_4405\"
+ Debug.AspNetCompiler.Updateable = "true"
+ Debug.AspNetCompiler.ForceOverwrite = "true"
+ Debug.AspNetCompiler.FixedNames = "false"
+ Debug.AspNetCompiler.Debug = "True"
+ Release.AspNetCompiler.VirtualPath = "/localhost_4405"
+ Release.AspNetCompiler.PhysicalPath = "."
+ Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_4405\"
+ Release.AspNetCompiler.Updateable = "true"
+ Release.AspNetCompiler.ForceOverwrite = "true"
+ Release.AspNetCompiler.FixedNames = "false"
+ Release.AspNetCompiler.Debug = "False"
+ VWDPort = "4405"
+ SlnRelativePath = "."
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A4DE5293-DB47-41D1-8890-7C67B83F663C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A4DE5293-DB47-41D1-8890-7C67B83F663C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..c993a2a8
--- /dev/null
+++ b/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "bitwarden",
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "webpack --config webpack.dev.js",
+ "dev:watch": "webpack --config webpack.dev.js --watch",
+ "lint": "tslint src/**/*.ts || true",
+ "lint:fix": "tslint src/**/*.ts --fix"
+ },
+ "devDependencies": {
+ "clean-webpack-plugin": "^0.1.17",
+ "copy-webpack-plugin": "^4.2.0",
+ "css-loader": "^0.28.7",
+ "extract-text-webpack-plugin": "^3.0.1",
+ "file-loader": "^1.1.5",
+ "font-awesome": "4.7.0",
+ "html-loader": "^0.5.1",
+ "html-webpack-plugin": "^2.30.1",
+ "less": "^3.0.0-alpha.3",
+ "less-loader": "^4.0.5",
+ "style-loader": "^0.19.0",
+ "ts-loader": "^3.0.5",
+ "tslint": "^5.8.0",
+ "tslint-loader": "^3.5.3",
+ "typescript": "^2.5.3",
+ "webpack": "^3.8.1",
+ "webpack-merge": "^4.1.0"
+ },
+ "dependencies": {
+ "@angular/animations": "5.2.0",
+ "@angular/common": "5.2.0",
+ "@angular/compiler": "5.2.0",
+ "@angular/core": "5.2.0",
+ "@angular/forms": "5.2.0",
+ "@angular/http": "5.2.0",
+ "@angular/platform-browser": "5.2.0",
+ "@angular/platform-browser-dynamic": "5.2.0",
+ "@angular/router": "5.2.0",
+ "@angular/upgrade": "5.2.0",
+ "core-js": "^2.4.1",
+ "rxjs": "^5.5.6",
+ "zone.js": "^0.8.19",
+ "@bitwarden/jslib": "git+https://github.com/bitwarden/jslib.git"
+ }
+}
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
new file mode 100644
index 00000000..d180239c
--- /dev/null
+++ b/src/app/app.component.ts
@@ -0,0 +1,15 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'my-app',
+ styles: [''],
+ template: `
+
+
The App Lives!
+
{{ message }}
+
+ `,
+})
+export class AppComponent {
+ message = 'This is the sample message.';
+}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
new file mode 100644
index 00000000..6da4fbdc
--- /dev/null
+++ b/src/app/app.module.ts
@@ -0,0 +1,12 @@
+import 'zone.js/dist/zone';
+
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [BrowserModule],
+ declarations: [AppComponent],
+ bootstrap: [AppComponent],
+})
+export class AppModule { }
diff --git a/src/app/main.ts b/src/app/main.ts
new file mode 100644
index 00000000..2470c959
--- /dev/null
+++ b/src/app/main.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 00000000..90c978b3
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+ bitwarden
+
+
+
+
+
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 00000000..331f7ac8
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "moduleResolution": "node",
+ "noImplicitAny": true,
+ "experimentalDecorators": true,
+ "module": "es6",
+ "target": "ES2016",
+ "allowJs": true,
+ "sourceMap": true,
+ "types": [],
+ "baseUrl": ".",
+ "paths": {
+ "jslib/*": [ "node_modules/@bitwarden/jslib/src/*" ]
+ }
+ },
+ "exclude": [
+ "node_modules",
+ "dist",
+ "build"
+ ]
+}
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 00000000..b6d55716
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,53 @@
+{
+ "extends": "tslint:recommended",
+ "rules": {
+ "align": [ true, "statements", "members" ],
+ "ban-types": {
+ "options": [
+ [ "Object", "Avoid using the `Object` type. Did you mean `object`?" ],
+ [ "Boolean", "Avoid using the `Boolean` type. Did you mean `boolean`?" ],
+ [ "Number", "Avoid using the `Number` type. Did you mean `number`?" ],
+ [ "String", "Avoid using the `String` type. Did you mean `string`?" ],
+ [ "Symbol", "Avoid using the `Symbol` type. Did you mean `symbol`?" ]
+ ]
+ },
+ "member-access": [ true, "no-public" ],
+ "member-ordering": [
+ true,
+ {
+ "order": [
+ "public-static-field",
+ "public-static-method",
+ "protected-static-field",
+ "protected-static-method",
+ "private-static-field",
+ "private-static-method",
+ "public-instance-field",
+ "protected-instance-field",
+ "private-instance-field",
+ "public-constructor",
+ "protected-constructor",
+ "private-constructor",
+ "public-instance-method",
+ "protected-instance-method",
+ "private-instance-method"
+ ]
+ }
+ ],
+ "no-empty": [ true, "allow-empty-catch" ],
+ "object-literal-sort-keys": false,
+ "object-literal-shorthand": [ true, "never" ],
+ "prefer-for-of": false,
+ "quotemark": [ true, "single" ],
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-module",
+ "check-operator",
+ "check-preblock",
+ "check-separator",
+ "check-type"
+ ]
+ }
+}
diff --git a/webpack.common.js b/webpack.common.js
new file mode 100644
index 00000000..cd7602f2
--- /dev/null
+++ b/webpack.common.js
@@ -0,0 +1,67 @@
+const path = require('path');
+const webpack = require('webpack');
+const CleanWebpackPlugin = require('clean-webpack-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+
+const isVendorModule = (module) => {
+ if (!module.context) {
+ return false;
+ }
+
+ const nodeModule = module.context.indexOf('node_modules') !== -1;
+ const bitwardenModule = module.context.indexOf('@bitwarden') !== -1;
+ return nodeModule && !bitwardenModule;
+};
+
+module.exports = {
+ entry: {
+ 'app': './src/app/main.ts'
+ },
+ module: {
+ rules: [
+ {
+ test: /\.ts$/,
+ enforce: 'pre',
+ loader: 'tslint-loader'
+ },
+ {
+ test: /\.tsx?$/,
+ use: 'ts-loader',
+ exclude: /node_modules\/(?!(@bitwarden)\/).*/
+ },
+ {
+ test: /\.(html)$/,
+ loader: 'html-loader'
+ },
+ ]
+ },
+ plugins: [
+ new CleanWebpackPlugin([
+ path.resolve(__dirname, 'build/*')
+ ]),
+ new webpack.optimize.CommonsChunkPlugin({
+ name: 'app/vendor',
+ chunks: ['app'],
+ minChunks: isVendorModule
+ }),
+ new HtmlWebpackPlugin({
+ template: './src/index.html',
+ filename: 'index.html',
+ chunks: ['app/vendor', 'app']
+ }),
+ new CopyWebpackPlugin([
+
+ ])
+ ],
+ resolve: {
+ extensions: ['.tsx', '.ts', '.js'],
+ alias: {
+ jslib: path.join(__dirname, 'node_modules/@bitwarden/jslib/src')
+ }
+ },
+ output: {
+ filename: '[name].js',
+ path: path.resolve(__dirname, 'build')
+ }
+};
diff --git a/webpack.dev.js b/webpack.dev.js
new file mode 100644
index 00000000..b2ff1b57
--- /dev/null
+++ b/webpack.dev.js
@@ -0,0 +1,24 @@
+const merge = require('webpack-merge');
+const common = require('./webpack.common.js');
+
+module.exports = merge(common, {
+ devtool: 'inline-source-map',
+ module: {
+ rules: [
+ {
+ test: /\.less$/,
+ use: [
+ {
+ loader: 'style-loader'
+ },
+ {
+ loader: 'css-loader',
+ },
+ {
+ loader: 'less-loader',
+ }
+ ]
+ }
+ ]
+ }
+});